Gibt es einen guten Grund, warum es keinen gibt? Pair<L,R>
in Java ? Was wäre das Äquivalent zu diesem C ++ - Konstrukt? Ich würde es lieber vermeiden, meine eigenen neu zu implementieren.
Es scheint, dass 1.6 etwas Ähnliches liefert ( AbstractMap.SimpleEntry<K,V>
), aber das sieht ziemlich kompliziert aus.
AbstractMap.SimpleEntry
verschlungen?Antworten:
In einem Thread über
comp.lang.java.help
gibt Hunter Gratzner einige Argumente gegen das Vorhandensein einesPair
Konstrukts in Java. Das Hauptargument ist, dass eine KlassePair
keine Semantik über die Beziehung zwischen den beiden Werten vermittelt (woher wissen Sie, was "erste" und "zweite" bedeuten?).Eine bessere Vorgehensweise besteht darin, für jede Anwendung, die Sie für die
Pair
Klasse gemacht hätten, eine sehr einfache Klasse zu schreiben, wie die von Mike vorgeschlagene .Map.Entry
ist ein Beispiel für ein Paar, das seine Bedeutung im Namen trägt.Zusammenfassend ist es meiner Meinung nach besser, eine Klasse
Position(x,y)
, eine KlasseRange(begin,end)
und eine Klasse zu haben ,Entry(key,value)
als ein GenerikumPair(first,second)
, das mir nichts darüber sagt, was es tun soll.quelle
Das ist Java. Sie müssen Ihre eigene maßgeschneiderte Pair-Klasse mit beschreibenden Klassen- und Feldnamen erstellen und müssen nicht vergessen, dass Sie das Rad neu erfinden, indem Sie hashCode () / equals () schreiben oder Comparable immer wieder implementieren.
quelle
SimpleImmutableEntry
HashMap-kompatible Paarklasse:
quelle
super()
herausgenommen haben. Normalerweise würde ich es einfach abbrechen, wenn es optional ist, so wie es hier ist.Das kürzeste Paar, das ich mit Lombok finden konnte, ist das folgende :
Es verfügt über alle Vorteile der Antwort von @arturh ( mit Ausnahme der Vergleichbarkeit), hat sie
hashCode
,equals
,toString
und eine statische „Konstruktor“.quelle
Apache Commons Lang 3.0+ hat einige Paarklassen: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
quelle
Eine andere Möglichkeit, Pair mit zu implementieren.
Einfache Fabrik, so dass Sie die Typen nicht angeben müssen. zB Pair.of ("Hallo", 1);
quelle
of
. Es erinnert an unveränderliche Sammlungen von Google Guava .o1
zuComparable
, obwohl nichts gibt es tatsächlich , dass die Schnittstelle implementieren. Wenn dies erforderlich ist, sollte derFIRST
Typparameter seinFIRST extends Comparable<?>
.Wie wäre es mit http://www.javatuples.org/index.html Ich habe es sehr nützlich gefunden.
Das Javatuples bietet Ihnen Tupelklassen mit einem bis zehn Elementen:
quelle
Pair
und konnte mir vorstellen, esTriplet
vielleicht alle 50 Jahre einmal zu benutzen . Jetzt benutze ich Lombok und erstelle jedes Mal, wenn ich ein Paar brauche, eine winzige 4-Zeilen-Klasse. "10 zu viel" ist also genau.Bottom (0 element)
Klasse? :)Es hängt davon ab, wofür Sie es verwenden möchten. Der typische Grund dafür ist das Durchlaufen von Karten, für die Sie dies einfach tun (Java 5+):
quelle
Android bietet
Pair
Klasse ( http://developer.android.com/reference/android/util/Pair.html ), hier die Implementierung:quelle
Objects.equal(..)
benötigt die Guava-Bibliothek.Objects.equals(...)
das seit 2011 in Java ist (1.7).Das größte Problem ist wahrscheinlich, dass man die Unveränderlichkeit auf A und B nicht sicherstellen kann (siehe So stellen Sie sicher, dass Typparameter unveränderlich sind ), so dass
hashCode()
beispielsweise nach dem Einfügen in eine Sammlung inkonsistente Ergebnisse für dasselbe Paar erzielt werden können (dies würde zu undefiniertem Verhalten führen , siehe Gleichheit in Bezug auf veränderbare Felder definieren ). Für eine bestimmte (nicht generische) Paarklasse kann der Programmierer die Unveränderlichkeit sicherstellen, indem er A und B sorgfältig als unveränderlich auswählt.Wie auch immer, Löschen der Warnungen von Generika aus der Antwort von @ PeterLawrey (Java 1.7):
Ergänzungen / Korrekturen sehr willkommen :) Insbesondere bin ich mir über meine Verwendung von nicht ganz sicher
Pair<?, ?>
.Weitere Informationen dazu, warum diese Syntax verwendet wird, finden Sie unter Sicherstellen, dass Objekte Comparable implementieren. Eine ausführliche Erläuterung finden Sie unter Implementieren einer generischen
max(Comparable a, Comparable b)
Funktion in Java.quelle
Meiner Meinung nach gibt es in Java kein Paar, da Sie die Typen binden müssen, wenn Sie dem Paar zusätzliche Funktionen direkt hinzufügen möchten (z. B. Vergleichbar). In C ++ ist es uns einfach egal, und wenn Typen, aus denen ein Paar besteht, keine haben
operator <
, wird daspair::operator <
auch nicht kompiliert.Ein Beispiel für Vergleichbar ohne Begrenzung:
Ein Beispiel für die Prüfung von Vergleichbar mit Kompilierungszeit, ob Typargumente vergleichbar sind:
Dies ist gut, aber dieses Mal können Sie möglicherweise keine nicht vergleichbaren Typen als Typargumente in Pair verwenden. In einigen Utility-Klassen werden möglicherweise viele Comparators for Pair verwendet, aber C ++ - Benutzer erhalten diese möglicherweise nicht. Eine andere Möglichkeit besteht darin, viele Klassen in einer Typhierarchie mit unterschiedlichen Grenzen für Typargumente zu schreiben, aber es gibt zu viele mögliche Grenzen und deren Kombinationen ...
quelle
JavaFX (im Lieferumfang von Java 8 enthalten) verfügt über die Klasse Pair <A, B>
quelle
hashCode()
. Beachten Sie, dass Java selbst diese Methode nicht aufruft. Es ist für Benutzercode, einschließlich Bibliotheken.Wie viele andere bereits festgestellt haben, hängt es wirklich vom Anwendungsfall ab, ob eine Pair-Klasse nützlich ist oder nicht.
Ich denke, für eine private Hilfsfunktion ist es absolut legitim, eine Pair-Klasse zu verwenden, wenn dies Ihren Code lesbarer macht und die Mühe nicht wert ist, eine weitere Wertklasse mit all ihrem Kesselplattencode zu erstellen.
Wenn Sie andererseits auf Ihrer Abstraktionsebene die Semantik der Klasse, die zwei Objekte oder Werte enthält, klar dokumentieren müssen, sollten Sie eine Klasse dafür schreiben. Normalerweise ist dies der Fall, wenn die Daten ein Geschäftsobjekt sind.
Wie immer erfordert es ein geschicktes Urteilsvermögen.
Für Ihre zweite Frage empfehle ich die Pair-Klasse aus den Apache Commons-Bibliotheken. Diese können als erweiterte Standardbibliotheken für Java betrachtet werden:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
Vielleicht möchten Sie auch einen Blick auf EqualsBuilder , HashCodeBuilder und ToStringBuilder von Apache Commons werfen , die das Schreiben von Wertklassen für Ihre Geschäftsobjekte vereinfachen.
quelle
Sie können die Dienstprogrammklasse javafx verwenden,
Pair
die denselben Zweck erfüllt wie das Paar <> in c ++. https://docs.oracle.com/javafx/2/api/javafx/util/Pair.htmlquelle
Gute Nachrichten
JavaFX
haben ein Schlüsselwertpaar.Fügen Sie einfach Javafx als Abhängigkeit hinzu und importieren Sie es
javafx.util.Pair
.und einfach wie in verwenden
c++
.z.B
quelle
Die Map.Entry- Oberfläche kommt dem C ++ - Paar ziemlich nahe. Schauen Sie sich die konkrete Implementierung wie AbstractMap.SimpleEntry und AbstractMap.SimpleImmutableEntry an. Das erste Element ist getKey () und das zweite ist getValue ().
quelle
quelle
Entsprechend der Natur der Java-Sprache benötigen die
Pair
Benutzer vermutlich keine , eine Schnittstelle ist normalerweise das, was sie benötigen. Hier ist ein Beispiel:Wenn Benutzer zwei Werte zurückgeben möchten, können sie Folgendes tun:
Dies ist eine ziemlich leichte Lösung, die die Frage "Was ist die Semantik von a
Pair<L,R>
?" Beantwortet . Die Antwort lautet: Dies ist eine Schnittstellenerstellung mit zwei (möglicherweise unterschiedlichen) Typen, und es gibt Methoden, um jeden von ihnen zurückzugeben. Es liegt an Ihnen, weitere Semantik hinzuzufügen. Wenn Sie Position zum Beispiel verwenden und wirklich wollen , um es in Sie Code angeben, können Sie festlegen ,PositionX
undPositionY
das enthältInteger
, um ein Make - upPair<PositionX,PositionY>
. Wenn JSR 308 verfügbar ist, können Sie auch verwendenPair<@PositionX Integer, @PositionY Ingeger>
, um dies zu vereinfachen.EDIT: Eine Sache, die ich hier angeben sollte, ist, dass die obige Definition den Typparameternamen und den Methodennamen explizit in Beziehung setzt. Dies ist eine Antwort auf diese Argumente, dass
Pair
es an semantischer Information mangelt. TatsächlichgetL
bedeutet die Methode "Gib mir das Element, das dem Typ des Typparameters L entspricht", was etwas bedeutet.EDIT: Hier ist eine einfache Utility-Klasse, die das Leben leichter machen kann:
Verwendungszweck:
quelle
equals
ist mithashCode
undtoString
?toString
benötigen Sie mehr Wissen über die Beziehung zwischen den beiden Feldern.class
möglicherweise besser ist als nur ein,interface
weil es diese Dinge implementieren kann.Obwohl Java und C ++ syntaktisch ähnlich sind, haben sie sehr unterschiedliche Paradigmen. Schreiben von C ++ wie Java ist schlechtes C ++, und Schreiben von Java wie C ++ ist schlechtes Java.
Mit einer reflexionsbasierten IDE wie Eclipse ist das Schreiben der erforderlichen Funktionalität einer "Paar" -Klasse schnell und einfach. Klasse erstellen, zwei Felder definieren, die verschiedenen Menüoptionen "XX generieren" verwenden, um die Klasse in Sekundenschnelle auszufüllen. Vielleicht müssten Sie ganz schnell ein "compareTo" eingeben, wenn Sie die vergleichbare Oberfläche möchten.
Mit separaten Deklarations- / Definitionsoptionen in der Sprache sind C ++ - Codegeneratoren nicht so gut, so dass das manuelle Schreiben kleiner Dienstprogrammklassen zeitaufwändiger ist. Da es sich bei dem Paar um eine Vorlage handelt, müssen Sie nicht für Funktionen bezahlen, die Sie nicht verwenden, und die typedef-Funktion ermöglicht das Zuweisen aussagekräftiger Typnamen zum Code, sodass die Einwände gegen "keine Semantik" nicht wirklich zutreffen.
quelle
Paar wäre ein gutes Zeug, um eine grundlegende Konstruktionseinheit für ein komplexes Generikum zu sein, zum Beispiel ist dies aus meinem Code:
Es ist genauso wie Haskells Tupel
quelle
Pair
ist optimal, da es keine spezielle Semantik gibt. Einen klaren Namen für ein klares Konzept zu haben ist gut, aber nach einem Namen zu suchen, bei dem "erste" und "zweite" gut funktionieren, ist nicht gut.Einfacher Weg Objekt [] - kann als jedes Dimensionstupel verwendet werden
quelle
Bei Programmiersprachen wie Java besteht die alternative Datenstruktur, die von den meisten Programmierern zur Darstellung paarweiser Datenstrukturen verwendet wird, aus zwei Arrays, und auf Daten wird über denselben Index zugegriffen
Beispiel: http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080
Dies ist nicht ideal, da die Daten miteinander verknüpft werden sollten, sich aber auch als ziemlich billig herausstellen. Wenn Ihr Anwendungsfall das Speichern von Koordinaten erfordert, ist es besser, eine eigene Datenstruktur zu erstellen.
Ich habe so etwas in meiner Bibliothek
quelle
Sie können die AutoValue-Bibliothek von Google verwenden - https://github.com/google/auto/tree/master/value .
Sie erstellen eine sehr kleine abstrakte Klasse und kommentieren sie mit @AutoValue. Der Annotationsprozessor generiert für Sie eine konkrete Klasse mit einer Wertsemantik.
quelle
Hier sind einige Bibliotheken mit mehreren Tupelgraden:
Es wurde erwähnt, dass andere Bibliotheken mindestens das
Pair
Tupel enthalten.Insbesondere im Kontext der funktionalen Programmierung, bei der viel strukturelle Typisierung anstelle von nominaler Typisierung verwendet wird ( wie in der akzeptierten Antwort empfohlen ), sind diese Bibliotheken und ihre Tupel sehr praktisch.
quelle
Brian Goetz, Paul Sandoz und Stuart Marks erklären während der QS-Sitzung bei Devoxx'14 , warum .
Generische Paar Klasse in Standard - Bibliothek hat , wird in die technische Schulden einmal wenden Werttypen eingeführt.
Siehe auch: Hat Java SE 8 Paare oder Tupel?
quelle
eine weitere knappe Lombok-Implementierung
quelle
Ich habe festgestellt, dass alle hier verstreuten Paarimplementierungen der Reihenfolge der beiden Werte Bedeutung zuschreiben. Wenn ich an ein Paar denke, denke ich an eine Kombination von zwei Elementen, bei denen die Reihenfolge der beiden keine Rolle spielt. Hier ist meine Implementierung eines ungeordneten Paares mit
hashCode
undequals
Überschreibungen, um das gewünschte Verhalten in Sammlungen sicherzustellen. Auch klonbar.Diese Implementierung wurde ordnungsgemäß Unit-getestet und die Verwendung in einem Set und einer Map wurde ausprobiert.
Beachten Sie, dass ich nicht behaupte, dies öffentlich zugänglich zu machen. Dies ist Code, den ich gerade für die Verwendung in einer Anwendung geschrieben habe. Wenn Sie ihn also verwenden möchten, machen Sie bitte keine direkte Kopie und spielen Sie ein wenig mit den Kommentaren und Namen herum. Fang meinen Drift?
quelle
Wenn jemand eine absolut einfache und benutzerfreundliche Version haben möchte, habe ich meine unter https://github.com/lfac-pt/Java-Pair verfügbar gemacht . Auch Verbesserungen sind sehr willkommen!
quelle
com.sun.tools.javac.util.Pair ist eine einfache Implementierung eines Paares. Es befindet sich in jdk1.7.0_51 \ lib \ tools.jar.
Anders als das org.apache.commons.lang3.tuple.Pair ist es nicht nur eine Schnittstelle.
quelle
Verwendungszweck :
Unveränderlich, nur ein Paar!
quelle
Pair<Object, Object> pair = Pair.createPair("abc", "def")
Aber ich denke, man mussPair.createPair((Object)"abc", (Object)"def")
mit Ihrem Code schreiben ?@SuppressWarnings("unchecked") public static <K, V, X, Y> Pair<X, Y> createPair(K key, V value) { return new Pair<X, Y>((X) key, (Y) value); }
aber ich weiß nicht, ob es eine gute Praxis istnew Pair<Object, Object>("abc", "def")
war das zuverlässigste in meinen Experimenten.