1つのリストに他のリストの要素が含まれているかどうかを確認する


105

オブジェクトが異なる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;
}

しかし、私はこれを行うより良い、より速い方法があると思います:)誰かがそれを提案できますか?

ありがとう!


まず、found = trueに設定すると、その後、単に壊します。またはループから抜け出す
jsist

stackoverflow.com/questions/5187888/…。さらに、高速検索を行うには、バイナリ検索を使用して、状況に合わせてDSを変更してください...
jsist

彼らはオブジェクトのほかに共通の親を共有しますか?
Woot4Moo

@ Woot4Mooいいえ、彼らはしません
Ned

回答:


219

基本的な等価性をテストするだけでよい場合は、1行の入力リストを変更せずに、基本的なJDKでこれを行うことができます。

!Collections.disjoint(list1, list2);

特定のプロパティをテストする必要がある場合、それは困難です。デフォルトでは、

list1.stream()
   .map(Object1::getProperty)
   .anyMatch(
     list2.stream()
       .map(Object2::getProperty)
       .collect(toSet())
       ::contains)

...で個別の値を収集list2list1、存在するかどうか各値をテストします。


1
どちらも2つの異なるオブジェクトであるため、これは常にfalseを返しませんか?
Venki

2
いいえ?2つのコレクションの間に互いにequals()のオブジェクトがないかどうかをテストします。
Louis Wasserman、2014

13
また、リストの場合、これはO(n * m)になることに注意してください。比較list1するSet前にコピーしたい場合は、追加のRAMを犠牲にしてO(n)+ O(m)、つまりO(n + m)を取得します。それは速度かメモリかを選択する問題です。
Haroldo_OK 2016年

これは、「List <Person> list1; List <Person> list2」の場合にのみ機能し、List <Person> list1;のような2つの異なるオブジェクトまたはデータ型では機能しません。List <従業員> list2。
whoami 2018

もちろん、これはそれらのシナリオ@Zephyrでは機能しません。質問に対しては、正しいイコールが実装されている限り、完全に機能します。それがすべての問題です!
Syed Siraj Uddin

38

Apache Commons CollectionUtilsを使用できます。

if(CollectionUtils.containsAny(list1,list2)) {  
    // do whatever you want
} else { 
    // do other thing 
}  

これは、カスタムオブジェクトのequals機能が適切にオーバーロードされていることを前提としています。


9
それは4年になります。また、パッケージと機能を明示的に呼び出します。
Woot4Moo

1
jdkのみのソリューションがある場合のApache Commonsへの反対投票
ohcibi 2017年

9
@ohcibi Javaにもロガーが組み込まれています。Log4jとLog4j2を使用していることを提案している人に投票してください。
Woot4Moo 2017年

1
@ Woot4Mooそれは依存します。OP4の問題を解決するためにLog4jを使用する理由がある場合、反対票を投じる理由はありません。この場合、Apacheコモンズは、Apacheコモンズを示唆する回答の99%のように、単に役に立たない膨らみになります。
ohcibi 2017年

1
@ohcibiですが、Apacheコモンズをすでに使用している場合、それは実際には大したことではありません。これは良い答えでした。
vab2048

19

Narendraのロジックを短くするには、これを使用できます。

boolean var = lis1.stream().anyMatch(element -> list2.contains(element));

3
この答えは過小評価されています。
Kervvv

:あなたがしたい場合は、もう少しそれを短縮することができますlist1.stream().anyMatch(list2::contains);
tarka

9

ある一つの方法Collection命名はretainAllなく、いくつかの持つ副作用あなたのためのリファレンスを

指定されたコレクションに含まれているこのリストの要素のみを保持します(オプションの操作)。つまり、指定されたコレクションに含まれていないすべての要素をこのリストから削除します。

呼び出しの結果としてこのリストが変更された場合はtrue

そのような

boolean b = list1.retainAll(list2);

5

Loiusの答えは正しいです。例を追加したいだけです。

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

1
要素 'A'を2番目のリストに追加すると、listTwo.add( "A"); Collections.disjoint(listOne、listTwo);にもかかわらず trueを返します。
サイラムクカダラ2017年

2

より高速な方法では、追加のスペースが必要になります。

例えば:

  1. 1つのリストのすべての項目をHashSetに入れます(object.getAttributeSame()を使用するには、自分でハッシュ関数を実装する必要があります)

  2. 他のリストに目を通し、HashSetに項目があるかどうかを確認します。

このようにして、各オブジェクトは最大で1回アクセスされます。また、HashSetはO(1)のオブジェクトをチェックまたは挿入するのに十分な速度です。


2

のJavaDocによると.contains(Object obj)

リストに指定された要素が含まれている場合はtrueを返します。より正式には、このリストに少なくとも1つの要素e(o == null?e == null:o.equals(e))が含まれている場合にのみtrueを返します。

したがって.equals()、指定したオブジェクトのメソッドをオーバーライドすると、次のことができるはずです。if(list1.contains(object2))...

要素が一意になる(つまり、属性が異なる)場合は、.equals()および.hashcode()をオーバーライドして、すべてをに格納 できますHashSets。これにより、一定の時間内に別の要素が含まれているかどうかを確認できます。


2

速くするために、休憩を追加できます。こうすると、foundが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つのマップの値をすばやくチェックできます。


こんにちはトム、気づいてくれてありがとう!はい、入力中に「中断」を忘れました。しかし、私はおそらくいくつかのアルゴリズムがあるか、またはこれらのリストを他のコレクションに変更する必要があると考えていました。
ネッド

O(n * m)より良いものはありませんか?
Woot4Moo 2013年

.getAttributeSame()?
Mavenのツ

Object1およびObject2からのメソッドgetAttributeSame()の実装は提供されていませんが、質問と回答には関係ありません。両方のクラスが持つ属性(attributeSame、Long)を返すだけです。
トム

0

保持するデータのタイプを定義できますか?ビッグデータですか?ソートされていますか?データに応じて、さまざまな効率化アプローチを検討する必要があると思います。

たとえば、データが大きく、並べ替えられていない場合、2つのリストをインデックスで繰り返し処理して、各リスト属性を別のリストヘルパーに格納できます。次に、ヘルパーリストの現在の属性でクロスチェックできます。

幸運を

編集:と等しいオーバーロードをお勧めしません。これは危険で、おそらくオブジェクトoopの意味に反しています。



0

を使用するとjava 8、次のようにして、1つのリストに他のリストの要素が含まれているかどうかを確認できます

boolean var = lis1.stream().filter(element -> list2.contains(element)).findFirst().isPresent();

0

要素がリストに存在するかどうかを確認する場合は、containsメソッドを使用します。

if (list1.contains(Object o))
{
   //do this
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.