(For一个可变列表,你还需要set)。这些正是在AbstractList中仍然是抽象的。因此,所有其他方法都是相当“方便”的方法,可以基于这两种方法规范地实现。在这方面,我认为the answer 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);
}
}
}
7条答案
按热度按时间am46iovg1#
为什么Java中没有
List.reverse()
方法?因为有一个
Collections.reverse(List)
方法。因为API设计者认为强制 * 每个 *
List
实现1实现一个在99.9%的时间里没有使用的方法2是一个坏主意。这可以通过使方法“可选”来解决,但这也有缺点;例如运行时异常。因为对于某些类型的列表(例如流 Package 器/适配器),实现就地反向将是有问题的。它通过要求列表被具体化来改变列表的内存使用特性。
还要注意,
Collection
提供的reverse()
的通用实现(源代码)使用set
交换元素。对于标准列表类型,它接近于最优。@shmosel评论:
我假设OP在问为什么它没有像List.sort()那样被添加为默认方法。
好观点。可能99.9%的论点适用。请记住,这只会帮助使用Java 8或更高版本编译器构建的代码库的人。
1 -这包括您的代码库和第三方库中的实现。
2 - 86%的统计数据是为了戏剧效果而制作的:-)
xt0899hw2#
出于同样的原因,
fill
和rotate
和shuffle
和swap
以及无限多可能的列表函数没有在List
接口中声明。它们不是“列表”抽象的一部分;相反,它们可以在抽象之上实现。一旦
List
实现了List
接口中已有的方法,就可以在List
抽象之上编写reverse
函数,而无需了解特定的List
实现。因此,强制每个实现List
的类提供reverse
(以及fill
、rotate
、shuffle
、swap
等)的自定义实现是没有意义的。2lpgd9683#
注意:这个问题是"Why does the Collections class contain standalone (static) methods, instead of them being added to the List interface?"的一个非常特殊的情况-甚至可以认为是重复的。除此之外,争论每个方法的决策背后的原因是阅读茶叶,没有人能说出
reverse
方法的特定情况下的设计决策的“原因”(直到,也许Josh Bloch在这里发布了答案)。有趣的是,这是一个点,没有涵盖在Java Collections API Design FAQ...其他一些答案乍看起来似乎很有说服力,但也提出了其他问题。特别是,他们中的一些人根本没有给予设计决策的原因。即使有其他方法来模拟某个方法的行为,或者当一个方法“99.9%的时间”都没有被使用时,在接口中包含它仍然是有意义的。
查看
List
接口,您会注意到您基本上可以基于以下两个方法实现all**方法:T get(int index)
int size()
(For一个可变列表,你还需要
set
)。这些正是在AbstractList
中仍然是抽象的。因此,所有其他方法都是相当“方便”的方法,可以基于这两种方法规范地实现。在这方面,我认为the answer Sam Estep包含了一个重要的观点:人们可以争论实现几十种其他方法。当然,这样做肯定有很好的理由。看看Collections#reverse(List)
的实际实现:这里的
REVERSE_THRESHOLD
和RandomAccess
是什么?说真的,如果我觉得有必要引入像RandomAccess
这样的标记接口,我会强烈质疑我的设计。每当你有一个像那么这是一个强的迹象,表明这实际上应该是一个多态方法,应该相应地为
Special
类型实现。所以,是的,将
reverse
方法拉到接口中以允许多态实现是合理的。这同样适用于fill
rotate
,shuffle
,swap
,sort
等。类似地,可以引入一个静态方法,如它提供了现在用
Collection#containsAll
方法所做的事情。但总的来说:设计师们选择了一套他们认为合适的方法。省略某些方法的原因之一可能是the talk about "How to Design a Good API & Why it Matters" by Joshua Bloch的底线之一,Java Collections API的核心设计者之一:当有疑问时,离开它
有趣的是,在所有多态实现(通过
List
接口中的方法)可能是合理的方法中,一个实际上找到了进入接口的方法,使用Java 8default
方法:List#sort()
。也许其他的,像reverse
,将在以后添加...qnyhuwrf4#
因为
Collection
是一个实用类,它实际上是基于SOLID原则之一:S -单一责任原则
这个原则指出,如果我们有2个理由来改变一个类,我们必须将功能分成两个类。
你有一个扮演某种角色的类,如果你需要操作内部数据,你需要创建一些子类,它将扮演另一个角色。
0qx6xfy65#
如果你需要
list.reverse()
,你需要使用Eclipse Collections,当你可以只使用list.reverseThis()
时,请参阅this。在JDK列表中,很多方法(如sort,max,min)没有添加。这是两种不同的API设计方式:
1.只有最常用的方法和Utility类-> JDK集合,缺点:需要使用像Collections这样的Utility类,
ljo96ir56#
我相信
why
的问题已经得到了回答,但这里有一个问题-List.reversed
将从Java 21(发布日期2023年9月19日)开始提供:**注意:**返回此集合的逆序视图。
JEP 431: Sequenced Collections中的其他详细信息。
jrcvhitl7#
Reverse在Collections中定义(带有额外的(s))。这不是集合层次结构的一部分,而是作为实用程序类的一部分,可用于不同的列表。
反转列表并不是定义列表的关键部分,所以它不在接口中,单独给出。如果在接口中定义,每个人都必须实现它,这可能不适合所有人。
集合的创建者也可以在List层次结构中构建它,(因为大多数列表派生都有一个抽象类,他们可以把它放在任何抽象类中)。然而,为了简化每个人的生活,将其保留在单个实用程序类中是有意义的,这样我们就不必弄清楚在哪个类中查找所有与集合相关的实用程序函数。