Java 是否具有与 Python 的 ArrayLists list.sorted() 方法等效的方法?

Does Java have an equivalent to Python's list.sorted() method for ArrayLists?

我知道我可以在 Java 中的 ArrayList 上调用 Collections.sort(),但我目前正在尝试重载构造函数,而在第二个构造函数中我想调用第一个构造函数。但是,我想传递一个排序列表作为参数之一,但是 Java 不会让我在排序列表后调用 this() - 它需要 this() 作为第一行。我可以将 Collections.sort(myList) 放在构造函数中,但我不知道此方法是否 return 是排序列表,但理想情况下我想 return 排序列表而不改变原始列表.

这是我的代码(适用于您在学校或大学中找到的一段时间),包括错误:

public class Period {

    private String name;
    private LocalDateTime start;
    // duration in seconds
    private int duration;
    private Lecturer lecturer;
    private ArrayList<Demonstrator> dems;
    private ArrayList<Skill> skills;
    
    public Period(String name, LocalDateTime start, int duration, Lecturer lecturer) {
        this.name = name;
        this.start = start;
        this.duration = duration;
        this.lecturer = lecturer;
        this.dems = new ArrayList<>();
        this.skills = new ArrayList<>();
    }
    
    public Period(String name, ArrayList<AvailBlock> blocks, Lecturer lecturer) {
        // this line is illegal, but shows you what I'm trying to do.
        Collections.sort(blocks);
        this(name, blocks.get(0).getStart(), ( blocks.size() * AvailBlock.LENGTH ), lecturer);
    }
    ...
}

AvailBlock class 有一个作为 LocalDateTime 对象的开始时间,以及一个固定的持续时间(目前为 15 分钟)。我正在尝试选择创建一个持续时间以秒为单位的时间段,或者只是传入一个 AvailBlock 对象列表并让它确定时间段何时开始以及它应该持续多长时间。

这里是AvailBlockclass的开头:

public class AvailBlock implements Comparable {
    
    // the start time of the slot
    private LocalDateTime start;
    // Length of slots in seconds
    public static final int LENGTH = 900;
    
    public AvailBlock(LocalDateTime start) {
        this.start = start;
    }
    ...
}

创建一个静态工厂方法

作为,我会在静态方法中而不是在构造函数中完成这项工作。最好让构造函数完全简单。

此外,构造函数的第一行必须是对超级构造函数的隐式或显式调用。因此我们无法在调用 this( … ) 之前获得诸如您对 Collections.sort 的调用之类的代码。这一定是您在说“// 这条线是非法的,但向您展示了我正在尝试做的事情”时提到的问题。 Java 第一行作为超级构造函数调用的语言要求是使用静态工厂方法解决问题的另一个原因。

我会根据 java.time naming conventions.

将方法命名为 from
public static Period from ( … )
{
    …
    return new Period( … ) ;
}

用法:

Period p = Period.from( … ) ;

复制输入列表

你说:

I could just put Collections.sort(myList) in the constructor, but I don't know if this method returns the sorted list, but ideally I would like to return the sorted list without mutating the original.

排序前复制列表。然后你避免改变原来的。

要进行浅拷贝,您可以将任何 Collection 传递给 ArrayList.

的构造函数

另外注意,既然我们先复制然后排序,你的工厂方法可以接受任何一种List, not just ArrayList. Actually, any kind of Collection

public static Period from ( String name, Collection< AvailBlock > blocks, Lecturer lecturer )
{
    ArrayList< AvailBlock > blocksSorted = new ArrayList<>( blocks ) ;
    Collections.sort( blocksSorted );
    return new Period( name, blocksSorted.get(0).getStart(), ( blocks.size() * AvailBlock.LENGTH ), lecturer ) ;
}

List.copyOf

如果您想要一份不可修改的副本,请将您的列表传递给 List.copyOf


record

顺便说一句,您可能会发现 records feature added to Java 16.

记录是编写 class 的一种简短方式,其主要目的是透明且不可变地传递数据。您只需要声明每个成员字段的类型和名称。编译器隐式创建构造函数、getter、equals & hashCodetoString.

一条记录可以携带一个静态工厂方法,正如我们在解决方案中所需要的那样。

我赞同其他人关于不要在构造函数中做太多事情的评论。但是,如果您 do 想要在不改变原始列表的情况下进行内联排序,流似乎是最自然的方式。您可以很容易地进行排序而不改变原始列表:

blocks.stream().sorted().collect(Collectors.toList())

(...这将 return 一个排序列表,您可以使用内联或分配给变量。)