異なるオブジェクトを含む2つのリストがあります。
List<Object1> list1;
List<Object2> list2;
特定の属性に基づいて、list1の要素がlist2に存在するかどうかを確認します(Object1とObject2は(特に)、1つの相互属性(Long型)、attributeSameという名前を持っています)。
今、私はこのようにします:
boolean found = false;
for(Object1 object1 : list1){
for(Object2 object2: list2){
if(object1.getAttributeSame() == object2.getAttributeSame()){
found = true;
//also do something
}
}
if(!found){
//do something
}
found = false;
}
しかし、これを行うためのより良い、より速い方法があると思います:)誰かがそれを提案できますか?
ありがとう!
基本的な同等性をテストする必要がある場合、1行の入力リストを変更せずに基本的なJDKでこれを実行できます。
!Collections.disjoint(list1, list2);
特定のプロパティをテストする必要がある場合、それは難しくなります。デフォルトでは、
list1.stream()
.map(Object1::getProperty)
.anyMatch(
list2.stream()
.map(Object2::getProperty)
.collect(toSet())
::contains)
...list2
の個別の値を収集し、list1
の各値の存在をテストします。
Apache Commons CollectionUtils を使用できます。
if(CollectionUtils.containsAny(list1,list2)) {
// do whatever you want
} else {
// do other thing
}
これは、カスタムオブジェクトのequals機能が適切にオーバーロードされていることを前提としています。
1つのメソッドCollection
という名前のretainAll
がありますが、いくつかの副作用があります 参照
指定されたコレクションに含まれるこのリスト内の要素のみを保持します(オプションの操作)。つまり、指定されたコレクションに含まれていない要素をすべてこのリストから削除します。
呼び出しの結果、このリストが変更された場合はtrue
そのような
boolean b = list1.retainAll(list2);
ルイの答えは正しいです、例を追加したいだけです:
listOne.add("A");
listOne.add("B");
listOne.add("C");
listTwo.add("D");
listTwo.add("E");
listTwo.add("F");
boolean noElementsInCommon = Collections.disjoint(listOne, listTwo); // true
ナレンドラのロジックを短縮するには、これを使用できます:
boolean var = lis1.stream().anyMatch(element -> list2.contains(element));
より高速な方法では、追加のスペースが必要になります。
例えば:
1つのリスト内のすべてのアイテムをHashSetに入れます(object.getAttributeSame()を使用するには、自分でハッシュ関数を実装する必要があります)
他のリストに目を通し、HashSetにアイテムがあるかどうかを確認します。
このようにして、各オブジェクトは最大で1回アクセスされます。また、HashSetはO(1)のオブジェクトをチェックまたは挿入するのに十分高速です。
より速くするために、ブレークを追加できます。そのように、見つかった場合にループは停止しますtrueに設定されます:
boolean found = false;
for(Object1 object1 : list1){
for(Object2 object2: list2){
if(object1.getAttributeSame() == object2.getAttributeSame()){
found = true;
//also do something
break;
}
}
if(!found){
//do something
}
found = false;
}
AttributeSameをキーとするリストの代わりにマップがある場合、2番目のマップに対応する値があるかどうかによって、1つのマップの値をより速くチェックできます。
.contains(Object obj)
のJavaDocによると:
このリストに指定された要素が含まれている場合、trueを返します。より正式には、このリストに(o == null?e == null:o.equals(e))などの要素eが少なくとも1つ含まれている場合にのみtrueを返します。
したがって、指定したオブジェクトの.equals()
メソッドをオーバーライドすると、次のことができるはずです:if(list1.contains(object2))...
要素が一意である(つまり、属性が異なる)場合は、.equals()
および.hashcode()
をオーバーライドして、すべてを HashSets
に格納できます。これにより、一定時間内に別の要素が含まれているかどうかを確認できます。
org.springframework.util.CollectionUtils
boolean containsAny(Java.util.Collection<?> source, Java.util.Collection<?> candidates)
Return true if any element in 'candidates' is contained in 'source'; otherwise returns false
Java 8
を使用すると、1つのリストに他のリストの要素が含まれているかどうかを以下のように確認できます
boolean var = lis1.stream().filter(element -> list2.contains(element)).findFirst().isPresent();
保持するデータのタイプを定義できますか?それはビッグデータですか?ソートされていますか?データに応じて異なる効率化アプローチを検討する必要があると思います。
たとえば、データが大きくソートされていない場合は、インデックスで2つのリストを繰り返し、各リスト属性を別のリストヘルパーに保存してみてください。次に、ヘルパーリストの現在の属性でクロスチェックできます。
幸運を
編集:そして私は等しいをオーバーロードすることはお勧めしません。それは危険であり、おそらくオブジェクトのoopの意味に反します。