Frage

Sie haben einen guten Grund, warum es keine Pair<L,R> in Java ist? Was wäre das Äquivalent dieser C ++ konstruieren? Ich würde lieber vermeiden meine eigene Neuimplementierung.

Es scheint, dass 1.6 bietet etwas ähnliches (AbstractMap.SimpleEntry<K,V>), aber dies sieht ganz verworren.

War es hilfreich?

Lösung

einen Thread auf comp.lang.java.help gibt Hunter Gratzner einige Argumente gegen die Anwesenheit eines Pair Konstrukt in Java. Das Hauptargument ist, dass eine Klasse Pair vermitteln keine Semantik über die Beziehung zwischen den beiden Werten (wie Sie wissen, was „erste“ und „zweite“ bedeuten?).

Eine bessere Praxis ist eine sehr einfache Klasse zu schreiben, wie der Mike, für jede Anwendung vorgeschlagen Sie die Pair Klasse gemacht habe. Map.Entry ist ein Beispiel für ein Paar, das seine Bedeutung in ihrem Namen trägt.

Um es zusammenzufassen, meiner Meinung nach ist es besser, eine Klasse Position(x,y) zu haben, eine Klasse Range(begin,end) und eine Klasse Entry(key,value) eher als eine allgemeine Pair(first,second), die mich nichts über nicht sagen, was es angenommen hat, zu tun.

Andere Tipps

Dies ist Java. Sie haben eine eigene maßgeschneiderte Pair-Klasse mit beschreibender Klasse und Feldnamen zu machen, und nicht in dem Sinne, dass Sie das Rad durch das Schreiben hashCode neu erfinden () / equals () oder vergleichbar wieder Implementierung und wieder.

HashMap kompatibel Pair-Klasse:

public class Pair<A, B> {
    private A first;
    private B second;

    public Pair(A first, B second) {
        super();
        this.first = first;
        this.second = second;
    }

    public int hashCode() {
        int hashFirst = first != null ? first.hashCode() : 0;
        int hashSecond = second != null ? second.hashCode() : 0;

        return (hashFirst + hashSecond) * hashSecond + hashFirst;
    }

    public boolean equals(Object other) {
        if (other instanceof Pair) {
            Pair otherPair = (Pair) other;
            return 
            ((  this.first == otherPair.first ||
                ( this.first != null && otherPair.first != null &&
                  this.first.equals(otherPair.first))) &&
             (  this.second == otherPair.second ||
                ( this.second != null && otherPair.second != null &&
                  this.second.equals(otherPair.second))) );
        }

        return false;
    }

    public String toString()
    { 
           return "(" + first + ", " + second + ")"; 
    }

    public A getFirst() {
        return first;
    }

    public void setFirst(A first) {
        this.first = first;
    }

    public B getSecond() {
        return second;
    }

    public void setSecond(B second) {
        this.second = second;
    }
}

Das kürzeste Paar, das ich tun konnte, ist die folgende, mit Lombok :

@Data
@AllArgsConstructor(staticName = "of")
public class Pair<F, S> {
    private F first;
    private S second;
}

Es alle Vorteile der die Antwort von @arturh (mit Ausnahme der Vergleichbarkeit), hat es hashCode, equals, toString und ein statischer „Konstruktor“.

Eine andere Art und Weise zu implementieren Paar mit.

  • öffentliche unveränderliche Felder, das heißt einfache Datenstruktur.
  • vergleichbar.
  • Einfache Hash und gleichkommt.
  • Einfache Fabrik, so dass Sie die Typen nicht zur Verfügung stellen müssen. z.B. Pair.of ( "Hallo", 1);

    public class Pair<FIRST, SECOND> implements Comparable<Pair<FIRST, SECOND>> {
    
        public final FIRST first;
        public final SECOND second;
    
        private Pair(FIRST first, SECOND second) {
            this.first = first;
            this.second = second;
        }
    
        public static <FIRST, SECOND> Pair<FIRST, SECOND> of(FIRST first,
                SECOND second) {
            return new Pair<FIRST, SECOND>(first, second);
        }
    
        @Override
        public int compareTo(Pair<FIRST, SECOND> o) {
            int cmp = compare(first, o.first);
            return cmp == 0 ? compare(second, o.second) : cmp;
        }
    
        // todo move this to a helper class.
        private static int compare(Object o1, Object o2) {
            return o1 == null ? o2 == null ? 0 : -1 : o2 == null ? +1
                    : ((Comparable) o1).compareTo(o2);
        }
    
        @Override
        public int hashCode() {
            return 31 * hashcode(first) + hashcode(second);
        }
    
        // todo move this to a helper class.
        private static int hashcode(Object o) {
            return o == null ? 0 : o.hashCode();
        }
    
        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof Pair))
                return false;
            if (this == obj)
                return true;
            return equal(first, ((Pair) obj).first)
                    && equal(second, ((Pair) obj).second);
        }
    
        // todo move this to a helper class.
        private boolean equal(Object o1, Object o2) {
            return o1 == null ? o2 == null : (o1 == o2 || o1.equals(o2));
        }
    
        @Override
        public String toString() {
            return "(" + first + ", " + second + ')';
        }
    }
    

Wie wäre es http://www.javatuples.org/index.html ich gefunden habe, es sehr nützlich.

Die javatuples bieten Klassen von eins bis zehn Elemente Tupel:

Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)
Quartet<A,B,C,D> (4 elements)
Quintet<A,B,C,D,E> (5 elements)
Sextet<A,B,C,D,E,F> (6 elements)
Septet<A,B,C,D,E,F,G> (7 elements)
Octet<A,B,C,D,E,F,G,H> (8 elements)
Ennead<A,B,C,D,E,F,G,H,I> (9 elements)
Decade<A,B,C,D,E,F,G,H,I,J> (10 elements)

Es hängt davon ab, was Sie es für verwenden möchten. Der typische Grund, dies zu tun ist, Karten iterieren, für die Sie einfach tun dies (Java 5 +):

Map<String, Object> map = ... ; // just an example
for (Map.Entry<String, Object> entry : map.entrySet()) {
  System.out.printf("%s -> %s\n", entry.getKey(), entry.getValue());
}

Android bietet Pairclass ( http://developer.android.com/reference/android/util/Pair .html ), hier die Umsetzung:

public class Pair<F, S> {
    public final F first;
    public final S second;

    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pair)) {
            return false;
        }
        Pair<?, ?> p = (Pair<?, ?>) o;
        return Objects.equal(p.first, first) && Objects.equal(p.second, second);
    }

    @Override
    public int hashCode() {
        return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
    }

    public static <A, B> Pair <A, B> create(A a, B b) {
        return new Pair<A, B>(a, b);
    }
}

Das größte Problem ist wahrscheinlich, dass man nicht Unveränderlichkeit auf A und B gewährleisten (siehe Wie die Parameter des Typs unveränderlich ) sind, um sicherzustellen, so inkonsistente Ergebnisse für das gleiche Paar geben hashCode() kann nach in einer Sammlung zum Beispiel eingeführt wird (dies würde nicht definiert Verhalten finden Sie unter Definition in Bezug auf veränderbare Felder gleich ). Für eine bestimmte (nicht generisch) Pair-Klasse kann der Programmierer Unveränderlichkeit gewährleistet durch sorgfältige Auswahl A und B unveränderlich sein.

Wie auch immer, allgemeine Warnungen von @ PeterLawrey Antwort Clearing (Java 1.7):

public class Pair<A extends Comparable<? super A>,
                    B extends Comparable<? super B>>
        implements Comparable<Pair<A, B>> {

    public final A first;
    public final B second;

    private Pair(A first, B second) {
        this.first = first;
        this.second = second;
    }

    public static <A extends Comparable<? super A>,
                    B extends Comparable<? super B>>
            Pair<A, B> of(A first, B second) {
        return new Pair<A, B>(first, second);
    }

    @Override
    public int compareTo(Pair<A, B> o) {
        int cmp = o == null ? 1 : (this.first).compareTo(o.first);
        return cmp == 0 ? (this.second).compareTo(o.second) : cmp;
    }

    @Override
    public int hashCode() {
        return 31 * hashcode(first) + hashcode(second);
    }

    // TODO : move this to a helper class.
    private static int hashcode(Object o) {
        return o == null ? 0 : o.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Pair))
            return false;
        if (this == obj)
            return true;
        return equal(first, ((Pair<?, ?>) obj).first)
                && equal(second, ((Pair<?, ?>) obj).second);
    }

    // TODO : move this to a helper class.
    private boolean equal(Object o1, Object o2) {
        return o1 == o2 || (o1 != null && o1.equals(o2));
    }

    @Override
    public String toString() {
        return "(" + first + ", " + second + ')';
    }
}

Ergänzungen / Korrekturen viel willkommen :) Insbesondere Ich bin nicht ganz sicher über meine Verwendung von Pair<?, ?>.

Für weitere Informationen darüber, warum diese Syntax finden Sie unter Stellen Sie sicher, dass Objekte Vergleichbare implementieren und für eine ausführliche Erklärung How eine generische max(Comparable a, Comparable b) Funktion in Java zu implementieren?

Meiner Meinung nach gibt es kein Paar in Java, weil, wenn Sie direkt zusätzliche Funktionalität hinzufügen wollen auf das Paar (z Vergleichbar), müssen Sie die Typen gebunden. In C ++, wir kümmern uns einfach nicht, und wenn Typen ein Paar Komponieren nicht operator < haben, wird die pair::operator < nicht so gut zusammenzustellen.

Ein Beispiel für Vergleichbare ohne Begrenzungs:

public class Pair<F, S> implements Comparable<Pair<? extends F, ? extends S>> {
    public final F first;
    public final S second;
    /* ... */
    public int compareTo(Pair<? extends F, ? extends S> that) {
        int cf = compare(first, that.first);
        return cf == 0 ? compare(second, that.second) : cf;
    }
    //Why null is decided to be less than everything?
    private static int compare(Object l, Object r) {
        if (l == null) {
            return r == null ? 0 : -1;
        } else {
            return r == null ? 1 : ((Comparable) (l)).compareTo(r);
        }
    }
}

/* ... */

Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
//Runtime error here instead of compile error!
System.out.println(a.compareTo(b));

Ein Beispiel für Vergleichbar mit Kompilierung-Check für ob Typargumente sind vergleichbar:

public class Pair<
        F extends Comparable<? super F>, 
        S extends Comparable<? super S>
> implements Comparable<Pair<? extends F, ? extends S>> {
    public final F first;
    public final S second;
    /* ... */
    public int compareTo(Pair<? extends F, ? extends S> that) {
        int cf = compare(first, that.first);
        return cf == 0 ? compare(second, that.second) : cf;
    }
    //Why null is decided to be less than everything?
    private static <
            T extends Comparable<? super T>
    > int compare(T l, T r) {
        if (l == null) {
            return r == null ? 0 : -1;
        } else {
            return r == null ? 1 : l.compareTo(r);
        }
    }
}

/* ... */

//Will not compile because Thread is not Comparable<? super Thread>
Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
System.out.println(a.compareTo(b));

Das ist gut, aber dieses Mal sind Sie möglicherweise nicht nicht vergleichbare Typen als Typargument in Pair verwenden. Man kann viele Komparatoren für Pair in einigen Utility-Klasse verwenden, aber C ++ Menschen kann es nicht bekommen. Eine weitere Möglichkeit ist eine Menge Klassen in einer Typhierarchie mit unterschiedlichen Grenzen auf Typargumente zu schreiben, aber es gibt zu viele möglichen Grenzen und deren Kombinationen ...

JavaFX (die mit Java 8 mitgeliefert) hat das Paar Klasse

Wie viele andere haben bereits gesagt, es hängt wirklich von dem Anwendungsfall, wenn ein Paar Klasse sinnvoll ist oder nicht.

Ich denke, für eine private Hilfsfunktion es völlig legitim ist, ein Paar Klasse zu verwenden, wenn das Ihr Code besser lesbar und ist nicht der Mühe wert mit all seinen Kesselblech Code noch eine andere Wertklasse zu schaffen.

Auf der anderen Seite, wenn Ihre Abstraktionsebene erfordert, dass Sie klar die Semantik der Klasse zu dokumentieren, die zwei Objekte oder Werte enthalten, dann sollten Sie eine Klasse für sie schreiben. In der Regel das ist der Fall, wenn die Daten ein Business-Objekt.

Wie immer es erfordert qualifiziertes Urteil.

Für Ihre zweite Frage empfehle ich die Klasse Pair aus den Apache Commons Bibliotheken. Diejenigen, könnte als erweiterte Standard-Bibliotheken für Java in Betracht gezogen werden:

https: // commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html

Sie möchten vielleicht auch einen Blick auf Apache Commons' haben, Equals , HashCodeBuilder und ToStringBuilder , die für Ihre Business-Objekte zu schreiben Wertklassen vereinfachen.

Good News Java addierte Schlüsselwertpaar.

nur importieren javafx.util.Pair;

und verwenden Sie einfach als in c++.

Pair < Key , Value > 

z.

Pair < Integer , Integer > pr = new Pair<Integer , Integer>()

pr.get(key); // will return corresponding value

Sie können javafx Utility-Klasse, Pair verwendet werden, die den gleichen Zweck wie Paar dient <> in c ++. https://docs.oracle.com/javafx/2/api /javafx/util/Pair.html

Map.Entry Schnittstelle ziemlich nahe gekommen c ++ Paar. Schauen Sie sich die konkrete Umsetzung, wie AbstractMap.SimpleEntry und AbstractMap.SimpleImmutableEntry Erster Punkt ist getKey () und das zweite ist getValue ().

Collections.singletonMap(left, rigth);

Nach der Art der Java-Sprache, nehme ich an Menschen eigentlich keine Pair benötigen, eine Schnittstelle in der Regel ist das, was sie brauchen. Hier ein Beispiel:

interface Pair<L, R> {
    public L getL();
    public R getR();
}

Also, wenn die Leute zwei Werte zurückgeben möchten, können sie wie folgt vor:

... //Calcuate the return value
final Integer v1 = result1;
final String v2 = result2;
return new Pair<Integer, String>(){
    Integer getL(){ return v1; }
    String getR(){ return v2; }
}

Dies ist eine ziemlich leichte Lösung, und es beantwortet die Frage „Was ist die semantische ein Pair<L,R> ist?“. Die Antwort ist, ist dies eine Schnittstelle Build mit zwei (kann unterschiedlich sein) Arten, und es hat Methoden jeden von ihnen zurückzukehren. Es liegt an Ihnen weiter, um es semantische hinzuzufügen. wenn Sie Position zum Beispiel verwenden und wirklich wollen, um es in Sie Code angeben, können Sie PositionX und PositionY zu definieren, die Integer enthält, um eine Pair<PositionX,PositionY> zu bilden. Wenn JSR 308 verfügbar ist, können Sie auch Pair<@PositionX Integer, @PositionY Ingeger> verwenden, um das zu vereinfachen.

EDIT: Eine Sache, ich soll hier zeigen, ist, dass die obige Definition explizit den Namen type-Parameter bezieht und die Methodennamen. Dies ist eine Antwort auf diejenigen, argumentiert, dass ein Pair Mangel an semantischen Informationen ist. Eigentlich bedeutet das Verfahren getL „Gib mir das Element, das auf die Art des Typ-Parameter L entsprechen“, die tun etwas bedeutet.

EDIT: Hier ist eine einfache Utility-Klasse, die das Leben erleichtern kann:

class Pairs {
    static <L,R> Pair<L,R> makePair(final L l, final R r){
        return new Pair<L,R>(){
            public L getL() { return l; }
            public R getR() { return r; }   
        };
    }
}

Nutzung:

return Pairs.makePair(new Integer(100), "123");

Trotz syntaktisch ähnlich zu sein, Java und C ++ haben sehr unterschiedliche Paradigmen. Schreiben C ++ wie Java ist schlecht C ++ und Java zu schreiben wie C ++ ist schlecht Java.

Bei einer Reflexion basierten IDE wie Eclipse, die notwendigerweise Funktionalität eines „Paar“ Klasse schreiben, ist schnell und einfach. Erstellen Klasse definiert zwei Felder, verwenden Sie die verschiedenen „Gene XX“ Menüoptionen, die Klasse in einer Angelegenheit von Sekunden zu füllen. Vielleicht würden Sie haben eine „compareTo“ ganz schnell eingeben, wenn Sie die Schnittstelle Comparable wollten.

Mit gesonderter Erklärung / Definition Optionen in der Sprache C ++ Code-Generatoren sind nicht so gut, so Handschrift wenig Utility-Klassen ist zeitaufwendig Eintönigkeit. Da das Paar eine Schablone ist, müssen Sie nicht für Funktionen zahlen Sie nicht verwenden, und die typedef Einrichtung ermöglicht es sinnvoll typenames auf den Code zuweisen, so dass die Einwände etwa „keine Semantik“ nicht wirklich halten.

Paar ein gutes Material sein würde, eine grundlegende Konstruktionseinheit für eine komplexe Generika, zum Beispiel zu sein, das aus meinem Code ist:

WeakHashMap<Pair<String, String>, String> map = ...

Es ist genau die gleiche wie Haskells Tuple

Programmiersprachen wie Java, die alternative Strukturdaten von den meisten Programmierern verwendet Paar zu repräsentieren, wie Daten-Strukturen zwei Arrays sind, und Daten werden über den gleichen Index

zugegriffen

Beispiel: http: //www-igm.univ -mlv.fr/~lecroq/string/node8.html#SECTION0080

Das ist nicht ideal, da die Daten miteinander verbunden werden sollen, sondern auch ziemlich billig entpuppen. Auch, wenn Ihr Anwendungsfall verlangt Speicherung Koordinaten dann ist es besser, Ihre eigene Datenstruktur aufzubauen.

Ich habe so etwas in meiner Bibliothek

public class Pair<First,Second>{.. }

Sie können mit Google-Bibliothek Autovalue - https://github.com/google/auto / Baum / Master / Wert .

Sie erstellen eine sehr kleine abstrakte Klasse und mit Anmerkungen versehen es mit @AutoValue und dem Annotation-Prozessor erzeugt eine konkrete Klasse für Sie, die einen Wert semantischen hat.

Hier sind einige Bibliotheken, die mehrere Grad von Tupeln für Ihre Bequemlichkeit haben:

  • JavaTuples . Tupeln von Grad 1 bis 10 ist alles was man hat.
  • JavaSlang . Tupeln von Grad 0-8 und viele andere funktionelle Leckereien.
  • jOOλ . Tupeln von Grad 0-16 und einige andere funktionelle Leckereien. (Disclaimer, ich arbeite für den Betreuer Gesellschaft)
  • Functional Java . Tupeln von Grad 0-8 und viele andere funktionelle Leckereien.

Andere Bibliotheken haben zumindest erwähnt das Pair Tupel enthalten.

Insbesondere im Zusammenhang mit der funktionalen Programmierung, die Verwendung von vielen strukturellen Typisierung macht, anstatt nominal Typisierung ( als befürwortete in dem akzeptierte Antwort ), sehr praktisch, diese Bibliotheken und ihre Tupel kommen.

Brian Goetz, Paul Sandoz und Stuart Marks erklären, warum während QA-Sitzung bei Devoxx'14 .

generic Paar Klasse in Standard-Bibliothek hat, wird in die technische Schulden einmal wenden Werttypen eingeführt .

Siehe auch: Ist Java SE 8 haben Pairs oder Tupeln?

Einfache Art und Weise Object [] - kann als anу Dimension Tupel verwendet werden

Ich habe bemerkt, die alle Pair-Implementierungen um hier auf die Reihenfolge der beiden Werte Attribut Bedeutung gestreut wird. Wenn ich an einem Paar denke, denke ich an einer Kombination von zwei Positionen, in denen die Reihenfolge der beiden nicht von Bedeutung ist. Hier ist meine Implementierung eines ungeordneten Paares, mit hashCode und equals überschreibt das gewünschte Verhalten in einer Sammlung zu gewährleisten. Auch klonbar.

/**
 * The class <code>Pair</code> models a container for two objects wherein the
 * object order is of no consequence for equality and hashing. An example of
 * using Pair would be as the return type for a method that needs to return two
 * related objects. Another good use is as entries in a Set or keys in a Map
 * when only the unordered combination of two objects is of interest.<p>
 * The term "object" as being a one of a Pair can be loosely interpreted. A
 * Pair may have one or two <code>null</code> entries as values. Both values
 * may also be the same object.<p>
 * Mind that the order of the type parameters T and U is of no importance. A
 * Pair&lt;T, U> can still return <code>true</code> for method <code>equals</code>
 * called with a Pair&lt;U, T> argument.<p>
 * Instances of this class are immutable, but the provided values might not be.
 * This means the consistency of equality checks and the hash code is only as
 * strong as that of the value types.<p>
 */
public class Pair<T, U> implements Cloneable {

    /**
     * One of the two values, for the declared type T.
     */
    private final T object1;
    /**
     * One of the two values, for the declared type U.
     */
    private final U object2;
    private final boolean object1Null;
    private final boolean object2Null;
    private final boolean dualNull;

    /**
     * Constructs a new <code>Pair&lt;T, U&gt;</code> with T object1 and U object2 as
     * its values. The order of the arguments is of no consequence. One or both of
     * the values may be <code>null</code> and both values may be the same object.
     *
     * @param object1 T to serve as one value.
     * @param object2 U to serve as the other value.
     */
    public Pair(T object1, U object2) {

        this.object1 = object1;
        this.object2 = object2;
        object1Null = object1 == null;
        object2Null = object2 == null;
        dualNull = object1Null && object2Null;

    }

    /**
     * Gets the value of this Pair provided as the first argument in the constructor.
     *
     * @return a value of this Pair.
     */
    public T getObject1() {

        return object1;

    }

    /**
     * Gets the value of this Pair provided as the second argument in the constructor.
     *
     * @return a value of this Pair.
     */
    public U getObject2() {

        return object2;

    }

    /**
     * Returns a shallow copy of this Pair. The returned Pair is a new instance
     * created with the same values as this Pair. The values themselves are not
     * cloned.
     *
     * @return a clone of this Pair.
     */
    @Override
    public Pair<T, U> clone() {

        return new Pair<T, U>(object1, object2);

    }

    /**
     * Indicates whether some other object is "equal" to this one.
     * This Pair is considered equal to the object if and only if
     * <ul>
     * <li>the Object argument is not null,
     * <li>the Object argument has a runtime type Pair or a subclass,
     * </ul>
     * AND
     * <ul>
     * <li>the Object argument refers to this pair
     * <li>OR this pair's values are both null and the other pair's values are both null
     * <li>OR this pair has one null value and the other pair has one null value and
     * the remaining non-null values of both pairs are equal
     * <li>OR both pairs have no null values and have value tuples &lt;v1, v2> of
     * this pair and &lt;o1, o2> of the other pair so that at least one of the
     * following statements is true:
     * <ul>
     * <li>v1 equals o1 and v2 equals o2
     * <li>v1 equals o2 and v2 equals o1
     * </ul>
     * </ul>
     * In any other case (such as when this pair has two null parts but the other
     * only one) this method returns false.<p>
     * The type parameters that were used for the other pair are of no importance.
     * A Pair&lt;T, U> can return <code>true</code> for equality testing with
     * a Pair&lt;T, V> even if V is neither a super- nor subtype of U, should
     * the the value equality checks be positive or the U and V type values
     * are both <code>null</code>. Type erasure for parameter types at compile
     * time means that type checks are delegated to calls of the <code>equals</code>
     * methods on the values themselves.
     *
     * @param obj the reference object with which to compare.
     * @return true if the object is a Pair equal to this one.
     */
    @Override
    public boolean equals(Object obj) {

        if(obj == null)
            return false;

        if(this == obj)
            return true;

        if(!(obj instanceof Pair<?, ?>))
            return false;

        final Pair<?, ?> otherPair = (Pair<?, ?>)obj;

        if(dualNull)
            return otherPair.dualNull;

        //After this we're sure at least one part in this is not null

        if(otherPair.dualNull)
            return false;

        //After this we're sure at least one part in obj is not null

        if(object1Null) {
            if(otherPair.object1Null) //Yes: this and other both have non-null part2
                return object2.equals(otherPair.object2);
            else if(otherPair.object2Null) //Yes: this has non-null part2, other has non-null part1
                return object2.equals(otherPair.object1);
            else //Remaining case: other has no non-null parts
                return false;
        } else if(object2Null) {
            if(otherPair.object2Null) //Yes: this and other both have non-null part1
                return object1.equals(otherPair.object1);
            else if(otherPair.object1Null) //Yes: this has non-null part1, other has non-null part2
                return object1.equals(otherPair.object2);
            else //Remaining case: other has no non-null parts
                return false;
        } else {
            //Transitive and symmetric requirements of equals will make sure
            //checking the following cases are sufficient
            if(object1.equals(otherPair.object1))
                return object2.equals(otherPair.object2);
            else if(object1.equals(otherPair.object2))
                return object2.equals(otherPair.object1);
            else
                return false;
        }

    }

    /**
     * Returns a hash code value for the pair. This is calculated as the sum
     * of the hash codes for the two values, wherein a value that is <code>null</code>
     * contributes 0 to the sum. This implementation adheres to the contract for
     * <code>hashCode()</code> as specified for <code>Object()</code>. The returned
     * value hash code consistently remain the same for multiple invocations
     * during an execution of a Java application, unless at least one of the pair
     * values has its hash code changed. That would imply information used for 
     * equals in the changed value(s) has also changed, which would carry that
     * change onto this class' <code>equals</code> implementation.
     *
     * @return a hash code for this Pair.
     */
    @Override
    public int hashCode() {

        int hashCode = object1Null ? 0 : object1.hashCode();
        hashCode += (object2Null ? 0 : object2.hashCode());
        return hashCode;

    }

}

Diese Implementierung wird getestet richtig Einheit gewesen und die Verwendung in einem Set und Karte wurde ausprobiert.

Beachten Ich behaupte nicht, dies in der Öffentlichkeit zu veröffentlichen. Dies ist Code, den ich in einer Anwendung verwendet nur geschrieben habe, also wenn du gehst, es zu benutzen, unterlassen Sie bitte eine direkte Kopie und Chaos über mit den Kommentaren und Namen ein wenig aus zu machen. Catch meine Drift?

Wenn jemand will eine tote einfach und leicht Version benutzt ich meine zur Verfügung gestellt unter https: / /github.com/lfac-pt/Java-Pair . Auch Verbesserungen sind sehr willkommen!

com.sun.tools.javac.util.Pair ist eine einfache Implementierung eines Paares. Es finden sich in jdk1.7.0_51 \ lib \ tools.jar.

Anders als die org.apache.commons.lang3.tuple.Pair, es ist nicht nur eine Schnittstelle.

eine andere terse lombok Implementierung

import lombok.Value;

@Value(staticConstructor = "of")
public class Pair<F, S> {
    private final F first;
    private final S second;
}
public class Pair<K, V> {

    private final K element0;
    private final V element1;

    public static <K, V> Pair<K, V> createPair(K key, V value) {
        return new Pair<K, V>(key, value);
    }

    public Pair(K element0, V element1) {
        this.element0 = element0;
        this.element1 = element1;
    }

    public K getElement0() {
        return element0;
    }

    public V getElement1() {
        return element1;
    }

}

Nutzung:

Pair<Integer, String> pair = Pair.createPair(1, "test");
pair.getElement0();
pair.getElement1();

Immutable, nur ein Paar!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top