716 Stimmen

Was ist das Äquivalent von C++ Pair<L,R> in Java?

Gibt es einen guten Grund, warum es in Java kein Pair gibt? Was wäre das Äquivalent zu diesem C++-Konstrukt? Ich würde es lieber vermeiden, mein eigenes neu zu implementieren.

Es scheint, dass 1.6 etwas Ähnliches bereitstellt (AbstractMap.SimpleEntry), aber das sieht ziemlich verworren aus.

10 Stimmen

Warum ist AbstractMap.SimpleEntry umständlich?

0 Stimmen

Sehen Sie meine Antwort stackoverflow.com/a/16089164/173149, wo ich AbstractMap.SimpleImmutableEntry ohne Probleme verwende (kompliziertes Beispiel).

0 Stimmen

SimpleEntry hat drei Methoden, die nicht von Object vererbt wurden. Warum sollte es "verschachtelt" sein?

4voto

Denis Arkharov Punkte 79
Collections.singletonMap(left, rigth);

0 Stimmen

Wenn ein Wert null sein muss, funktioniert dies nicht.

3voto

Testus Punkte 104

Einfache Methode Object [] - kann als Tupel im Dimension verwendet werden

2 Stimmen

Jede Dimension, ja. Aber: Umständlich zu erstellen und nicht typsicher.

0 Stimmen

Object[] paar = {links, rechts}; // Nicht umständlich.

2voto

Illarion Kovalchuk Punkte 5518

Paar wäre ein gutes Element, um eine grundlegende Konstruktionseinheit für komplexe Generika zu sein, zum Beispiel, das ist aus meinem Code:

WeakHashMap, String> map = ...

Es ist genau wie das Tuple in Haskell

2 Stimmen

Jetzt kann ich sagen, dass die Verwendung von Pair den Code weniger informativ macht, und die Implementierung spezieller Objekte anstelle der Verwendung von Pair ist viel besser.

1 Stimmen

Besser oder schlechter. Stellen Sie sich vor, Sie haben eine Funktion, die ihre beiden Argumente kombiniert (z. B. das Zusammenführen von Graphen in einem) und sie zwischenspeichern müssen. Hier ist Pair optimal, da es keine spezielle Semantik gibt. Es ist gut, einen klaren Namen für ein klares Konzept zu haben, aber nach einem Namen zu suchen, bei dem "erstens" und "zweitens" gut funktionieren, ist nicht notwendig.

1voto

G_H Punkte 11428

Mir ist aufgefallen, dass alle Pair-Implementierungen, die hier verstreut sind, der Reihenfolge der beiden Werte Bedeutung beimessen. Wenn ich an ein Paar denke, denke ich an eine Kombination von zwei Elementen, bei der die Reihenfolge der beiden keine Rolle spielt. Hier ist meine Implementierung eines ungeordneten Paares, mit hashCode y equals Überschreibungen, um das gewünschte Verhalten in Sammlungen 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 wurde gründlich getestet und die Verwendung in einem Set und einer Map wurde ausprobiert.

Bitte beachten Sie, dass ich nicht behaupte, diese Informationen für die Öffentlichkeit zugänglich zu machen. Es handelt sich um Code, den ich gerade für eine Anwendung geschrieben habe. Wenn Sie ihn also verwenden wollen, sehen Sie bitte davon ab, ihn direkt zu kopieren und spielen Sie ein wenig mit den Kommentaren und Namen herum. Verstehen Sie, worauf ich hinaus will?

3 Stimmen

Eigentlich, überprüfen Sie den unteren Teil jeder Seite: "Nutzerbeiträge lizenziert unter cc-wiki"

0 Stimmen

Ah, das hatte ich nicht bemerkt. Danke für den Hinweis. In diesem Fall verwenden Sie den Code nach Belieben unter dieser Lizenz.

1 Stimmen

Die Frage handelt von einem C++-Äquivalentpaar - das geordnet ist. Außerdem denke ich, dass solange man eine Referenz auf ein Objekt von Pair hat und diese veränderbar sind, das Einfügen von Paaren in Sammlungen zu undefiniertem Verhalten führen könnte.

1voto

Luís Cardoso Punkte 11

Wenn jemand eine sehr einfache und benutzerfreundliche Version haben möchte, stelle ich meine unter https://github.com/lfac-pt/Java-Pair zur Verfügung. Verbesserungen sind auch sehr willkommen!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X