Warum gibt es in Java keine Methode "List.reverse ()"?

8

Um Elemente in einer Liste umzukehren, muss ich in Java folgendes verwenden:

%Vor%

Ich habe mich nur gefragt, warum Java die umgekehrte Methode nicht in der List -Schnittstelle implementiert, so dass ich die In-Place-Umkehr wie folgt machen könnte:

%Vor%

Hat jemand irgendwelche Ideen dazu?

    
Hanfei Sun 18.06.2016, 12:19
quelle

6 Antworten

10
  

Warum gibt es in Java keine Methode List.reverse() ?

Weil stattdessen eine Collections.reverse(List) Methode existiert.

Da die API-Designer festgestellt haben, dass es eine schlechte Idee war, jede List Implementierung 1 zu implementieren, wurde eine Methode implementiert, die nicht 99,9% der Zeit verwendet wurde sup> 2 . Dies könnte angegangen werden, indem die Methode "optional" gemacht wird, aber das hat auch Nachteile; z.B. Laufzeitausnahmen.

Weil für einige Arten von Listen (z. B. Stream-Wrapper / Adapter) die Implementierung von In-Place-Reverse problematisch wäre. Es ändert die Speicherauslastungseigenschaften der Liste, indem es vergegenständlicht wird.

Beachten Sie auch, dass die generische Implementierung ( Quellcode ) von reverse() , das von Collection bereitgestellt wird, verwendet set , um Elemente zu tauschen. Es ist nahezu optimal für die Standardlistentypen.

@shmosel Kommentare:

  

Ich gehe davon aus, dass OP fragt, warum es nicht als Standardmethode hinzugefügt wurde, wie es List.sort () war.

Gute Frage. Möglicherweise gilt das 99,9% Argument. Denken Sie daran, dass dies nur Leuten mit einer Codebasis helfen würde, die mit einem Java 8 oder späteren Compilern usw. erstellt wurde.

1 - Dies umfasst Implementierungen in Ihrer Codebasis und Bibliotheken von Drittanbietern.

2 - 86% der Statistiken sind für den theatralischen Effekt gemacht :-)

    
Stephen C 18.06.2016, 12:29
quelle
6

Aus dem gleichen Grund, dass fill und rotate und shuffle und swap und unendlich viele weitere Listenfunktionen sind in der Schnittstelle List nicht deklariert. Sie sind kein Teil der "Listen" -Abstraktion; Vielmehr können sie zusätzlich zu dieser Abstraktion implementiert werden.

Sobald ein List die bereits in der List -Schnittstelle implementierten Methoden implementiert, kann eine reverse -Funktion über die List -Abstraktion geschrieben werden, ohne eine bestimmte List -Implementierung zu kennen. Daher wäre es sinnlos, jede Klasse, die List implementiert, zu zwingen, eine benutzerdefinierte Implementierung von reverse (und fill , rotate , shuffle , swap usw.) bereitzustellen.

    
Sam Estep 18.06.2016 12:32
quelle
4

Weil Collection eine utilitaristische Klasse ist, die tatsächlich auf einem von SOLID Prinzip:
S - Prinzip der einfachen Verantwortung

  

Dieses Prinzip besagt, dass wir, wenn wir 2 Gründe für eine Klasse ändern müssen, die Funktionalität in zwei Klassen aufteilen müssen.

Sie haben eine Klasse, die eine gewisse Rolle spielt, und wenn Sie innere Daten manipulieren müssen, müssen Sie eine Unterklasse erstellen, die eine andere Rolle spielt.

    
Sergey Shustikov 18.06.2016 12:31
quelle
3

Wenn Sie list.reverse() benötigen, müssen Sie Eclipse-Sammlungen verwenden, wenn Sie nur list.reverseThis() verwenden können, siehe < a href="https://www.eclipse.org/collections/javadoc/7.1.0/org/eclipse/collections/api/list/MutableList.html"> dies . In der JDK-Liste werden viele Methoden (wie sort, max, min) nicht hinzugefügt.

Es gibt zwei verschiedene Arten des API-Designs:

  1. Eine Menge Methode in Collection - & gt; reiche Sammlung - & gt; Finsternis Sammlungen, Nachteil : viele selten verwendete Methode in List,
  2. Nur die am häufigsten verwendete Methode und Utility-Klasse - & gt; JDK     Sammlung, Nachteil : Verwenden Sie die Hilfsklasse wie Sammlungen,
Viacheslav Vedenin 18.06.2016 12:30
quelle
3

Hinweis: Diese Frage ist ein sehr spezifischer Fall von " Warum enthält die Collections-Klasse eigenständige (statische) Methoden, anstatt sie der List-Schnittstelle hinzuzufügen? " - man könnte sogar annehmen, dass es sich um ein Duplikat handelt. Darüber hinaus argumentiert man über die Gründe für die Entscheidung für jede einzelne Methode Teeblätter zu lesen, und niemand kann "den Grund" für die Designentscheidung für den speziellen Fall der reverse -Methode sagen (bis , vielleicht gibt Josh Bloch hier eine Antwort). Interessanterweise ist dies ein Punkt, der in den Java Collections API Design FAQ ...

Einige der anderen Antworten scheinen auf den ersten Blick überzeugend zu sein, werfen aber andere Fragen auf. Insbesondere geben einige von ihnen überhaupt keinen Grund für die Designentscheidung. Auch wenn es andere Möglichkeiten gibt, das Verhalten einer bestimmten Methode zu emulieren, oder wenn eine Methode nicht "99,9% aller Zeit" verwendet wird, kann es immer noch sinnvoll sein, sie in die Schnittstelle aufzunehmen.

Wenn Sie sich die Schnittstelle List ansehen, werden Sie feststellen, dass Sie grundsätzlich all Methoden basierend auf zwei anderen implementieren können:

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

(Für eine veränderbare Liste benötigen Sie auch set ). Dies sind genau diejenigen, die in AbstractList noch abstrakt sind. Alle anderen Methoden sind also eher "Convenience" -Methoden, die basierend auf diesen beiden Methoden kanonisch implementiert werden können. In dieser Hinsicht denke ich, dass die Antwort Sam Estep einen wichtigen Punkt enthält: Man könnte argumentieren, Dutzende anderer Methoden zu implementieren. Und es gibt sicherlich gute Gründe dafür. Werfen Sie einen Blick auf die tatsächliche Implementierung von Collections#reverse(List) :

%Vor%

Was ist das REVERSE_THRESHOLD und RandomAccess Ding dort? Im Ernst, wenn ich die Notwendigkeit hätte, ein Tagging-Interface wie RandomAccess einzuführen, würde ich stark mein Design in Frage stellen. Immer wenn du eine Methode wie

hast %Vor%

dann ist dies ein starkes Zeichen, dass dies eigentlich eine polymorphe Methode sein sollte, die entsprechend für den Special -Typ implementiert werden sollte.

Also ja, es war gerechtfertigt, die Methode reverse in die Schnittstelle zu ziehen, um eine polymorphe Implementierung zu ermöglichen. Gleiches gilt für fill rotate , shuffle , swap , sort und andere. Ähnlich könnte man eine statische Methode wie

eingeführt haben %Vor%

das bietet, was jetzt mit der Methode Collection#containsAll gemacht wird. Aber im Allgemeinen: Die Designer wählten eine bestimmte Reihe von Methoden, die sie für geeignet hielten. Einer der Gründe dafür, bestimmte Methoden auszulassen, könnte in einer der unteren Zeilen von der Rede von "How to Design Eine gute API & warum es wichtig ist "von Joshua Bloch, einer der Kerndesigner der Java Collections API:

Im Zweifelsfall

weglassen

Interessanterweise hat von allen Methoden, für die eine polymorphe Implementierung (über eine Methode in der List -Schnittstelle) sinnvoll gewesen sein könnte, one tatsächlich mit Java 8 in die Schnittstelle hineingelangt default Methode: List#sort() . Vielleicht werden andere wie reverse später hinzugefügt ...

    
Marco13 18.06.2016 13:41
quelle
0

Umkehren wird in Sammlungen definiert (mit zusätzlichen). Dies ist kein Teil der Auflistungshierarchie, sondern wurde als Teil der Dienstprogrammklasse angegeben, die für verschiedene Listen verwendet werden kann.

Das Umkehren einer Liste ist kein Schlüssel zum Definieren einer Liste, daher wird sie außerhalb der Schnittstelle gehalten und separat angegeben. Wenn es in der Oberfläche definiert ist, muss jeder es implementieren, was möglicherweise nicht für alle geeignet ist.

Die Macher der Sammlung könnten dies auch in der Listenhierarchie erstellen. (Da die meisten Listenableitungen eine abstrakte Klasse dazwischen haben, könnten sie sie in jede abstrakte Klasse dazwischen gesetzt haben). Um jedoch das Leben jedes Einzelnen zu vereinfachen, ist es sinnvoll, es in einer einzigen Dienstprogrammklasse zu belassen, so dass wir nicht herausfinden müssen, welche Klasse nach allen sammlungsbezogenen Dienstprogrammfunktionen suchen soll.

    
Rishi Goel 18.06.2016 12:58
quelle

Tags und Links