[java] Java 값 쌍 모음? (튜플?)

예를 들어 Java에 맵의 각 항목 유형을 정의 할 수있는 Map이있는 방법이 좋습니다 <String, Integer>.

내가 찾고있는 것은 컬렉션의 각 요소가 값 쌍인 컬렉션 유형입니다. 쌍의 각 값은 선언시 정의 된 고유 한 유형 (위의 문자열 및 정수 예제)을 가질 수 있습니다.

컬렉션은 주어진 순서를 유지하며 값 중 하나를 맵에서와 같이 고유 키로 취급하지 않습니다.

본질적으로 유형의 ARRAY <String,Integer>또는 다른 2 가지 유형 을 정의 할 수 있기를 원합니다 .

나는 2 개의 변수만으로 클래스를 만들 수는 있지만 지나치게 장황한 것처럼 보입니다.

또한 2D 배열을 사용할 수 있다는 것을 알고 있지만 사용해야하는 다른 유형으로 인해 OBJECT 배열을 만들어야하며 항상 캐스팅해야합니다.

컬렉션에 쌍만 저장하면되므로 항목 당 두 개의 값만 필요합니다. 수업 경로를 거치지 않고 이와 같은 것이 있습니까? 감사!



답변

Pair 클래스는 독자적으로 작성하기에 충분히 쉬운 “gimme”제네릭 예제 중 하나입니다. 예를 들어, 내 머리 꼭대기에서 :

public class Pair<L,R> {

  private final L left;
  private final R right;

  public Pair(L left, R right) {
    assert left != null;
    assert right != null;

    this.left = left;
    this.right = right;
  }

  public L getLeft() { return left; }
  public R getRight() { return right; }

  @Override
  public int hashCode() { return left.hashCode() ^ right.hashCode(); }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Pair)) return false;
    Pair pairo = (Pair) o;
    return this.left.equals(pairo.getLeft()) &&
           this.right.equals(pairo.getRight());
  }

}

그리고 네, 이것은 다양한 정도의 완성도와 기능으로 인터넷의 여러 곳에 존재합니다. (위의 예는 변경 불가능합니다.)


답변

AbstractMap.SimpleEntry

당신이 이것을 쉽게 찾고 있습니다 :

java.util.List<java.util.Map.Entry<String,Integer>> pairList= new java.util.ArrayList<>();

당신은 어떻게 그것을 채울 수 있습니까?

java.util.Map.Entry<String,Integer> pair1=new java.util.AbstractMap.SimpleEntry<>("Not Unique key1",1);
java.util.Map.Entry<String,Integer> pair2=new java.util.AbstractMap.SimpleEntry<>("Not Unique key2",2);
pairList.add(pair1);
pairList.add(pair2);

이것은 다음을 단순화합니다.

Entry<String,Integer> pair1=new SimpleEntry<>("Not Unique key1",1);
Entry<String,Integer> pair2=new SimpleEntry<>("Not Unique key2",2);
pairList.add(pair1);
pairList.add(pair2);

그리고,의 도움으로 createEntry 방법 같이 자세한 정보를 줄일 수 있습니다.

pairList.add(createEntry("Not Unique key1", 1));
pairList.add(createEntry("Not Unique key2", 2));

ArrayList최종적이지 않기 때문에 of메소드 (및 언급 된 createEntry메소드) 를 노출하도록 서브 클래스 화 될 수 있으므로 구문 상 간결합니다.

TupleList<java.util.Map.Entry<String,Integer>> pair = new TupleList<>();
pair.of("Not Unique key1", 1);
pair.of("Not Unique key2", 2);


답변

자바 9+

Java 9에서는 간단히 다음과 같이 쓸 수 있습니다 Map.entry(key, value)
. 불변 쌍을 만듭니다.

참고 : 이 방법은 키나 값을 null로 허용하지 않습니다. 예를 들어 null 값을 허용하려면 이것을 다음과 같이 변경하십시오 Map.entry(key, Optional.ofNullable(value)).


자바 8+

Java 8에서는보다 일반적인 용도 javafx.util.Pair를 사용하여 불변의 직렬화 가능 쌍을 작성할 수 있습니다. 이 클래스 null 키와 null 값을 허용합니다. (Java 9에서이 클래스는 javafx.base모듈에 포함되어 있습니다 ). 편집 : Java 11부터 JavaFX가 JDK에서 분리되었으므로 추가 maven 아티팩트 org.openjfx : javafx-base가 필요합니다.


자바 6+

Java 6 이상 AbstractMap.SimpleImmutableEntry에서는 불변 쌍 또는 AbstractMap.SimpleEntry값을 변경할 수있는 쌍에 더 자세한 정보 를 사용할 수 있습니다. 이 클래스는 널 키와 널 값도 허용하며 직렬화 가능합니다.


기계적 인조 인간

Android 용으로 쓰고 있다면 Pair.create(key, value)불변 쌍을 만들기 위해 사용하십시오 .


아파치 커먼즈

Apache Commons LangPair.of(key, value)불변의 비교 가능한 직렬화 쌍을 만드는 데 도움이 됩니다.


이클립스 컬렉션

기본 요소가 포함 된 쌍을 사용하는 경우 Eclipse 콜렉션 는 비효율적 인 자동 복싱 및 자동 언 박싱을 피하는 매우 효율적인 기본 쌍 클래스를 제공합니다.

예를 들어, 당신은 사용할 수 PrimitiveTuples.pair(int, int)을 만들 IntIntPair거나 PrimitiveTuples.pair(float, long)을 만들 FloatLongPair.


롬복 프로젝트

Project Lombok을 사용하면 다음과 같이 간단히 작성하여 불변 쌍 클래스를 만들 수 있습니다.

@Value
public class Pair<K, V> {
    K key;
    V value;
}

롬복은 생성자, 게터에 채울 것 equals(), hashCode()그리고 toString()생성 된 바이트 코드에 자동으로 방법. 생성자 대신 정적 팩토리 메소드 (예 : a)를 원하면 Pair.of(k, v)주석을 다음과 같이 변경하십시오 @Value(staticConstructor = "of").


그렇지 않으면

위의 해결책 중 어느 것도 보트를 떠 올리지 않으면 다음 코드를 복사하여 붙여 넣을 수 있습니다 (허용 된 답변에 나열된 클래스와 달리 NullPointerExceptions을 방지합니다).

import java.util.Objects;

public class Pair<K, V> {

    public final K key;
    public final V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public boolean equals(Object o) {
        return o instanceof Pair && Objects.equals(key, ((Pair<?,?>)o).key) && Objects.equals(value, ((Pair<?,?>)o).value);
    }

    public int hashCode() {
        return 31 * Objects.hashCode(key) + Objects.hashCode(value);
    }

    public String toString() {
        return key + "=" + value;
    }
}


답변

Map.Entry

이러한 내장 클래스도 옵션입니다. 둘 다 Map.Entry인터페이스를 구현합니다 .

구현 클래스 쌍이있는 Map.Entry 인터페이스의 UML 다이어그램


답변

Apache 공통 lang3에는 Pair 클래스와이 스레드에서 언급 된 다른 라이브러리가 거의 없습니다 . Java에서 C ++ Pair <L, R>과 동등한 것은 무엇입니까?

원래 질문의 요구 사항과 일치하는 예 :

List<Pair<String, Integer>> myPairs = new ArrayList<Pair<String, Integer>>();
myPairs.add(Pair.of("val1", 11));
myPairs.add(Pair.of("val2", 17));

//...

for(Pair<String, Integer> pair : myPairs) {
  //following two lines are equivalent... whichever is easier for you...
  System.out.println(pair.getLeft() + ": " + pair.getRight());
  System.out.println(pair.getKey() + ": " + pair.getValue());
}


답변

Android를 개발하는 사람이라면 android.util.Pair 를 사용할 수 있습니다 . 🙂


답변

“Apache Commons Lang 3″은 어떤가요? Pair 클래스와 상대 서브 클래스는 어떻습니까?

    import org.apache.commons.lang3.tuple.ImmutablePair;
    import org.apache.commons.lang3.tuple.Pair;
    ...
    @SuppressWarnings("unchecked")
    Pair<String, Integer>[] arr = new ImmutablePair[]{
            ImmutablePair.of("A", 1),
            ImmutablePair.of("B", 2)};

    // both access the 'left' part
    String key = arr[0].getKey();
    String left = arr[0].getLeft();

    // both access the 'right' part
    Integer value = arr[0].getValue();
    Integer right = arr[0].getRight();

ImmutablePair는 쌍의 값을 수정할 수없는 특정 서브 클래스이지만 다른 의미를 가진 다른 구현이 있습니다. 필요한 경우 Maven 좌표입니다.

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>