Pair<L,R>
Java 가없는 이유가 있습니까? 이 C ++ 구문과 동등한 것은 무엇입니까? 오히려 내 자신을 다시 구현하는 것을 피하고 싶습니다.
것 같다 1.6 비슷한 (제공 AbstractMap.SimpleEntry<K,V>
)하지만,이 모습이 꽤 뒤얽힌.
Pair<L,R>
Java 가없는 이유가 있습니까? 이 C ++ 구문과 동등한 것은 무엇입니까? 오히려 내 자신을 다시 구현하는 것을 피하고 싶습니다.
것 같다 1.6 비슷한 (제공 AbstractMap.SimpleEntry<K,V>
)하지만,이 모습이 꽤 뒤얽힌.
답변:
년 에 스레드comp.lang.java.help
, 헌터 Gratzner은의 존재에 대한 몇 가지 인수를 제공 Pair
자바 구문을. 주요 주장은 클래스 Pair
가 두 값 사이의 관계에 대한 의미를 전달하지 않는다는 것입니다 ( "first"와 "second"의 의미는 무엇입니까?).
더 좋은 방법은 Mike가 제안한 것과 같이 클래스로 만든 각 응용 프로그램에 대해 매우 간단한 클래스를 작성하는 것 Pair
입니다. Map.Entry
이름에 의미가있는 쌍의 예입니다.
요약하자면, 제 생각에는 수행해야 할 일에 대해 아무것도 알려주지 않는 제네릭보다는 클래스 Position(x,y)
, 클래스 Range(begin,end)
및 클래스 를 갖는 Entry(key,value)
것이 좋습니다 Pair(first,second)
.
이것은 자바입니다. 설명 클래스 및 필드 이름을 사용하여 사용자 정의 된 Pair 클래스를 작성해야하며 hashCode () / equals ()를 작성하거나 Comparable을 반복해서 구현하여 휠을 재발 명 할 것이라는 점을 염두에 두지 마십시오.
SimpleImmutableEntry
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;
}
}
super()
외출 했을 때의 동작은 정확히 같습니다 . 일반적으로 여기에있는 것처럼 선택 사항 인 경우 그냥 기울입니다.
아파치 코 몬즈 랭 3.0 이상 몇 쌍의 클래스가 : 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 + ')';
}
}
of
. Google Guava의 불변 컬렉션을 상기시킵니다 .
o1
에 Comparable
아무것도 실제로 그 인터페이스를 구현하는 것입니다 나타냅니다에도 불구하고. 이것이 필수 인 경우 FIRST
type 매개 변수는이어야합니다 FIRST extends Comparable<?>
.
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)
Pair
Triplet
50 년마다 한 번씩 하고 상상할 수있었습니다 . 이제는 롬복을 사용하고 필요할 때마다 작은 4 라인 클래스를 만듭니다. "10이 너무 많음"이 정확합니다.
Bottom (0 element)
수업이 합니까? :)
사용하려는 대상에 따라 다릅니다. 그렇게하는 일반적인 이유는지도를 반복하기 위해서입니다 (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());
}
안드로이드는 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);
}
}
Objects.equal(..)
구아바 도서관이 필요합니다.
Objects.equals(...)
2011 년 이후 Java (1.7) 이후로 변경하십시오 .
가장 큰 문제는 사람이 A와 B에 불변성을 보장 할 수 없습니다 아마도 (참조 유형 매개 변수는 불변을 보장하기 위하여 어떻게 그렇게) hashCode()
같은 쌍에 대한 일관성없는 결과를 제공 할 수 있습니다 후 예를 들어 콜렉션에 삽입 (이 정의되지 않은 동작을 줄 것 변경 가능한 필드의 관점에서 등가 정의 참조 ). 특정 (일반적이지 않은) 페어 클래스의 경우 프로그래머는 A와 B를 불변으로 신중하게 선택하여 불변성을 보장 할 수 있습니다.
어쨌든 @PeterLawrey의 답변 (java 1.7)에서 generic의 경고를 지우십시오.
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)
내 의견으로는 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의 예는 다음과 같습니다.
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));
이것은 좋지만 이번에는 비교할 수없는 유형을 쌍의 유형 인수로 사용할 수 없습니다. 일부 유틸리티 클래스에서는 쌍에 대해 많은 비교기를 사용할 수 있지만 C ++ 사람들은 그것을 얻지 못할 수 있습니다. 또 다른 방법은 유형 인수에 대해 다른 범위를 가진 유형 계층 구조에서 많은 클래스를 작성하는 것이지만 가능한 범위와 조합이 너무 많습니다.
JavaFX와 함께 제공되는 JavaFX에는 Pair <A, B> 클래스가 있습니다.
hashCode()
. Java 자체는이 메소드를 호출하지 않습니다. 라이브러리를 포함한 사용자 코드 용입니다.
다른 많은 사람들이 이미 언급했듯이 Pair 클래스가 유용한 지 여부는 실제로 유스 케이스에 달려 있습니다.
개인 도우미 기능의 경우 코드를 더 읽기 쉽게 만들고 모든 보일러 플레이트 코드로 또 다른 가치 클래스를 만들려는 노력이 없다면 Pair 클래스를 사용하는 것이 합법적이라고 생각합니다.
반면에 추상화 수준에서 두 객체 또는 값이 포함 된 클래스의 의미를 명확하게 문서화해야하는 경우 클래스를 작성해야합니다. 일반적으로 데이터가 비즈니스 오브젝트 인 경우입니다.
항상 그렇듯이 숙련 된 판단이 필요합니다.
두 번째 질문은 Apache Commons 라이브러리의 Pair 클래스를 권장합니다. Java 용 확장 표준 라이브러리로 간주 될 수 있습니다.
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
비즈니스 오브젝트의 값 클래스 작성을 단순화하는 Apache Commons의 EqualsBuilder , HashCodeBuilder 및 ToStringBuilder 를 살펴볼 수도 있습니다 .
Pair
C ++에서 <> 쌍과 동일한 용도로 사용되는 javafx 유틸리티 클래스를 사용할 수 있습니다 . https://docs.oracle.com/javafx/2/api/javafx/util/Pair.html
좋은 소식 JavaFX
은 키 값 쌍을가집니다.
의존성으로 javafx를 추가하고 가져 오기 javafx.util.Pair
;
에서처럼 간단하게 사용하십시오 c++
.
Pair <Key, Value>
예 :
Pair <Integer, Integer> pr = new Pair<Integer, Integer>()
pr.get(key);// will return corresponding value
Map.Entry 인터페이스는 C ++ 쌍과 매우 가깝습니다. AbstractMap.SimpleEntry 및 AbstractMap.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>
?"라는 질문에 대답합니다 . 답은 두 가지 유형이 다른 인터페이스 빌드이며 각 유형을 반환하는 메서드가 있다는 것입니다. 의미를 더 추가하는 것은 당신에게 달려 있습니다. 당신이 위치를 사용하고 정말 당신이 코드를 표시 할 경우 예를 들어, 정의 할 수 PositionX
와 PositionY
그 포함 Integer
를 만들기 위해 Pair<PositionX,PositionY>
. JSR 308이 사용 가능한 경우 Pair<@PositionX Integer, @PositionY Ingeger>
이를 단순화하기 위해 사용할 수도 있습니다 .
편집 : 여기에 표시해야 할 한 가지는 위의 정의가 형식 매개 변수 이름과 메서드 이름과 명시 적으로 관련되어 있다는 것입니다. 이것은 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");
equals
, hashCode
그리고 toString
?
toString
두 필드 간의 관계에 대한 자세한 지식이 필요합니다.
class
단순한 것보다 더 나은 것을 제공하는 interface
것입니다.
구문 적으로 비슷하지만 Java와 C ++의 패러다임은 매우 다릅니다. Java와 같은 C ++를 작성하는 것은 나쁜 C ++이고 C ++과 같은 Java를 작성하는 것은 나쁜 Java입니다.
Eclipse와 같은 리플렉션 기반 IDE를 사용하면 "페어"클래스의 필수 기능을 작성하는 것이 빠르고 간단합니다. 클래스를 생성하고 두 개의 필드를 정의한 다음 다양한 "XX 생성"메뉴 옵션을 사용하여 몇 초 만에 클래스를 채 웁니다. Comparable 인터페이스를 원한다면 "compareTo"를 빠르게 입력해야 할 수도 있습니다.
언어에서 별도의 선언 / 정의 옵션을 사용하면 C ++ 코드 생성기가 그리 좋지 않으므로 작은 유틸리티 클래스를 작성하는 데 시간이 많이 걸립니다. 이 쌍은 템플릿이기 때문에 사용하지 않는 함수에 대해 비용을 지불 할 필요가 없으며 typedef 기능을 사용하면 의미있는 유형 이름을 코드에 할당 할 수 있으므로 "의미론 없음"에 대한 이의 제기가 실제로 보류되지 않습니다.
쌍은 복잡한 제네릭의 기본 구성 단위가되는 좋은 물건입니다. 예를 들어, 이것은 내 코드에서 온 것입니다.
WeakHashMap<Pair<String, String>, String> map = ...
Haskell 's Tuple과 동일
Pair
특별한 의미가 없습니다로 최적입니다. 명확한 개념의 명확한 이름을 갖는 것은 좋지만 "첫 번째"와 "두 번째"가 잘 작동하지 않는 이름을 찾는 것이 좋습니다.
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로 주석을 달면 주석 처리기가 값 의미를 갖는 구체적인 클래스를 생성합니다.
다음은 편의를 위해 여러 수준의 튜플이있는 라이브러리입니다.
다른 라이브러리는 적어도 Pair
튜플 .
특히, 공칭 타이핑이 아닌 많은 구조적 타이핑을 사용하는 함수형 프로그래밍의 맥락 에서 (허용 된 답변에서 옹호 된 ) 라이브러리와 튜플은 매우 편리합니다.
또 다른 간결한 롬복 구현
import lombok.Value;
@Value(staticConstructor = "of")
public class Pair<F, S> {
private final F first;
private final S second;
}
모든 Pair 구현이 두 값의 순서에 따라 속성 의미로 퍼져있는 것을 알았습니다. 한 쌍을 생각할 때 두 항목의 순서가 중요하지 않은 두 항목의 조합을 생각합니다. 다음 은 컬렉션에서 원하는 동작을 보장하기 위해 재정렬 hashCode
및 비 정렬 쌍의 구현입니다 equals
. 또한 복제 가능합니다.
/**
* 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<T, U> can still return <code>true</code> for method <code>equals</code>
* called with a Pair<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<T, U></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 <v1, v2> of
* this pair and <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<T, U> can return <code>true</code> for equality testing with
* a Pair<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;
}
}
이 구현은 단위 테스트를 거쳤으며 세트 및 맵에서의 사용을 시도했습니다.
공개 도메인에서 이것을 공개한다고 주장하지 않습니다. 이것은 응용 프로그램에서 사용하기 위해 방금 작성한 코드이므로 사용하려는 경우 주석과 이름으로 약간의 직접 복사 및 엉망을 피하십시오. 드리프트 잡기?
누구나 간단하고 사용하기 쉬운 버전을 원한다면 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 이외의 인터페이스는 단순한 인터페이스가 아닙니다.
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();
불변, 한 쌍만!
Pair<Object, Object> pair = Pair.createPair("abc", "def")
하지만 Pair.createPair((Object)"abc", (Object)"def")
코드 로 작성 해야한다고 생각 합니까?
@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); }
그러나 이것이 좋은 습관인지는 모르겠습니다
new Pair<Object, Object>("abc", "def")
내 실험에서 가장 전통적 이었습니다.
AbstractMap.SimpleEntry
복잡한가?