JavaにPair<L,R>
がないのには正当な理由がありますか?このC++構文と同等のものは何でしょうか。私はむしろ私自身の再実装を避けたいと思います。
1.6 は似たようなもの(AbstractMap.SimpleEntry<K,V>
)を提供しているようですが、これはかなり複雑です。
comp.lang.Java.help
のスレッドで、Hunter GratznerはJavaのPair
構造の存在に対していくつかの引数を与えます。主な議論は、クラスPair
が2つの値の間の関係についての意味論を伝えていないということです(どのようにして "first"と "second"が何を意味するのかわかりますか?)。
より良い方法は、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以降には、いくつかのペアクラスがあります。 http://commons.Apache.org/proper/commons-lang/apidocs/org/Apache/commons/lang3/Tuple/package-summary.html
とペアを実装する別の方法。
単純なファクトリなので、型を指定する必要はありません。例えば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の要素からなるTupleクラスを提供します。
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)
AndroidはPair
class( 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);
}
}
それはあなたがそれを何に使いたいかによって異なります。これを行う一般的な理由は、マップを反復処理することです。そのためには、単純にこれを行います(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());
}
最大の問題は、おそらくAとBの不変性を保証できないことです( 型パラメーターが不変であることを確認する方法 を参照)。したがって、hashCode()
は同じペアafterは、たとえばコレクションに挿入されます(これにより、未定義の動作が発生します。 可変フィールドに関する等号の定義 を参照)。特定の(非ジェネリック)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 Java
はキー値Pairを追加しました。
javafx.util.Pair
をインポートするだけです。
c++
のように単純に使用します。
Pair < Key , Value >
例えば.
Pair < Integer , Integer > pr = new Pair<Integer , Integer>()
pr.get(key); // will return corresponding value
他の多くの人がすでに述べたように、Pairクラスが役に立つかどうかは、実際にはユースケースに依存します。
プライベートヘルパー関数では、Pairクラスを使用してコードを読みやすくし、そのボイラープレートコードをすべて使用してさらに別の値クラスを作成する努力に値しない場合は、Pairクラスを使用することがまったく合法です。
一方、抽象化レベルで、2つのオブジェクトまたは値を含むクラスのセマンティクスを明確に文書化する必要がある場合は、そのクラスを作成する必要があります。通常、データがビジネスオブジェクトの場合がそうです。
いつものように、それは熟練した判断を必要とします。
2番目の質問には、Apache CommonsライブラリーのPairクラスをお勧めします。これらは、Java用の拡張標準ライブラリと見なされる可能性があります。
https://commons.Apache.org/proper/commons-lang/apidocs/org/Apache/commons/lang3/Tuple/Pair.html
また、Apache Commonsの EqualsBuilder 、 HashCodeBuilder 、および ToStringBuilder を参照して、ビジネスオブジェクトの値クラスを簡単に記述することもできます。
JavafxユーティリティクラスPair
を使用できます。これは、c ++のpair <>と同じ目的で使用できます。 https://docs.Oracle.com/javafx/2/api/javafx/util/Pair.html
JavaFX(Java 8にバンドルされています)にはPair <A、B>クラスがあります。
私の考えでは、Javaにペアはありません。ペアに追加の機能を直接追加する場合(たとえば、比較可能)、型をバインドする必要があるためです。 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));
型引数が比較可能かどうかのコンパイル時チェックと比較可能な例:
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の型引数として非比較型を使用することはできません。あるユーティリティクラスでは、ペアのためにたくさんのComparatorsを使うかもしれませんが、C++の人々はそれを手に入れないかもしれません。もう1つの方法は、型引数にさまざまな境界を使用して型階層内に多数のクラスを記述することですが、使用できる境界とその組み合わせが多すぎます...
Collections.singletonMap(left, rigth);
Map.Entry インターフェイスはc ++のペアにかなり近づいています。 AbstractMap.SimpleEntry およびAbstractMap.SimpleImmutableEntryのような具体的な実装を見てください。最初の項目はgetKey()で、2番目の項目はgetValue()です。
構文的には似ていますが、JavaとC++はまったく異なるパラダイムを持ちます。 JavaのようにC++を書くのは悪いC++であり、C++のようにJavaを書くのは悪いJavaです。
EclipseのようなリフレクションベースのIDEを使うと、 "pair"クラスの必然的な機能を書くのは速くて簡単です。クラスを作成し、2つのフィールドを定義し、ほんの数秒でクラスに記入するためのさまざまな "Generate XX"メニューオプションを使用します。もしあなたがComparableインターフェースを望んでいるのであれば、あなたは "compareTo"を素早く入力しなければならないでしょう。
C++コードジェネレータの言語での宣言/定義オプションを別にしてもそれほど良くないので、小さなユーティリティクラスを手書きするのは時間がかかります。ペアはテンプレートなので、使用しない関数の代金を払う必要はありません。typedef機能を使用すると、意味のある型名をコードに割り当てることができます。そのため、「意味がない」という異論は実際には起こりません。
Java言語の性質によると、私は人々が実際にはPair
を必要としていないと思います、通常インターフェースは彼らが必要とするものです。これが一例です。
interface Pair<L, R> {
public L getL();
public R getR();
}
したがって、人々が2つの値を返したいとき、彼らは以下をすることができます:
... //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>
の意味は何ですか?」という質問に答えます。答えは、これは2つ(異なる場合もあります)のタイプを持つインターフェース構築であり、それぞれを返すメソッドがあります。それにさらに意味を追加するのはあなた次第です。たとえば、Positionを使用していて、コード内でそれを本当に指定したい場合は、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");
GoogleのAutoValueライブラリ - https://github.com/google/auto/tree/master/value を使用できます。
非常に小さい抽象クラスを作成し、それに@AutoValueというアノテーションを付けると、アノテーションプロセッサによって値の意味を持つ具象クラスが生成されます。
ここにあなたの便宜のために複数の程度のタプルを持っているいくつかのライブラリがあります:
他のライブラリは少なくともPair
Tupleを含むと言われています。
具体的には、名義型ではなく構造化型を多く使用する関数型プログラミングの場合( 受け入れられた答えで提唱されているように )、それらのライブラリとそのタプルは非常に便利です。
ペアは、複雑なジェネリック医薬品の基本的な構成単位になるのに適しています。たとえば、これは私のコードからです。
WeakHashMap<Pair<String, String>, String> map = ...
Haskellのタプルと全く同じです
Javaのようなプログラミング言語の場合、データ構造のようなペアを表すためにほとんどのプログラマーによって使用される代替データ構造は2つの配列であり、データは同じインデックスを介してアクセスされます。
例: http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080
データをまとめてバインドする必要があるため、これは理想的ではありませんが、かなり安いこともわかります。また、あなたのユースケースが座標を格納することを要求しているなら、あなた自身のデータ構造を構築することがより良いです。
私の図書館ではこんな感じです
public class Pair<First,Second>{.. }
Devoxx'14でのQAセッション中、Brian Goetz、Paul Sandoz、Stuart Marks なぜ説明 。
value types が導入されれば、標準ライブラリにジェネリックペアクラスを持つことは技術的債務となるでしょう。
以下も参照してください。 Java SE 8にはペアとタプルがありますか?
別の簡潔なロンボクの実装
import lombok.Value;
@Value(staticConstructor = "of")
public class Pair<F, S> {
private final F first;
private final S second;
}
簡単な方法Object [] - 次元として使うことができる
com.Sun.tools.javac.util.Pairはペアの単純な実装です。それはjdk1.7.0_51\lib\tools.jarにあります。
Org.Apache.commons.lang3.Tuple.Pair以外は、単なるインターフェースではありません。
私はここに散らばっているすべてのペアの実装が2つの値の順序に意味を意味することに気づいた。私がペアについて考えるとき、私は2つの順序が重要ではない2つの項目の組み合わせを考えます。これが私の順序付けられていないペアの実装です。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;
}
}
この実装は適切に単体テストされており、SetおよびMapでの使用が試行されています。
私はこれをパブリックドメインで公開すると主張していないことに注意してください。これは私がアプリケーションで使用するために作成したコードです。そのため、使用する予定がある場合は、直接コピーを作成してコメントや名前を少し変更しないでください。私のドリフトをキャッチ?
誰もがシンプルで使いやすいバージョンを望んでいるなら、私は https://github.com/lfac-pt/Java-Pair で私を利用可能にしました。また、改善も大歓迎です。
多くの人がMapのキーとして使えるPair
コードを投稿しています...ハッシュキーとしてペアを使用しようとしている場合(一般的な慣用句)、必ずGuavaのTable<R,C,V>
: http:/をチェックしてください。 /code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table 。それらはグラフの辺のために以下の使用例を与える:
Table<Vertex, Vertex, Double> weightedGraph = HashBasedTable.create();
weightedGraph.put(v1, v2, 4);
weightedGraph.put(v1, v3, 20);
weightedGraph.put(v2, v3, 5);
weightedGraph.row(v1); // returns a Map mapping v2 to 4, v3 to 20
weightedGraph.column(v3); // returns a Map mapping v1 to 20, v2 to 5
Table
は2つのキーを単一の値にマッピングし、両方のタイプのキーだけでも効率的な検索を提供します。私は私のコードの多くの部分でMap<Pair<K1,K2>, V>
の代わりにこのデータ構造を使い始めました。独自の中間マップクラスを指定するオプションを使用して、密な用途と疎な用途の両方に対して配列、ツリー、その他の実装があります。
@ Andreas Kreyによる答えは実際には良いものです。 Javaが困難にしているものは何でも、おそらくしてはいけません。
私の経験では、Pairの最も一般的な使用方法は、メソッドからの複数の戻り値と、ハッシュマップ内のVALUES(多くの場合は文字列でインデックス付けされている)です。
後者の場合、私は最近、このようなデータ構造を使用しました。
class SumHolder{MyObject trackedObject, double sum};
あなたの「Pair」クラス全体があり、一般的な「Pair」とほぼ同じ量のコードがありますが、わかりやすい名前が付いています。それはそれが使用するメソッドの中でインラインで定義することができ、パブリック変数などに関する典型的な問題を排除します。言い換えれば、それはこの使用法のためのペアよりも絶対的に優れており(名前付きのメンバーによる)、さらに悪いことではありません。
ハッシュマップのキーに実際に "Pair"が必要な場合は、基本的に二重キーインデックスを作成しています。私はこれが "ペア"がかなり少ないコードである1つのケースであるかもしれないと思います。 Eclipseがあなたの小さなデータクラスにequals/hashを生成させることができるのでそれほど簡単ではありませんが、もっと多くのコードになるでしょう。ここでペアは簡単な解決策になりますが、もしあなたが二重インデックスのハッシュが必要なら誰があなたがnインデックスのハッシュを必要としないと言っているのですか?データクラスソリューションはスケールアップします、ペアはあなたがそれらを入れ子にしない限りしません!
そのため、メソッドから戻る2番目のケースは少し難しくなります。あなたのクラスはより多くの可視性を必要とします(呼び出し側もそれを見る必要があります)。メソッドの外側で、クラスの内側で上記とまったく同じように定義できます。その時点で、メソッドはMyClass.SumHolderオブジェクトを返すことができるはずです。呼び出し側は、単に「ペア」ではなく、返されたオブジェクトの名前を見ることができます。パッケージレベルの「デフォルト」のセキュリティはかなり優れていることに再度注意してください - それはあなたがあまりにも多くのトラブルに陥るべきではないことを十分に制限しています。とにかく "ペア"オブジェクトよりも優れています。
私がペアの使用を見ることができる他のケースはあなたの現在のパッケージの外の呼び出し側のための戻り値を持つパブリックAPIです。このために、私は真のオブジェクトを作成します - できれば不変です。最終的には呼び出し側がこの戻り値を共有し、それを変更可能にすることは問題になる可能性があります。これは、Pairオブジェクトが悪化しているもう1つのケースです。ほとんどのペアを不変にすることはできません。
これらすべてのケースに対するもう1つの利点 - Javaクラスが拡張され、私のsumクラスには2回目の合計と "Created"フラグが必要になるまでに必要でした。ペアは理にかなっていました、4つの値を持つ私のクラスはまだ少なくとも同じくらい理にかなっています。
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();
不変、ペアだけ!
Lombok の新しいバージョンでは、そのかわいいクラスをコンパイルできます。
@Value(staticConstructor = "of") public class Pair <E> {
E first, second;
}
そしてPair<Value> pairOfValues = Pair.of(value1, value2);
のように使います。