在Java中,要反转List中的元素,我需要使用:
Collections.reverse(list);
Collections.reverse(list)
我只是在想为什么Java没有在List
接口中实现反转方法,这样我就可以像这样进行原地反转:
list.reverse()
有没有人对此有任何想法?
List.reverse()
方法?Collections.reverse(List)
方法取而代之。List
实现都实现一个99.9%的时间都不用的方法是一个坏主意。这可以通过使该方法“可选”来解决,但这也有缺点;例如运行时异常。reverse()
的泛型实现(源代码)使用set
交换元素。对于标准列表类型,它接近最优。List.sort()
一样。List.sort()
一样被添加为默认方法。 - shmosel注意:这个问题是"为什么Collections类包含独立的(静态)方法,而不是将它们添加到List接口中?"的一个非常特定的情况 - 甚至可以认为它是重复的。除此之外,就每个单独方法背后的设计理念进行争论就像读茶叶一样,没有人能够告诉我们关于reverse
方法的设计决策的"原因",直到Josh Bloch在这里发表答案为止。有趣的是,这一点并没有在Java Collections API Design FAQ中涉及...
查看 List
接口,您会注意到基本上可以根据两个其他方法实现所有方法:
T get(int index)
int size()
(对于可变列表,您还需要 set
)。这些正是在 AbstractList
中仍然抽象的方法。因此,所有其他方法都是相对“方便”的方法,可以按照规范基于这两种方法实现。在这方面,我认为 答案Sam Estep 包含了一个重要观点:可以争论要实现数十个其他方法。当然,有很多 好的理由这样做。看一下 Collections#reverse(List)
的实际实现:
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
REVERSE_THRESHOLD
和 RandomAccess
的东西?说真的,如果我觉得需要引入像 RandomAccess
这样的标记接口,我会强烈质疑我的设计。每当你有一个像这样的方法:void doSomethingWith(Type x) {
if (x instanceof Special) doSomethingSpecial((Special)x);
else doSomethingNormal(x);
}
Special
类型进行实现。
所以,将reverse
方法引入接口是有道理的,以允许多态实现。对于fill
、rotate
、shuffle
、swap
、sort
等也同样适用。同样地,可以引入静态方法,例如
Collections.containsAll(containing, others);
Collection#containsAll
方法的功能。但总的来说,设计者选择了一组特定的方法,认为它们是合适的。留出某些方法的原因之一可能可以从Java集合API的核心设计者之一Joshua Bloch在"如何设计一个好的API及其重要性"的演讲中给出的底线之一得到解释:
有趣的是,在所有可以通过List
接口中的方法实现多态(通过方法)的情况下,只有一个方法实际上以Java 8 default
方法的形式出现在接口中:List#sort()
。也许其他方法,例如reverse
,以后会被添加...
Collection
是一个实用类,它基于SOLID原则之一:你有一个扮演某种角色的类,如果你需要操作内部数据,你需要创建一个子类来扮演另一个角色。这个原则指出如果我们有两个理由去更改一个类,我们必须将功能拆分成两个类。
list.reverse()
,你需要使用Eclipse Collections,而当你可以使用list.reverseThis()
时,请参见这里。在JDK列表中,很多方法(如排序、最大值、最小值等)未被添加。List.reversed
将会在Java 21中可用(发布日期为2023年9月19日)。System.out.println(List.of(1, 2, 3).reversed()); // [3, 2, 1]
注意:它返回此集合的逆序view。
有关更多详细信息,请参阅JEP 431:序列化集合。
Reverse(反转)在Collections中被定义(带有额外的“s”)。这不是集合层次结构的一部分,而是作为实用程序类的一部分给出,可以用于不同的列表。
将列表反转并不是定义列表的关键部分,因此它被保留在接口之外并单独给出。如果在接口中定义,每个人都必须实现它,这可能并不适合所有人。
集合的制造商也可以将其构建在List层次结构中(由于大多数列表派生都有一个抽象类在中间,他们可以将其放在任何抽象类中间)。然而,为了简化每个人的生活,将其保留在单个实用程序类中是有意义的,这样我们就不必找出所有与集合相关的实用程序函数所在的类。
Collection.reverse
与List
同时引入(JDK 1.2)以来,设计者的意图很可能是不将其包含在List
接口中,而仅提供一个帮助方法。 - wero