为什么Java中没有“List.reverse()”方法?

pbwdgjma  于 2023-09-29  发布在  Java
关注(0)|答案(7)|浏览(90)

在Java中,要反转List中的元素,我需要用途:

Collections.reverse(list)

我只是想知道为什么Java没有在List接口中实现reverse方法,这样我就可以像这样做就地反转:

list.reverse()

有人对此有什么想法吗?

am46iovg

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%的统计数据是为了戏剧效果而制作的:-)

xt0899hw

xt0899hw2#

出于同样的原因,fillrotateshuffleswap以及无限多可能的列表函数没有在List接口中声明。它们不是“列表”抽象的一部分;相反,它们可以在抽象之上实现。
一旦List实现了List接口中已有的方法,就可以在List抽象之上编写reverse函数,而无需了解特定的List实现。因此,强制每个实现List的类提供reverse(以及fillrotateshuffleswap等)的自定义实现是没有意义的。

2lpgd968

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)的实际实现:

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_THRESHOLDRandomAccess是什么?说真的,如果我觉得有必要引入像RandomAccess这样的标记接口,我会强烈质疑我的设计。每当你有一个像

void doSomethingWith(Type x) {
    if (x instanceof Special) doSomethingSpecial((Special)x);
    else doSomethingNormal(x);
}

那么这是一个的迹象,表明这实际上应该是一个多态方法,应该相应地为Special类型实现。
所以,是的,将reverse方法拉到接口中以允许多态实现是合理的。这同样适用于fillrotateshuffleswapsort等。类似地,可以引入一个静态方法,如

Collections.containsAll(containing, others);

它提供了现在用Collection#containsAll方法所做的事情。但总的来说:设计师们选择了一套他们认为合适的方法。省略某些方法的原因之一可能是the talk about "How to Design a Good API & Why it Matters" by Joshua Bloch的底线之一,Java Collections API的核心设计者之一:

当有疑问时,离开它

有趣的是,在所有多态实现(通过List接口中的方法)可能是合理的方法中,一个实际上找到了进入接口的方法,使用Java 8 default方法:List#sort()。也许其他的,像reverse,将在以后添加...

qnyhuwrf

qnyhuwrf4#

因为Collection是一个实用类,它实际上是基于SOLID原则之一:

S -单一责任原则

这个原则指出,如果我们有2个理由来改变一个类,我们必须将功能分成两个类。
你有一个扮演某种角色的类,如果你需要操作内部数据,你需要创建一些子类,它将扮演另一个角色。

0qx6xfy6

0qx6xfy65#

如果你需要list.reverse(),你需要使用Eclipse Collections,当你可以只使用list.reverseThis()时,请参阅this。在JDK列表中,很多方法(如sort,max,min)没有添加。
这是两种不同的API设计方式:

  1. Collection -> rich collection -> Eclipse Collections中的很多方法,缺点:List中很多很少使用的方法,
    1.只有最常用的方法和Utility类-> JDK集合,缺点:需要使用像Collections这样的Utility类,
ljo96ir5

ljo96ir56#

我相信why的问题已经得到了回答,但这里有一个问题-List.reversed将从Java 21(发布日期2023年9月19日)开始提供:

System.out.println(List.of(1, 2, 3).reversed()); // [3, 2, 1]

**注意:**返回此集合的逆序视图。

JEP 431: Sequenced Collections中的其他详细信息。

jrcvhitl

jrcvhitl7#

Reverse在Collections中定义(带有额外的(s))。这不是集合层次结构的一部分,而是作为实用程序类的一部分,可用于不同的列表。
反转列表并不是定义列表的关键部分,所以它不在接口中,单独给出。如果在接口中定义,每个人都必须实现它,这可能不适合所有人。
集合的创建者也可以在List层次结构中构建它,(因为大多数列表派生都有一个抽象类,他们可以把它放在任何抽象类中)。然而,为了简化每个人的生活,将其保留在单个实用程序类中是有意义的,这样我们就不必弄清楚在哪个类中查找所有与集合相关的实用程序函数。

相关问题