Wat is het equivalent van het C++-paar<L,R> op Java?

Is er een goede reden waarom er geen Pair<L,R> in Java is? Wat zou het equivalent zijn van dit C++-construct? Ik zou liever voorkomen dat ik die van mezelf opnieuw implementeer.

Het lijkt erop dat 1.6 iets soortgelijks biedt (AbstractMap.SimpleEntry<K,V>), maar dit ziet er nogal ingewikkeld uit.


Antwoord 1, autoriteit 100%

In een thread op comp.lang.java.help, geeft Hunter Gratzner enkele argumenten tegen de aanwezigheid van een Pair-constructie in Java. Het belangrijkste argument is dat een klasse Pair geen enkele semantiek over de relatie tussen de twee waarden weergeeft (hoe weet je wat “eerste” en “tweede” betekenen?).

Een betere gewoonte is om een ​​heel eenvoudige klas te schrijven, zoals degene die Mike voorstelde, voor elke toepassing die je zou hebben gemaakt voor de Pair-klasse. Map.Entry is een voorbeeld van een paar dat zijn betekenis in zijn naam draagt.

Samenvattend, naar mijn mening is het beter om een ​​klasse Position(x,y), een klasse Range(begin,end) en een klasse Entry(key,value) in plaats van een generiek Pair(first,second) dat me niets vertelt over wat het zou moeten doen.


Antwoord 2, autoriteit 39%

Dit is Java. Je moet je eigen op maat gemaakte Pair-klasse maken met beschrijvende klasse- en veldnamen, en niet te vergeten dat je het wiel opnieuw zult uitvinden door hashCode()/equals() te schrijven of Comparable keer op keer te implementeren.


Antwoord 3, autoriteit 26%

HashMap-compatibele paarklasse:

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;
    }
}

Antwoord 4, autoriteit 14%

Het kortste paar dat ik kon bedenken is het volgende, met behulp van Lombok:

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

Het heeft alle voordelen van het antwoord van @arturh (behalve de vergelijkbaarheid), het heeft hashCode, equals, toString en een statische constructor .


Antwoord 5, autoriteit 9%

Apache Commons Lang 3.0+ heeft een paar Pair-klassen:
http://commons .apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html


Antwoord 6, autoriteit 8%

Een andere manier om Pair with te implementeren.

  • Openbare onveranderlijke velden, d.w.z. eenvoudige gegevensstructuur.
  • Vergelijkbaar.
  • Eenvoudige hash en gelijken.
  • Eenvoudige fabriek, zodat u de typen niet hoeft aan te leveren. bijv. 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 + ')';
        }
    }
    

Antwoord 7, autoriteit 7%

Hoe zit het met http://www.javatuples.org/index.html die ik heb gevonden het is erg handig.

De javatuples biedt u tuple-klassen van één tot tien elementen:

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)

Antwoord 8, autoriteit 3%

android biedt Pairclass (http://developer.android.com /reference/android/util/Pair.html), hier de implementatie:

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);
    }
}

Antwoord 9, autoriteit 3%

Het hangt af van waar je het voor wilt gebruiken. De typische reden om dit te doen is om kaarten te herhalen, waarvoor u eenvoudigweg dit doet (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());
}

Antwoord 10, autoriteit 2%

Het grootste probleem is waarschijnlijk dat men geen onveranderlijkheid op A en B kan garanderen (zie Hoe ervoor te zorgen dat typeparameters onveranderbaar zijn) zodat hashCode() inconsistente resultaten kan geven voor hetzelfde paar nadat is ingevoegd in een verzameling bijvoorbeeld (dit zou ongedefinieerd gedrag geven, zie gelijken definiëren in termen van veranderlijke velden). Voor een bepaalde (niet-generieke) paarklasse kan de programmeur zorgen voor onveranderlijkheid door zorgvuldig A en B als onveranderlijk te kiezen.

Hoe dan ook, het wissen van de generieke waarschuwingen uit het antwoord van @PeterLawrey (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 + ')';
    }
}

Aanvullingen/correcties zeer welkom 🙂 In het bijzonder ben ik niet helemaal zeker van mijn gebruik van Pair<?, ?>.

Zie voor meer informatie over waarom deze syntaxis Zorg ervoor dat objecten Comparable implementeren en voor een gedetailleerde uitleg Hoe implementeer je een generieke max(Comparable a, Comparable b)-functie in Java?


Antwoord 11, autoriteit 2%

Goed nieuws JavaFX heeft een sleutelwaardepaar.

Voeg JavaFX toe als een afhankelijkheid en importeer javafx.util.Pair, en gebruik het gewoon zoals in C++.

Pair <Key, Value> 

bijv.

Pair <Integer, Integer> pr = new Pair<Integer, Integer>()
pr.get(key);// will return corresponding value

Antwoord 12

Naar mijn mening is er geen paar in Java, want als je extra functionaliteit rechtstreeks aan het paar wilt toevoegen (bijvoorbeeld vergelijkbaar), moet je de typen binden. In C++ maakt het ons niet uit, en als typen die een paar vormen geen operator < hebben, zal het pair::operator < niet zo goed compileren.

Een voorbeeld van Vergelijkbaar zonder begrenzing:

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));

Een voorbeeld van Vergelijkbaar met controle tijdens compileren om te zien of typeargumenten vergelijkbaar zijn:

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));

Dit is goed, maar deze keer mag je geen niet-vergelijkbare typen gebruiken als typeargumenten in Pair.
Je kunt in een bepaalde nutsklasse veel Comparators for Pair gebruiken, maar C++-mensen snappen het misschien niet. Een andere manier is om veel klassen in een typehiërarchie te schrijven met verschillende grenzen voor typeargumenten, maar er zijn te veel mogelijke grenzen en hun combinaties…


Antwoord 13

Volgens de aard van de Java-taal, veronderstel ik dat mensen niet echt een Pair nodig hebben, een interface is meestal wat ze nodig hebben. Hier is een voorbeeld:

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

Dus als mensen twee waarden willen retourneren, kunnen ze het volgende doen:

... //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; }
}

Dit is een vrij lichte oplossing en beantwoordt de vraag “Wat is de semantiek van een Pair<L,R>?”. Het antwoord is dat dit een interface is die is gebouwd met twee (mogelijk verschillende) typen, en het heeft methoden om ze allemaal te retourneren. Het is aan jou om er nog meer semantiek aan toe te voegen. Als u bijvoorbeeld Position gebruikt en dit ECHT in uw code wilt aangeven, kunt u PositionX en PositionY definiëren die Integer bevatten, om verzin een Pair<PositionX,PositionY>. Als JSR 308 beschikbaar is, kunt u ook Pair<@PositionX Integer, @PositionY Ingeger> gebruiken om dat te vereenvoudigen.

BEWERKEN:
Een ding dat ik hier moet aangeven, is dat de bovenstaande definitie expliciet betrekking heeft op de typeparameternaam en de methodenaam. Dit is een antwoord op de beweringen dat een Pair een gebrek aan semantische informatie is. Eigenlijk betekent de methode getL “geef me het element dat overeenkomt met het type type parameter L”, wat wel iets betekent.

BEWERKEN:
Hier is een eenvoudige hulpprogrammaklasse die het leven gemakkelijker kan maken:

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; }   
        };
    }
}

gebruik:

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

Antwoord 14

JavaFX (dat wordt meegeleverd met Java 8) heeft de Pair< A,B > klas


Antwoord 15

Map.Entry-interface komen vrij dicht bij c ++ paar. Kijk naar de concrete implementatie, zoals AbstractMap.SimpleEntry en AbstractMap.SimpleImmutableEntry
Het eerste item is getKey() en het tweede item is getValue().


Antwoord 16

Zoals vele anderen al hebben gezegd, hangt het echt af van de use case of een Pair-klasse nuttig is of niet.

Ik denk dat het voor een privé-helperfunctie volkomen legitiem is om een ​​Pair-klasse te gebruiken als dat je code leesbaarder maakt en het niet de moeite waard is om nog een andere waardeklasse te creëren met al zijn boilerplate-code.

Aan de andere kant, als je abstractieniveau vereist dat je de semantiek van de klasse die twee objecten of waarden bevat duidelijk documenteert, dan moet je er een klasse voor schrijven. Meestal is dat het geval als de gegevens een zakelijk object zijn.

Zoals altijd vereist het een deskundig oordeel.

Voor je tweede vraag raad ik de Pair-klasse uit de Apache Commons-bibliotheken aan. Deze kunnen worden beschouwd als uitgebreide standaardbibliotheken voor Java:

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

Misschien wil je ook eens kijken naar EqualsBuilder, HashCodeBuilder en ToStringBuilder waarmee het schrijven van waardeklassen voor uw bedrijfsobjecten wordt vereenvoudigd.


Antwoord 17

U kunt de javafx-hulpprogrammaklasse Pair gebruiken, die hetzelfde doel dient als pair <> in c++. https://docs.oracle.com/javafx/2/api /javafx/util/Pair.html


Antwoord 18

Collections.singletonMap(left, rigth);

Antwoord 19

nog een korte lombok-implementatie

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

Antwoord 20

Ondanks dat ze syntactisch vergelijkbaar zijn, hebben Java en C++ zeer verschillende paradigma’s. C++ schrijven zoals Java is slecht C++, en Java schrijven zoals C++ is slecht Java.

Met een op reflectie gebaseerde IDE zoals Eclipse, is het schrijven van de noodzakelijke functionaliteit van een “paar” -klasse snel en eenvoudig. Maak een klas aan, definieer twee velden, gebruik de verschillende “Genereer XX” menu-opties om de klas in een kwestie van seconden in te vullen. Misschien moet je heel snel “vergelijken” typen als je de vergelijkbare interface wilt hebben.

Met aparte declaratie-/definitie-opties in de taal zijn C++-codegeneratoren niet zo goed, dus het met de hand schrijven van kleine hulpprogrammaklassen kost meer tijd. Omdat het paar een sjabloon is, hoef je niet te betalen voor functies die je niet gebruikt, en de typedef-faciliteit maakt het mogelijk om betekenisvolle typenamen aan de code toe te kennen, dus de bezwaren over “geen semantiek” houden niet echt op.


Antwoord 21

Een paar zou een goede zaak zijn, om bijvoorbeeld een basisconstructie-eenheid te zijn voor complexe generieke geneesmiddelen, dit komt uit mijn code:

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

Het is precies hetzelfde als Haskell’s Tuple


Antwoord 22

Eenvoudig object [] – kan worden gebruikt als een dimensie-tuple


Antwoord 23

Voor programmeertalen zoals Java is de alternatieve datastructuur die door de meeste programmeurs wordt gebruikt om paarachtige datastructuren weer te geven, twee arrays, en gegevens worden via dezelfde index benaderd

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

Dit is niet ideaal omdat de gegevens aan elkaar moeten worden gekoppeld, maar ook vrij goedkoop blijken te zijn. Als uw gebruikssituatie het opslaan van coördinaten vereist, is het ook beter om uw eigen gegevensstructuur te bouwen.

Ik heb zoiets in mijn bibliotheek

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

Antwoord 24

U kunt de AutoValue-bibliotheek van Google gebruiken – https://github.com/google/auto /tree/master/value.

U maakt een zeer kleine abstracte klasse en annoteert deze met @AutoValue en de annotatieprocessor genereert een concrete klasse voor u die een semantische waarde heeft.


Antwoord 25

Hier zijn enkele bibliotheken die meerdere graden van tuples hebben voor uw gemak:

  • JavaTuples. Tupels van graad 1-10 is alles wat het heeft.
  • JavaSlang. Tuples van graad 0-8 en tal van andere functionele goodies.
  • jOO?. Tuples van graad 0-16 en enkele andere functionele goodies. (Disclaimer, ik werk voor het onderhoudsbedrijf)
  • Functionele Java. Tuples van graad 0-8 en tal van andere functionele goodies.

Er is vermeld dat andere bibliotheken ten minste de Pair-tupel bevatten.

Met name in de context van functioneel programmeren waarbij veel gebruik wordt gemaakt van structureel typen, in plaats van nominaal typen (zoals bepleit in de geaccepteerd antwoord), die bibliotheken en hun tuples zijn erg handig.


Antwoord 26

Brian Goetz, Paul Sandoz en Stuart Marks leg uit waarom tijdens QA-sessie op Devoxx’14 .

Het hebben van een generieke paarklasse in de standaardbibliotheek zal technische schulden worden zodra waardetypen zijn geïntroduceerd .

Zie ook: Heeft Java SE 8 paren of tupels?


Antwoord 27

Het viel me op dat alle implementaties van Pair die hier verspreid zijn, betekenis toekennen aan de volgorde van de twee waarden. Als ik aan een paar denk, denk ik aan een combinatie van twee items waarbij de volgorde van de twee niet van belang is. Hier is mijn implementatie van een ongeordend paar, met hashCode en equals overschrijvingen om het gewenste gedrag in collecties te garanderen. Ook te klonen.

/**
 * 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;
    }
}

Deze implementatie is correct getest en het gebruik in een Set en Map is uitgeprobeerd.

Merk op dat ik niet beweer dit in het publieke domein vrij te geven. Dit is code die ik zojuist heb geschreven voor gebruik in een applicatie, dus als je het gaat gebruiken, maak dan geen directe kopie en knoei met de opmerkingen en namen. Begrijp ik mijn drift?


Antwoord 28

Als iemand een doodeenvoudige en gemakkelijk te gebruiken versie wil, heb ik mijn versie beschikbaar gemaakt op https:/ /github.com/lpac-pt/Java-Pair. Ook zijn verbeteringen zeer welkom!


Antwoord 29

com.sun.tools.javac.util.Pair is een eenvoudige implementatie van een paar.
Het is te vinden in jdk1.7.0_51\lib\tools.jar.

Behalve de org.apache.commons.lang3.tuple.Pair is het niet zomaar een interface.


Antwoord 30

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;
    }
}

gebruik:

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

Onveranderlijk, slechts een paar!

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes