web-dev-qa-db-ja.com

Javaでペアまたは2タプルを使用する

Javaでの私のHashtableはTuple構造を持つ値から利益を得るでしょう。そのためにJavaで使用できるデータ構造は何ですか?

Hashtable<Long, Tuple<Set<Long>,Set<Long>>> table = ...
277
syker

Javaには汎用のTupleクラスがあるとは思いませんが、カスタムのものは次のように簡単な場合があります。

public class Tuple<X, Y> { 
  public final X x; 
  public final Y y; 
  public Tuple(X x, Y y) { 
    this.x = x; 
    this.y = y; 
  } 
} 

もちろん、インスタンスをハッシュ化のキーとして使用する予定の場合は特に、等価性、不変性などに関してこのクラスを設計する方法には、いくつか重要な影響があります。

290
maerics

javatuples はJavaのタプル専用のプロジェクトです。

Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)
156
Daniel

Apache Commons は、 Pair を含む一般的なJavaユーティリティをいくつか提供していました。 Map.EntryComparableSerializableを実装しています。

86
rhgb

組み込みのJava 2要素Tupleを探しているなら、AbstractMap.SimpleEntryを試してください。

49
at7000ft

@maericsへの拡張として、いい答えですが、私はいくつかの便利なメソッドを追加しました:

public class Tuple<X, Y> { 
    public final X x; 
    public final Y y; 
    public Tuple(X x, Y y) { 
        this.x = x; 
        this.y = y; 
    }

    @Override
    public String toString() {
        return "(" + x + "," + y + ")";
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }

        if (!(other instanceof Tuple)){
            return false;
        }

        Tuple<X,Y> other_ = (Tuple<X,Y>) other;

        // this may cause NPE if nulls are valid values for x or y. The logic may be improved to handle nulls properly, if needed.
        return other_.x.equals(this.x) && other_.y.equals(this.y);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((x == null) ? 0 : x.hashCode());
        result = prime * result + ((y == null) ? 0 : y.hashCode());
        return result;
    }
}
36
Aram Kocharyan

さらに2セント:Java 7以降、標準Libにこのクラスが追加されました:javafx.util.Pair。

そしてはい、それは標準的なJavaです、今やJavaFxはJDKに含まれています:)

29
Teocali

これとまったく同じ質問が他の場所にあります。これには、より堅牢なequalshashが含まれています。

http://groups.google.com/group/comp.lang.Java.help/browse_thread/thread/f8b63fc645c1b487/1d94be050cfc249b

この議論では、「このような状況に遭遇するたびに、クラスTupleを不特定の名前で再利用するか、新しいクラスを特定の名前で作成する必要があるか」というメリック対ColinDのアプローチを反映しています。何年も前に私は後者のキャンプにいました。私は前者をサポートするように進化しました。

17
not-just-yeti

Androidタプルユーティリティ

このオブジェクトはequals()の実用的な実装を提供し、equals()が含まれている各オブジェクトでtrueの場合にtrueを返します。

7
see2851

lombok を使うとPairクラスを宣言するのは簡単です:

@Data(staticConstructor = "of")
public class Pair<A, B> {
    private final A left;
    private final B right;
}

これはgetter、 "of"という名前の静的コンストラクタ、equals()hashcode()toString()を生成します。

詳細については @Data のドキュメントを参照してください。

7
user180100

実際にモデル化している概念を説明するクラスを作成してそれを使用します。それはただ2つのSet<Long>を格納してそれらにアクセサを提供することができますが、それらの各セットが正確に何であるか、そしてそれらが一緒にグループ化されている理由を示すために命名されるべきです。

6
ColinD

@ maericsの答えを補足するために、これがComparableタプルです。

import Java.util.*;

/**
 * A Tuple of two classes that implement Comparable
 */
public class ComparableTuple<X extends Comparable<? super X>, Y extends Comparable<? super Y>>
       extends Tuple<X, Y>
       implements Comparable<ComparableTuple<X, Y>>
{
  public ComparableTuple(X x, Y y) {
    super(x, y);
  }

  /**
   * Implements lexicographic order
   */
  public int compareTo(ComparableTuple<X, Y> other) {
    int d = this.x.compareTo(other.x);
    if (d == 0)
      return this.y.compareTo(other.y);
    return d;
  }
}
5

この記事は今ではかなり古くなっていますが、あまり役に立ちませんが、その作業はここで行われていると思います: http://www.pds.ewi.tudelft.nl/pubs/papers/cpe2005。 pdf 、Javaのメインストリームではナイスだったでしょう。

次のようなことができます。

int a;
char b;
float c;
[a,b,c] = [3,'a',2.33];

または

[int,int,char] x = [1,2,'a'];

または

public [int,boolean] Find(int i)
{
  int idx = FindInArray(A,i);
  return [idx,idx>=0];
}

[idx, found] = Find(7);

タプルは次のとおりです。

  • プリミティブ型として定義 - テンプレート/総称なし
  • ローカルで宣言されている場合はスタック割り当て
  • パターンマッチングを使用して割り当て

このアプローチは増加します

  • パフォーマンス
  • 読みやすさ
  • 表現力
4

私はJavaのタプルについての一般的な観点から始めて、あなたの具体的な問題への含意で終わります。

1)タプルが非ジェネリック言語で使用される方法は、タイプセーフではないため、Javaでは避けられています(例えばPythonではTuple = (4, 7.9, 'python'))。それでも汎用Tuple( 推奨されない )のようなものを使用したい場合は、Object[]またはList<Object>を使用し、型安全性を保証するためにinstanceofを使用して要素をキャストしてください。

通常、特定の設定のタプルは、常に同じ構造を含むことで同じ方法で使用されます。 Javaでは、明確に定義されたタイプセーフな値とメソッドを提供するために、この構造体をclassに明示的に定義する必要があります。これは最初は厄介で不必要なようですが、 compile-time でエラーを防ぐことができます。

2)同じ(スーパー)クラスFooを含むTupleが必要な場合は、Foo[]List<Foo>、またはList<? extends Foo>(またはリストの不変の同等物)を使用してください。タプルは定義された長さではないので、この解決策は同等です。

3)あなたの場合、あなたはPair(すなわち、明確に定義された長さのTuple 2)を必要としているようです。将来的にコードを再利用することができるので、これはmaericsの答えまたは補足的な答えの1つを最も効率的にします。

2
Mario Reutter

Google Guava Table を使用できます

2
Ste