programing tip

C ++ 쌍에 해당하는 것은 무엇입니까?

itbloger 2020. 10. 2. 21:46
반응형

C ++ 쌍에 해당하는 것은 무엇입니까? 자바?


Pair<L,R>Java에 없는 이유가 있습니까? 이 C ++ 구조와 동등한 것은 무엇입니까? 차라리 내 자신을 다시 구현하는 것을 피하고 싶습니다.

것 같다 1.6 비슷한 (제공 AbstractMap.SimpleEntry<K,V>)하지만,이 모습이 꽤 뒤얽힌.


에 스레드comp.lang.java.help , 헌터 Gratzner은의 존재에 대한 몇 가지 인수를 제공 Pair자바 구문을. 주된 주장은 클래스 Pair가 두 값 사이의 관계에 대한 의미를 전달하지 않는다는 것입니다 ( "첫 번째"와 "두 번째"가 무엇을 의미하는지 어떻게 알 수 있습니까?).

더 나은 방법은 Mike가 제안한 것과 같은 매우 간단한 클래스를 작성하여 각 응용 프로그램에 대해 작성하는 것 Pair입니다. Map.Entry이름에 의미를 담고있는 한 쌍의 예입니다.

요약하자면, 제 생각에는 어떤 일을해야하는지 알려주지 않는 제네릭보다는 클래스 Position(x,y), 클래스 Range(begin,end)클래스를 갖는 것이 낫습니다 .Entry(key,value)Pair(first,second)


이것은 Java입니다. 설명적인 클래스와 필드 이름을 사용하여 맞춤형 Pair 클래스를 만들어야하며 hashCode () / equals ()를 작성하거나 Comparable을 반복해서 구현하여 휠을 재발 명 할 것이라는 점을 염두에 두지 마십시오.


HashMap 호환 쌍 클래스 :

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

내가 생각 해낼 수있는 가장 짧은 쌍은 Lombok을 사용하여 다음과 같습니다 .

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

@arturh의 답변 의 모든 이점 (비교 성 제외)이 hashCode있으며 equals, toString및 정적 "생성자"가 있습니다.


Apache Commons Lang 3.0+에는 몇 가지 Pair 클래스가 있습니다. http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html


Pair with를 구현하는 또 다른 방법입니다.

  • 공개 불변 필드, 즉 간단한 데이터 구조.
  • 유사한.
  • 간단한 해시와 같음.
  • 간단한 공장이므로 유형을 제공 할 필요가 없습니다. 예 : Pair.of ( "hello", 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 + ')';
        }
    }
    

http://www.javatuples.org/index.html어떻습니까? 나는 그것이 매우 유용하다는 것을 알았습니다.

javatuples는 1 ~ 10 개의 요소로 구성된 튜플 클래스를 제공합니다.

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)

사용하려는 용도에 따라 다릅니다. 이렇게하는 일반적인 이유는지도를 반복하는 것입니다. 이렇게하면됩니다 (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는 Pair클래스 ( http://developer.android.com/reference/android/util/Pair.html )를 제공하며 여기에 구현이 있습니다.

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

가장 큰 문제는 A와 B에서 불변성을 보장 할 수 없기 때문에 ( 유형 매개 변수가 불변인지 확인하는 방법 참조 ) 예를 들어 컬렉션에 삽입 된 hashCode() 동일한 Pair에 대해 일관되지 않은 결과를 제공 할 수 있다는 것입니다 (이것은 정의되지 않은 동작을 제공합니다 , 가변 필드 측면에서 같음 정의 참조 ). 특정 (일반이 아닌) Pair 클래스의 경우 프로그래머는 A와 B를 불변으로 신중하게 선택하여 불변성을 보장 할 수 있습니다.

어쨌든 @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 + ')';
    }
}

추가 / 수정을 많이 환영합니다. :) 특히 Pair<?, ?>.

이 구문의 이유에 대한 자세한 내용 은 객체가 Comparable을 구현하는지 확인 하고 자세한 설명 은 Java에서 일반 함수 를 구현하는 방법을 참조 하십시오 .max(Comparable a, Comparable b)


Good News JavaFX에는 키 값 쌍이 있습니다.

javafx를 종속성으로 추가하고 가져옵니다 javafx.util.Pair.

에서와 같이 간단히 사용하십시오 c++.

Pair <Key, Value> 

예 :

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

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

제 생각에는 Java에는 Pair가 없습니다. 왜냐하면 그 쌍에 직접 추가 기능 (예 : Comparable)을 추가하려면 유형을 바인딩해야하기 때문입니다. C ++에서 우리는 상관하지 않고, 한 쌍의 구성 유형이없는 경우 operator <는이 pair::operator <뿐만 아니라 컴파일되지 않습니다.

경계가없는 Comparable의 예 :

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

Comparable with compile-time check for whether type arguments are similar :

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

이것은 좋지만 이번에는 비교할 수없는 유형을 Pair의 유형 인수로 사용하지 않을 수 있습니다. 일부 유틸리티 클래스에서 Pair에 대해 많은 Comparators를 사용할 수 있지만 C ++ 사용자는이를 얻지 못할 수 있습니다. 또 다른 방법은 유형 인수에 대한 경계가 다른 유형 계층 구조에 많은 클래스를 작성하는 것입니다. 그러나 가능한 경계와 그 조합이 너무 많습니다.


JavaFX (Java 8과 함께 제공됨)에는 Pair <A, B> 클래스가 있습니다.


다른 많은 사람들이 이미 언급했듯이 Pair 클래스가 유용한 지 여부는 사용 사례에 따라 다릅니다.

개인 도우미 함수의 경우 코드를 더 읽기 쉽게 만들고 모든 보일러 플레이트 코드로 또 다른 값 클래스를 만들 가치가없는 경우 Pair 클래스를 사용하는 것이 합법적이라고 생각합니다.

반면에 추상화 수준에서 두 개의 개체 또는 값을 포함하는 클래스의 의미를 명확하게 문서화해야하는 경우 해당 클래스를 작성해야합니다. 일반적으로 데이터가 비즈니스 객체 인 경우입니다.

항상 그렇듯이 숙련 된 판단이 필요합니다.

두 번째 질문에 대해서는 Apache Commons 라이브러리의 Pair 클래스를 권장합니다. Java 용 확장 표준 라이브러리로 간주 될 수 있습니다.

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

비즈니스 객체에 대한 값 클래스 작성을 단순화하는 Apache Commons의 EqualsBuilder , HashCodeBuilderToStringBuilder살펴볼 수도 있습니다 .


PairC ++의 <> 쌍과 동일한 용도로 사용되는 javafx 유틸리티 클래스를 사용할 수 있습니다 . https://docs.oracle.com/javafx/2/api/javafx/util/Pair.html


Map.Entry 인터페이스는 C ++ 쌍에 매우 가깝습니다. AbstractMap.SimpleEntryAbstractMap.SimpleImmutableEntry같은 구체적인 구현을 살펴보십시오. 첫 번째 항목은 getKey ()이고 두 번째 항목은 getValue ()입니다.


Collections.singletonMap(left, rigth);

Java 언어의 특성에 따라 사람들은 실제로를 필요로하지 않는다고 생각 Pair합니다. 일반적으로 인터페이스가 필요한 것입니다. 다음은 예입니다.

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

따라서 사람들이 두 개의 값을 반환하려면 다음을 수행 할 수 있습니다.

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

이것은 매우 가벼운 솔루션이며 "의 의미는 무엇입니까 Pair<L,R>?"라는 질문에 답합니다 . 대답은 이것이 두 가지 (다를 수 있음) 유형이있는 인터페이스 빌드이며 각각을 반환하는 메서드가 있다는 것입니다. 더 많은 의미를 추가하는 것은 당신에게 달려 있습니다. 예를 들어, Position을 사용 중이고 실제로 코드에 표시하려면을 정의 PositionX하고 PositionY포함 Integer하여 Pair<PositionX,PositionY>. JSR 308을 사용할 수있는 경우 Pair<@PositionX Integer, @PositionY Ingeger>이를 단순화하는 데 사용할 수도 있습니다 .

편집 : 여기서 표시해야하는 한 가지는 위의 정의가 형식 매개 변수 이름과 메서드 이름을 명시 적으로 관련 시킨다는 것입니다. 이것은 a Pair가 의미 정보가 부족하다는 주장에 대한 대답 입니다. 실제로이 방법 getL은 "L 유형 매개 변수 유형에 해당하는 요소를 줘"라는 의미이며, 이는 의미가 있습니다.

편집 : 삶을 더 쉽게 만들 수있는 간단한 유틸리티 클래스는 다음과 같습니다.

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

용법:

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

구문 상 유사 함에도 불구하고 Java와 C ++는 매우 다른 패러다임을 가지고 있습니다. Java와 같은 C ++를 작성하는 것은 나쁜 C ++이고 C ++와 같은 Java를 작성하는 것은 나쁜 Java입니다.

Eclipse와 같은 리플렉션 기반 IDE를 사용하면 "쌍"클래스의 필수 기능을 작성하는 것이 빠르고 간단합니다. 클래스를 만들고 두 개의 필드를 정의하고 다양한 "XX 생성"메뉴 옵션을 사용하여 몇 초 만에 클래스를 채 웁니다. Comparable 인터페이스를 원한다면 "compareTo"를 빨리 입력해야 할 수도 있습니다.

별도의 선언 / 정의 옵션을 사용하는 C ++ 코드 생성기는 그리 좋지 않으므로 유틸리티 클래스를 거의 작성하지 않으면 시간이 더 많이 소요됩니다. 쌍이 템플릿이기 때문에 사용하지 않는 함수에 대해 비용을 지불 할 필요가 없으며 typedef 기능을 사용하면 코드에 의미있는 유형 이름을 할당 할 수 있으므로 "의미 없음"에 대한 이의가 실제로 유지되지 않습니다.


예를 들어, 이것은 내 코드에서 가져온 것입니다.

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

Haskell의 Tuple과 동일합니다.


Java와 같은 프로그래밍 언어의 경우 대부분의 프로그래머가 데이터 구조와 같은 쌍을 나타내는 데 사용하는 대체 데이터 구조는 두 개의 배열이며 데이터는 동일한 인덱스를 통해 액세스됩니다.

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

데이터를 함께 묶어야하기 때문에 이상적이지는 않지만 매우 저렴합니다. 또한 사용 사례에서 좌표를 저장해야하는 경우 자체 데이터 구조를 구축하는 것이 좋습니다.

내 도서관에 이런 게 있어요

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

Google의 AutoValue 라이브러리 ( https://github.com/google/auto/tree/master/value)를 사용할 수 있습니다 .

아주 작은 추상 클래스를 만들고 @AutoValue로 주석을 달면 주석 프로세서가 값 의미가있는 구체적인 클래스를 생성합니다.


편의를 위해 여러 수준의 튜플이있는 라이브러리는 다음과 같습니다.

  • JavaTuples . 1-10 차의 튜플 만 있으면됩니다.
  • JavaSlang . 0-8 차의 튜플 및 기타 많은 기능적 장점.
  • jOOλ . 0-16 차의 튜플 및 기타 기능적 장점. (면책 조항, 나는 유지 보수 회사에서 일합니다)
  • 기능적인 자바 . 0-8 차의 튜플 및 기타 많은 기능적 장점.

적어도 Pair튜플 을 포함하는 다른 라이브러리가 언급되었습니다 .

특히, ( 허용 된 답변에서 옹호 된 것처럼) 명목 형 형식보다는 구조적 형식을 많이 사용하는 함수형 프로그래밍의 맥락 에서 이러한 라이브러리와 튜플은 매우 유용합니다.


Brian Goetz, Paul Sandoz 및 Stuart Marks 가 Devoxx'14의 QA 세션에서 그 이유를 설명 합니다.

표준 라이브러리에 일반 쌍 클래스가 있으면 값 유형이 도입 되면 기술 부채로 바뀝니다 .

참고 항목 : Java SE 8에는 쌍 또는 튜플이 있습니까?


간단한 방법 객체 []-차원 튜플로 사용할 수 있습니다.


두 값의 순서를 의미하는 모든 쌍 구현이 여기에 흩어져 있음을 알았습니다. 한 쌍을 생각할 때 두 항목의 순서가 중요하지 않은 두 항목의 조합을 생각합니다. 다음 은 컬렉션에서 원하는 동작을 보장하기 위해 hashCodeequals재정의를 사용하여 정렬되지 않은 쌍을 구현 한 것입니다 . 또한 복제 가능합니다.

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

    }

}

이 구현은 적절하게 단위 테스트를 거쳤으며 Set 및 Map에서의 사용이 시도되었습니다.

나는 이것을 공개 도메인에서 공개한다고 주장하지 않습니다. 이 코드는 방금 응용 프로그램에서 사용하기 위해 작성한 코드이므로이를 사용하려는 경우 직접 복사를 삼가하고 주석과 이름을 약간 엉망으로 만드십시오. 내 드리프트를 잡아?


누구나 간단하고 사용하기 쉬운 버전을 원한다면 https://github.com/lfac-pt/Java-Pair 에서 사용할 수 있도록 만들었습니다 . 또한 개선 사항을 환영합니다!


com.sun.tools.javac.util.Pair는 쌍의 간단한 구현입니다. jdk1.7.0_51 \ lib \ tools.jar에서 찾을 수 있습니다.

org.apache.commons.lang3.tuple.Pair 외에는 단순한 인터페이스가 아닙니다.


또 다른 간결한 롬복 구현

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

}

사용법 :

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

불변, 단 한 쌍!

참고 URL : https://stackoverflow.com/questions/156275/what-is-the-equivalent-of-the-c-pairl-r-in-java

반응형