为什么没有" List.reverse()" Java中的方法?

时间:2016-06-18 12:19:04

标签: java list oop interface

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

Collections.reverse(list)

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

list.reverse()

有没有人对此有任何想法?

6 个答案:

答案 0 :(得分:10)

  

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

因为有Collections.reverse(List)方法。

因为API设计人员认为强制每个 List实现 1 来实现一个未使用99.9%的方法是一个坏主意。时间 2 。这可以通过使方法“可选”来解决,但这也有缺点;例如运行时异常。

因为对于某些类型的列表(例如流包装器/适配器),实现就地反向会有问题。它通过要求对其进行修改来更改列表的内存使用特性。

另请注意,reverse()提供的Collection的通用实现(source code)使用set来交换元素。它接近标准列表类型的最佳值。

@shmosel评论:

  

我假设OP问为什么它没有作为默认方法添加,因为List.sort()是。

好问题。可能99.9%的论点适用。请记住,这只会帮助拥有使用Java 8或更高版本编译器等构建的代码库的人。

1 - 这包括代码库和第三方库中的实现。

2 - 86%的统计数据用于戏剧效果:-)

答案 1 :(得分:6)

出于同样的原因Leaky RELUfill以及rotateshuffle以及无法更多可能的列表函数未在List接口中声明。它们不是“列表”抽象的部分;相反,它们可以在那个抽象的基础上实现

一旦List实现了List接口中已有的方法,reverse函数就可以在List抽象之上编写,而不需要了解特定的List {1}}实施。因此,强制每个实现List的类提供reverse(和fillrotateshuffle,{{1}的自定义实现是毫无意义的。等等。)。

答案 2 :(得分:4)

因为Collection是一个功利主义阶级,实际上是基于documentation原则之一: S - 单一责任原则

  

这个原则指出,如果我们要为一个类改变 2个原因,我们必须将功能分成两个类。

你有一个扮演某个角色的类,如果你需要操作内部数据,你需要创建一些辅助类,这将扮演另一个角色。

答案 3 :(得分:3)

如果您需要list.reverse(),则需要使用Eclipse Collections,当您只使用list.reverseThis()时,请参阅this。在JDK列表中,不添加许多方法(如sort,max,min)。

这是API设计的两种不同方式:

  1. Collection中的很多方法 - >丰富的收藏 - >日食 集合,缺点:List中很多很少使用的方法,
  2. 仅使用最常用的方法和实用程序类 - > JDK     集合,缺点:需要像集合一样使用Utility类,

答案 4 :(得分:3)

注意:这个问题是"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界面,您会发现基本上可以基于另外两个方法实施所有方法:

  • T get(int index)
  • int size()

(对于可变列表,您还需要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方法拉入接口是合理的,以允许多态实现。这同样适用于fill rotateshuffleswapsort等。同样,人们可以引入静态方法,如

Collections.containsAll(containing, others);

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

如有疑问,请将其删除

有趣的是,在多态实现(通过List接口中的方法)可能合理的所有方法中,一个实际上已经进入接口,使用Java 8 default方法:List#sort()。也许其他人,比如reverse,稍后会添加......

答案 5 :(得分:0)

反转在集合中定义(带有额外的(s))。这不是集合层次结构的一部分,而是作为实用程序类的一部分给出,可用于不同的列表。

反转列表不是定义列表的关键部分,因此它不受界面限制并单独给出。如果在界面中定义,每个人都必须实现它,这可能不适合所有人。

集合的制作者也可以在List层次结构中构建它,(因为大多数列表派生之间都有一个抽象类,它们可以将它放在其间的任何抽象类中)。但是,为了简化每个人的生活,将它保存在单个实用程序类中是有意义的,这样我们就不必弄清楚要查找所有与集合相关的实用程序函数的类。