为什么像 `Collections` 类中的 `sort` 等方法不在 `List` 接口中?

huangapple go评论69阅读模式
英文:

Why methods like sort in Collections class are not in List interface?

问题

Class Collections具有一些静态方法,用于操作诸如List之类的集合。例如,排序方法(Collections.sort(list))。我不明白为什么Java规范会创建另一个类来承载排序方法(以及诸如binarySearch之类的其他方法),而不是由List接口和具体子类(如ArrayList和LinkedList)来实现这些方法。

更新

经过我进行的全局研究,并阅读了这篇帖子中的答案,我不得不说(总览全局):
在这篇帖子中,有些人(我提到了@dan,@WJS,@cdalxndr)使用排序方法作为例子,因为ArrayList和LinkedList的排序可以以相同的方式完成,所以我们可以只实现一次代码。因此(我认为),我们可以将代码放在List接口中,但是在Java 7之前,我们无法在接口的主体中放入任何实现,唯一的方法是在实用程序类中实现。但自从Java 8以来,接口具有“默认”方法的功能。Java团队利用了这个特性,在接口级别上实现了排序方法,并且ArrayList和LinkedList可以使用该方法(如果类没有对其进行覆盖,则使用默认方法)。

英文:

Class Collections has some static methods as utilities to manipulate collections like List. For example the sort method (Collections.sort(list)). I do not understand why Java specs made another class to host the sort method (and all the others like binarySearch) and not to List interface and concrete subclasses like ArrayList and LinkedList implement these methods.

UPDATED

As I made a global research and read the answers from this post I have to say that (bird's eye view):
Some people (I mention @dan,@WJS,@cdalxndr) said in this post, using the sort method as example, that because the sort of ArrayList and LinkedList can be done with the same way then we can implemented writing only one time. So (I say) we could put the code in the List interface but until Java 7 we couldn't put any implementation in interface's body and the only way to write it one time was to implemented in utility class. But since Java 8 interfaces has the feature of "default" method. And Java team took advantage of this feature to have sort method implementation in interface level and that method can be used by ArrayList and LinkedList (as default if the classes do not override it)

答案1

得分: 2

排序是一种算法,List是一个容器。

开发者希望将列表算法(排序、二分搜索等)与容器逻辑(添加、移除等)分开,因此将这些算法放在了实用类Collections中。

英文:

Sorting is an algorithm, and List is a container.

The developers wanted to separate list algorithms (sort, binary search, etc) from container logic (add, remove, etc) so they put the algorithms to the utility class Collections.

答案2

得分: 2

在Java 8之前,接口无法拥有defaultstatic方法,因此,添加到接口的每个方法都需要被实现接口的所有类实现。即使您在支持类中提供了有用的实现,实现类仍需要至少一个委派方法。

因此,除非您希望强制所有实现从某个提供这些方法的抽象基类继承,否则您必须小心您添加到接口中的内容。

即使使用了default方法,您仍然需要小心,以避免在实现类的命名空间中添加过多的方法。这也可能是为什么并非所有操作都在Java 8中改为了default方法的原因:

虽然向接口添加default方法的方式不太侵入,因为它不会在已有的实现类中创建需要实现的方法,但它仍可能与实现类的具体方法发生冲突,而这些方法在之前的版本中没有实现接口方法。

想象一下,在Java 8之前的自定义List实现中,它提供了一个有用的void sort(Comparator c)实例方法,只是委托给了Collections.sort(this, c);。这在Java 8之前是可以工作的,虽然不会提高性能,但允许编写list.sort(c);。而在今天,这个方法会无意中覆盖掉同名且类型相同的default方法,而这个default方法会委托给Collections.sort,从而产生无限循环(或者说递归)。

尽管如此,sort方法已被添加到List接口中,因为它带来了直接的好处。与Collections实用类中的static方法不同,default方法是可以被重写的。这已经针对最常用的列表类型(ArrayListVector以及Array.asList(…)返回的实现)完成了。由于所有这些实现都由数组支持,重写的方法可以直接使用支持数组来委托给Arrays.sort,而default实现将使用列表内容的临时副本进行操作。

还值得注意的是,Collections中的这些方法最初似乎是基于这样一个假设而构建的,即这些算法适用于所有类型的实现,但事实并非如此。在引入集合API后的两个版本中,引入了RandomAccess标记接口,以区分两种基本不同的列表实现类别,使得静态方法可以根据它选择两种不同的算法。

每当我们必须根据我们正在操作的类进行分支时,我们可能会质疑抽象,并说我们最好在类型本身上拥有可重写的方法,但正如上面所解释的,设计存在历史原因,并且仍然需要小心地向接口中添加方法。

英文:

Before Java 8, interfaces could not have default nor static methods, hence, every method added to the interface needed to be implemented by all classes implementing the interface. Even when you provided a helpful implementation in a support class, the implementing class needed at least a delegating method.

So, unless you wanted to force all implementations to inherit from some abstract base class providing those methods, you had to be careful with what you add to the interface.

Even with the default methods, you have to be careful, to avoid polluting the name space of an implementing class with too many methods. This might also be the reason why not every operation has been retrofitted to default methods in Java 8:

While adding a default method to an interface is less intrusive, as it does not create the need to implement it in already existing implementation classes, it may still cause a clash with a concrete method of the implementation class that didn’t implement an interface method in the previous version.

Just imagine a custom List implementation in pre-Java 8 times that provided a helpful void sort(Comparator c) instance method just delegating to Collections.sort(this, c);. That worked before Java 8, not improving the performance, but allowing to write list.sort(c);. Nowadays, this method would unintentionally happen to override the default method with the same name and type, to which Collections.sort will delegate, producing an infinite loop (or rather, recursion).

Still, the sort method has been added to the List interface, because of the immediate benefits. Unlike the static methods in the Collections utility class, the default method can be overridden. This has been done for the most commonly used list types, ArrayList, Vector, and the implementation returned by Array.asList(…). Since all those implementations are backed by an array, the overriding method can delegate to Arrays.sort using the backing array directly, whereas the default implementation will work with a temporary copy of the list contents.

It’s also worth noting that those methods in Collections seem to be originally based on the assumption that those algorithms were suitable to all kind of implementations, which didn’t hold. Two releases after the introduction of the Collection API, the RandomAccess marker interface was introduced, to tell two fundamentally different list implementation categories apart, so the static method could branch to two alternative algorithms based on it.

Whenever we have to branch based on the class we’re operating on, we could question the abstraction and say that we might be better off with overridable methods on the type itself, but as explained above, there are historical reasons for the design and there still are reasons to be careful with adding methods to the interface.

答案3

得分: 0

自 Java 8 开始,有一种类似的选项,只需要您定义(或使用预定义的比较器)。

以下是一个示例:

List<Integer> list = new ArrayList();
list.addAll(List.of(1, 5, 4, 3, 6, 8, 9, 2));

list.sort(Comparator.naturalOrder());

但显然,作为用户,您的操作方式与在 Collections 工具中不同(尽管我确信 Collections 的实现也会围绕使用类似的比较器进行包装或类似的操作)。

英文:

There is sort of an option since Java 8, just requires you to define (or use predefined comparator).

Dummy example below:

    List&lt;Integer&gt; list = new ArrayList();
    list.addAll(List.of(1,5,4,3,6,8,9,2));

    list.sort(Comparator.naturalOrder());

But obviously it is not done the same way to you as an user as it is in Collections util (although I do believe that Collections implementation also wraps around using such comparator or something like it).

答案4

得分: 0

因为这并非必要。以下所有的扩展都是Collection

BeanContext、BeanContextServices、BlockingDeque<E>、BlockingQueue<E>、
Deque<E>、EventSet、List<E>、NavigableSet<E>、Queue<E>、Set<E>、
SortedSet<E>、TransferQueue<E>

所以您所主张的是每个接口都提供完全相同的实现,或者可能是Collections的每个方法都提供一个便捷方法。在我看来,这将是一种代码膨胀的形式。在前一种情况下,如果发现改进,将需要更改多个实现。

我知道他们在List接口中添加了sort,可能是因为这是一个非常常见的需求。但是我从未在使用Collections.sort进行排序时遇到问题。可能还有其他我不知道的原因。

但我倾向于将Collections视为与Math类非常相似的东西。
DoubleInteger没有重复的数学函数。类似于MathCollections是一个实用工具类,提供了许多可被相关类使用的静态方法。当然,Math类不在DoubleInteger等层次结构中,但其使用方式非常相似。

英文:

Because it isn't necessary. All the following extend Collection

BeanContext, BeanContextServices, BlockingDeque&lt;E&gt;, BlockingQueue&lt;E&gt;,&lt;br&gt;
Deque&lt;E&gt;, EventSet, List&lt;E&gt;, NavigableSet&lt;E&gt;, Queue&lt;E&gt;, Set&lt;E&gt;,&lt;br&gt;
SortedSet&lt;E&gt;, TransferQueue&lt;E&gt;

So what you are advocating is that each interface provide the exact same implementation or perhaps a convenience method to each method in Collections. That would be, imho, a form of code bloat. In the former case, it would require changing multiple implementations if improvements were discovered.

I know they added sort to the List interface, perhaps because it is such a common requirement. But I never had a problem using Collections.sort to do sorting. There may be other reasons of which I am unaware.

But I tend to think of Collections as very similar to the Math class.
Double and Integer don't have duplicate math functions. Similar to Math, Collections is a utility that offers a variety of static methods that are usable by related classes. Granted, the Math class is not in the Double or Integer, etc hierarchy, but its use is very similar.

答案5

得分: 0

设计者们对于Java的集合框架(主要是Josh BlochSun Microsystems工作期间)以及Java API的许多其他部分都考虑了语言的持久性。Java将API的持续维护和演进的概念直接融入了文档支持的语法中,通过@deprecated标签来实现。具体而言,他们预见到在往年开发出额外的排序和搜索算法之前,很可能会开发出额外的“容器”操作,以添加到CollectionList接口中。

他们非常清楚,对接口进行更改会对开发团队产生升级要求。升级要求会减缓开发团队吸收修复和改进的速度,而Sun Microsystems希望团队能够轻松吸收这些改变。将新的排序和搜索方法纳入接口中会严重阻碍这一目标,给选择升级到Java语言的最新版本的团队带来不必要的负担。相反,他们明智地选择将这些实用方法移到一个静态实用工具类中。

与Java 8的List.sort(..)一样,我只能猜测Oracle感受到了行业的压力,以及其他语言将这些常见操作直接纳入其集合本身。然而,将这些实用工具与集合分开,最大程度地减少了对直接实现接口的人所施加的采用要求。

英文:

The designers of the Collections Framework (primarily Josh Bloch while working at Sun Microsystems), as with many other sections of the Java API, had an eye to the longevity of the language. Java incorporates the notion of sustainment and evolution of APIs directly into the syntax supported by the documentation with the @deprecated tag. Specifically, they anticipated additional sorting and searching algorithms would likely be developed over the years long before additional "container" operations would be discovered to add to the Collection, and List interfaces.

They knew very well changes to the interfaces would impose upgrade requirements on development teams to deal with. Upgrade requirements slows the adoption of fixes and improvements that Sun Microsystems wanted teams to be able to absorb with ease. Incorporating new methods for sorting and searching into the interface would greatly impede that goal; placing an unnecessary burden on teams choosing to upgrade to the latest version of the Java language. Instead, they wisely chose to shunt these utility methods to a static utility class.

As with Java 8's List.sort(..), I can only guess Oracle felt the pressures of the industry and other languages incorporating these common operations right into their collection itself. However, keeping these utilities separate from the collection minimizes adoption requirements they would impose on those who directly implement their interfaces.

huangapple
  • 本文由 发表于 2020年10月14日 20:10:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/64352962.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定