微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决为什么像Collections类中的sort这样的方法不在List接口中?

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

已更新

当我进行全球研究并阅读了这篇文章的答案时,我不得不说(鸟瞰图): 有人(我提到@ dan,@ WJS,@ cdalxndr)在本文中以sort方法为例说,因为ArrayList和LinkedList的排序可以用相同的方式完成,所以我们只能实现一次编写。因此(我说)我们可以将代码放入List接口中,但是直到Java 7之前,我们都无法在接口主体中实现任何实现,并且一次编写该接口的唯一方法是在Utility类中实现。但是由于Java 8接口具有“认”方法功能。 Java团队利用此功能在接口级别上实现了sort方法的实现,并且该方法可以由ArrayList和LinkedList使用(认情况下,如果类未覆盖它)

解决方法

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

开发人员希望将列表算法(排序,二进制搜索等)与容器逻辑(添加,删除等)分开,以便将算法放入实用程序类Collections中。

,

在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所代表的Collections.sort方法,从而产生无限循环(或更确切地说,是递归)。

尽管如此,sort方法已被添加到List界面中,因为具有直接的好处。与static实用工具类中的Collections方法不同,default方法可以被覆盖。对于最常用的列表类型ArrayListVectorArray.asList(…)返回的实现,已经完成了此操作。由于所有这些实现都由数组支持,因此重写方法可以直接使用支持数组委托给Arrays.sort,而default实现则可以使用列表内容的临时副本。

值得注意的是,Collections中的这些方法最初似乎是基于这样的假设,即这些算法适用于所有类型的实现,但并不成立。在引入Collection API之后的两个版本中,引入了RandomAccess标记接口,以区分两个根本不同的列表实现类别,因此静态方法可以分支到基于它的两个替代算法。

每当我们必须基于正在操作的类进行分支时,我们都可以质疑抽象,并说我们可以使用类型本身上的可重写方法来做得更好,但是如上所述,历史原因是设计,仍然有理由在向接口添加方法时要小心。

,

自Java 8以来,有选项,只需要您定义(或使用预定义的比较器)即可。

下面的虚拟示例:

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

    list.sort(Comparator.naturalOrder());

但是显然,对于用户来说,它的处理方式与Collections util中的处理方式不同(尽管我确实相信Collections实现也可以使用此类比较器或类似方法进行包装)。

,

因为没有必要。以下所有扩展Collection

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

因此,您要提倡的是,每个接口都为Collections中的每个方法提供完全相同的实现,或者也许是一种便捷方法。恕我直言,这就是一种代码膨胀。在前一种情况下,如果发现改进,则需要更改多个实现。

我知道他们在sort界面中添加了List,也许是因为这是一个普遍的要求。但是使用Collections.sort进行排序我从来没有遇到问题。我可能不知道其他原因。

但是我倾向于认为CollectionsMath类非常相似。 DoubleInteger没有重复的数学函数。与Math类似,Collectionsutility,它提供了可供相关类使用的各种静态方法。当然,Math类不在Double或Integer等hierarchy中,但是其用法非常相似。

,

与Java API的许多其他部分一样,Collections Framework(主要是Josh Bloch的设计师,而在Sun Microsystems工作时)的设计者也着眼于该语言的长寿。 Java将API的维持和发展概念直接并入带有@deprecated标签的文档所支持的语法中。 特别是,他们预计,在发现额外的“容器”操作以添加到CollectionList接口之前,很长一段时间内可能会开发出更多的排序和搜索算法。

他们深知,对接口的更改会给开发团队提出升级要求。升级要求减慢了Sun Microsystems希望团队能够轻松吸收的修补程序和改进的采用。将用于分类和搜索的新方法结合到接口中将极大地阻碍该目标。给选择升级到Java语言最新版本的团队带来不必要的负担。相反,他们明智地选择将这些实用程序方法分流到静态实用程序类。

与Java 8的List.sort(..)一样,我只能猜测Oracle感受到了行业和其他语言的压力,这些语言将这些通用操作直接集成到其集合中。但是,将这些实用程序与集合分开放置可以最大程度地减少对直接实现其接口的人员的采用要求。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?