简体   繁体   English

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

[英]Why is there no “List.reverse()” method in Java?

In Java, to reverse elements in a List, I need to use:在 Java 中,要反转 List 中的元素,我需要使用:

Collections.reverse(list)

I was just wondering why Java doesn't implement the reverse method within the List interface so that I could do the in-place reverse like this:我只是想知道为什么 Java 不在List接口中实现 reverse 方法,以便我可以像这样执行就地反向操作:

list.reverse()

Does anyone have any ideas about this?有没有人对此有任何想法?

Why is there no List.reverse() method in Java?为什么 Java 中没有List.reverse()方法?

Because there is a Collections.reverse(List) method instead.因为有一个Collections.reverse(List)方法。

Because the API designers figured it was a bad idea to force every List implementation 1 to implement a method that wasn't used 99.9% of the time 2 .因为 API 设计者认为强制每个List实现1实现一个在 99.9% 的时间都没有使用的方法2是一个坏主意。 This could be addressed by making the method "optional", but that has downsides too;这可以通过使方法“可选”来解决,但这也有缺点; eg runtime exceptions.例如运行时异常。

Because for some kinds of list (stream wrappers / adapters for example) implementing in-place reverse would be problematic.因为对于某些类型的列表(例如流包装器/适配器),实现就地反向将是有问题的。 It changes the memory usage characteristics of the list by requiring it to be reified.它通过要求将列表具体化来更改列表的内存使用特性。

Also note that the generic implementation ( source code ) of reverse() that is provided by Collection uses set to swap elements.另请注意, Collection提供的reverse()的通用实现( 源代码)使用set来交换元素。 It is close to optimal for the standard list types.它接近于标准列表类型的最佳选择。


@shmosel comments: @shmosel 评论:

I assume OP is asking why it wasn't added as a default method, as List.sort() was.我假设 OP 是在问为什么它没有像 List.sort() 那样作为默认方法添加。

Good point.好点。 Possibly the 99.9% argument applies.可能 99.9% 的论点适用。 Bear in mind that this would only help people with a codebase that is built using a Java 8 or later compilers, etc.请记住,这只会帮助那些使用 Java 8 或更高版本编译器等构建的代码库的人。


1 - This includes implementations in your codebase and 3rd-party libraries. 1 - 这包括您的代码库和第 3 方库中的实现。

2 - 86% of statistics are made up for theatrical effect :-) 2 - 86% 的统计数据用于戏剧效果:-)

For the same reason that fill and rotate and shuffle and swap and infinitely more possible list functions aren't declared in the List interface.出于同样的原因, List接口中没有声明fillrotateshuffleswap以及无限更多可能的列表函数。 They're not part of the "list" abstraction;他们不是在“名单”抽象的一部分; rather, they can be implemented on top of that abstraction.相反,它们可以在该抽象之上实现。

Once a List implements the methods already in the List interface, a reverse function can be written on top of the List abstraction without any knowledge of a particular List implementation.一旦List实现了List接口中已有的方法,就可以在List抽象之上编写一个reverse函数,而无需任何特定List实现的知识。 Therefore, it would be pointless to force every class implementing List to provide a custom implementation of reverse (and fill , rotate , shuffle , swap , etc.).因此,强制每个实现List类都提供reverse的自定义实现(以及fillrotateshuffleswap等)是没有意义的。

Because Collection is an utilitarian class, that actually based on one of SOLID principle :因为Collection是一个实用类,它实际上基于SOLID原则之一:
S - Single Responsibility Principle S - 单一职责原则

This principle states that if we have 2 reasons to change for a class, we have to split the functionality in two classes.这个原则指出,如果我们有两个理由改变一个类,我们必须将功能拆分为两个类。

You have a class that play a some role, and if you need to manipulate of inner data you need to create some subsidiary class, that will plays another role.你有一个扮演某种角色的类,如果你需要操作内部数据,你需要创建一些子类,这将扮演另一个角色。

If you need list.reverse() you need to use Eclipse Collections , when you can use just list.reverseThis() , see this .如果您需要list.reverse() ,则需要使用Eclipse Collections ,当您可以仅使用list.reverseThis() ,请参阅 In JDK list, a lot of method (like sort, max, min) does not be added.在 JDK 列表中,很多方法(如 sort、max、min)没有被添加。

It's two different ways of API design:这是两种不同的 API 设计方式:

  1. A lot of method in Collection -> rich collection -> Eclipse Collections, drawback : a lot of rarely used method in List, Collection -> rich collection -> Eclipse Collections 中的很多方法,缺点:List 中很多很少使用的方法,
  2. Only most used method and Utility class -> JDK collection, drawback : need to use Utility class like Collections,只有最常用的方法和实用程序类 -> JDK 集合,缺点:需要像集合一样使用实用程序类,

Note: This question is a very specific case of "Why does the Collections class contain standalone (static) methods, instead of them being added to the List interface?"注意:这个问题是“为什么 Collections 类包含独立(静态)方法,而不是将它们添加到 List 接口中?”的一个非常具体的案例。 - one could even consider is as a duplicate. - 甚至可以认为是重复。 Beyond that, arguing about the reasoning behind the decision for each individual method is reading tea leaves, and nobody can tell " the reason" for the design decision for the particular case of the reverse method (until, maybe Josh Bloch posts an answer here).除此之外,争论为每个方法的决定背后的推理是阅读茶叶,没有人可以告诉了针对的具体情况设计决定“原因,” reverse法(直到,也许乔希布洛赫帖子这里的答案) . Interestingly, this is a point that is not covered in the Java Collections API Design FAQ ...有趣的是, Java 集合 API 设计常见问题解答中没有涵盖这一点......


Some of the other answers seem convincing at the first glance, but raise other questions.其他一些答案乍一看似乎令人信服,但引发了其他问题。 Particularly, some of them don't give a reason for the design decision at all.特别是,其中一些根本没有给出设计决策的理由。 Even if there are other ways to emulate the behavior of a certain method, or when a method is not used "99.9% of all time", it can still make sense to include it in the interface.即使有其他方法可以模拟某个方法的行为,或者当“99.9% 的时间”都没有使用某个方法时,将它包含在界面中仍然有意义。


Looking at the List interface, you will notice that you can basically implement all methods based on two others:查看List接口,您会注意到您基本上可以基于另外两个方法来实现所有方法:

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

(For a mutable list, you also need set ). (对于可变列表,您还需要set )。 These are exactly the ones that are still abstract in AbstractList .这些正是AbstractList中仍然抽象的那些。 So all other methods are rather "convenience" methods that can be implemented canonically, based on these two methods.所以所有其他方法都是相当“方便”的方法,可以基于这两种方法规范地实现。 In this regard, I think that the answer Sam Estep contains an important point: One could argue to implement dozens of other methods.在这方面,我认为Sam Estep 的答案包含一个重要的观点:人们可以争论实施其他数十种方法。 And there would certainly be good reasons to do so.这样做肯定有充分的理由。 Having a look at the actual implementation of Collections#reverse(List) :看看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);
        }
    }
}

What is this REVERSE_THRESHOLD and RandomAccess thing there?那里的REVERSE_THRESHOLDRandomAccess是什么东西? Seriously, if I felt the necessity to introduce a tagging interface like RandomAccess , I would strongly question my design.说真的,如果我觉得有必要引入像RandomAccess这样的标记界面,我会强烈质疑我的设计。 Whenever you have a method like每当你有一个像

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

then this is a strong sign that this should actually be a polymorphic method, which should be implemented accordingly for the Special type.那么这是一个强烈的迹象,表明这实际上应该是一个多态方法,应该为Special类型相应地实现。


So yes, it have been justified to pull the reverse method into the interface, to allow a polymorphic implementation.所以是的,将reverse方法拉入接口中是合理的,以允许多态实现。 The same applies to fill rotate , shuffle , swap , sort and others.这同样适用于fill rotateshuffleswapsort等。 Similarly, one could have introduced a static method like同样,可以引入一个静态方法,如

Collections.containsAll(containing, others);

that offers what is now done with the Collection#containsAll method.它提供了现在使用Collection#containsAll方法所做的事情。 But in general: The designers chose a particular set of methods that they found suitable.但总的来说:设计师选择了一组他们认为合适的特定方法。 One of the reasonings behind leaving out certain methods may be given by one of the bottom lines of the talk about "How to Design a Good API & Why it Matters" by Joshua Bloch , one of the core designers of the Java Collections API: Java Collections API 的核心设计者之一Joshua Bloch 在关于“如何设计一个好的 API 以及为什么它很重要”的演讲中提到了忽略某些方法的原因之一:

When in doubt, leave it out如有疑问,请忽略它

Interestingly, of all the methods for which a polymorphic implementation (via a method in the List interface) could have been reasonable, one actually found its way into the interface, using a Java 8 default method: List#sort() .有趣的是,在所有多态实现(通过List接口中的方法)可能是合理的方法中,有一个实际上找到了进入接口的方法,使用 Java 8 default方法: List#sort() Maybe others, like reverse , will be added later...也许其他人,如reverse ,将在以后添加......

Reverse is defined in Collections (with an extra (s)).反向在集合中定义(带有额外的 (s))。 This is not a part of collection hierarchy, rather it has been given as a part of utility class which can be used for different Lists.这不是集合层次结构的一部分,而是作为可用于不同列表的实用程序类的一部分。

Reversing a list is not a key part of defining a list , so its kept out of interface and given separately.反转列表不是定义列表的关键部分,因此它被排除在接口之外并单独给出。 If defined in the interface, everyone will have to implement it, which may not be suitable for all.如果在接口中定义,每个人都必须实现它,这可能不适合所有人。

The makers of collection could have build this in List hierarchy as well, ( Since most list derivations have an abstract class in between, they could have put it in any abstract class in between).集合的创建者也可以在 List 层次结构中构建它,(由于大多数列表派生之间都有一个抽象类,他们可以将它放在中间的任何抽象类中)。 However, to simplify everyone's life it makes sense to keep it in single utility class so that we don't have to figure out which class to look for all collection related utility functions.然而,为了简化每个人的生活,将它保存在单个实用程序类中是有意义的,这样我们就不必弄清楚要查找所有与集合相关的实用程序函数的类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM