質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

5回答

11426閲覧

複数のListを比較する方法

lupus_dingo

総合スコア257

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2014/12/07 06:59

List<String>で定義した変数が10個(list01~list10)あるとします。

これらリストすべての要素をチェックして、共通の要素を抜き出したいのですが
一番簡潔に行うにはどのように処理を組み立てればよいでしょうか?
ちなみに要素が1つもないNULLのListも含まれています。

私が考えた方法は以下の通りです。

List<String> commonList = new ArrayList<String>(); //共通要素が入る
// list01に要素が含まれる場合
if( list01 != null ){
for(int i=0; i<list01.size(); i++){
if( list02.contains(list01.get(i))
&& list03.contains(list01.get(i))
&& list04.contains(list01.get(i))
&& list05.contains(list01.get(i))
&& list06.contains(list01.get(i))
&& list07.contains(list01.get(i))
&& list08.contains(list01.get(i))
&& list09.contains(list01.get(i))
&& list10.contains(list01.get(i))
){
commonList.add(i);
}
}
}
// list01はnullだがlist02に要素が含まれる場合
if( commonList.size() == 0 && list02 != null ){
for(int i=0; i<list02.size(); i++){
if( list01.contains(list02.get(i))
&& list03.contains(list02.get(i))
&& list04.contains(list02.get(i))
&& list05.contains(list02.get(i))
&& list06.contains(list02.get(i))
&& list07.contains(list02.get(i))
&& list08.contains(list02.get(i))
&& list09.contains(list02.get(i))
&& list10.contains(list02.get(i))
){
commonList.add(i);
}
}
}
// list01、list02はnullだがlist03に要素が含まれる場合
if( commonList.size() == 0 && list03 != null ){
省略
}
以下同様


このやり方だと比較するListが増えるたびにコードも増えて修正もしづらくなってしまいます。
もっと簡単に行える方法はないでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

Setに突っ込んで積集合を取る。

参考:Setインターフェース

retainsAllで積集合を取れるので、それを繰り返せばよいと思います。

投稿2014/12/07 07:56

ShinpeiYamamoto

総合スコア540

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2014/12/08 10:53

回答ありがとうございます。 コレクションはarrayListとMapしか使ったことがないのでsetについて調べてみます。便利なメソッドがあるんですね。
swordone

2016/11/24 02:08

ListにもretainAllメソッドはあるのでListのままでもできます。
guest

0

すべてのリストの要素をまとめて、Comparatorを作ってソートするなんてどうでしょうか?

List<String> allList = new ArrayList<String>()
allList.addAll(list01);
allList.addAll(list02);
(省略)

Comparator<String> comp = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
Collections.sort(allList , comp); // ソート処理

ソートしたものをループで見て、
同じ要素が元々のリストの数(例だと10個)続いていれば、
ずべてのリストに存在する共通要素となります。

内部でまわすループ数は他と大して変わりませんが、
Comparatorを作ればソースはかなり簡潔になると思います。

投稿2014/12/08 02:25

runun

総合スコア305

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2014/12/09 06:32

Comparatorは初めて聞きました。 というか、こんな形のインスタンスの生成の仕方を初めてみました。 確かにきれいに見えますね。 勉強になります。
guest

0

Javaはずいぶん触っていないので、Javascriptでサンプルを書いてみました。

lang

1var list01 = [1,2,3,4,5]; 2var list02 = [1,2,3,4,5]; 3var list03 = [1,2,3,4,5]; 4var list = [list01,list02,list03]; 5 6var buf = {}; // hash map, 重複比較用 7var result =[]; // 重複要素格納用 8 9for(val in list){ 10 for(val2 in list[val]){ 11 // bufに探索キーが存在しなければ、bufにキーを追加 12 if(buf[val2] === undefined){ 13 // key追加。値はなんでも良い。 14 buf[val2] = 1; 15 } else { 16 // 重複したキーが存在する場合、結果Arrayに格納 17 result.push(val2); 18 } 19 } 20} 21 22// 終了時にはresultに重複する要素が全て格納されている 23console.log(JSON.stringify(result));

まず、List01~List10は、argiusさんの様に一つのリストに格納します。
次に、このリストを2重のforで、最終要素まで一気に探索します。
その際、連想配列(たぶんJavaではHashMap?)に最終要素をキーとして値を入れます。
キーが存在しなければ、連想配列に追加し、キーが存在する場合は結果用ArrayListに追加します。

この様にすると、一見無駄に複雑化している様に見えるかもしれませんが、
全要素数 * 1の比較回数で、全ての重複要素を抜き出す事が可能です。
また、HashMapのキー探索は非常に高速なので、このやり方であれば数千万要素程度までなら一瞬で探索できるはずです。

Javaで説明できなくて申し訳ないですが、ご参考になれば幸いです。

投稿2014/12/07 09:33

utun

総合スコア384

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2014/12/08 11:08

回答ありがとうございます。 jsもたまに作る必要があるので助かります。パフォーマンスを考えたらListよりもHashMapの方がいいみたいですね。
guest

0

ベストアンサー

処理概要だけを述べます。

  1. 2 つの list の共通部分を list で返すメソッドを定義します。
    List<String> get_common(List<String> l1, List<String>l2) {
    ...
    }
    l1 や l2 が null の場合も考慮して実装します。
    さらに l1, l2 の要素数が少ない方で ループを回すなどの工夫をしても良いかもしれません。

  2. List2, ... List10 を Lists[0] .. Lists[8] に代入しておきます。
    (面倒なら、 list1, ... list10 を lists[0], .. lists[0] に代入しても構いません。)

  3. List<String> ans = list1;
    for (List<String> list:Lists) {
    ans = get_common(ans, list);
    if (ans.isEmpty()) {
    break;
    }
    }
    として、ループを抜けた時点で ans には list1, ... list10 の共通要素が設定されています。

投稿2014/12/07 08:47

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2014/12/08 11:04

回答ありがとうございます。 拡張for文でListごとループができるのですね。勉強になりました。自分の中ではこの方法が一番理解しやすかったです。
guest

0

list01nullの場合、list02の中でlist01.containsを呼び出すとNullPointerExceptionになってしまいますね。
そこをどうすれば良いのか分かりませんでしたので、まずは「リストがnullの場合は含まれるのと同じにカウントする」という前提で考えてみました。

リストのリストを作れば、リストの数が増えても同じように処理できます。

以下のサンプルコードでは、お望みのものとは動作が異なるかもしれませんが、ここではリストが増えてもコードがほとんど増えないようにする点だけを参考にしてください。

lang

1// Java5以降 2 3// import java.util.*; 4 5List<String> list01 = ... ; 6List<String> list02 = ... ; 7List<String> list03 = ... ; 8 9List<List<String>> a = new ArrayList<List<String>>(); 10Collections.addAll(a, list01, list02, list03); 11 12List<String> commonList = new ArrayList<String>(); 13for (List<String> list : a) { 14 if (list != null) { 15 for (String s : list) { 16 int count = 1; 17 for (List<String> listB : a) { 18 if (listB == list) 19 continue; 20 if (listB == null || listB.contains(s)) 21 ++count; 22 } 23 if (count == a.size()) // nullでないすべてのlistに含まれていた 24 commonList.add(s); 25 } 26 } 27}

投稿2014/12/07 08:15

argius

総合スコア9388

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2014/12/08 10:58

回答ありがとうございます。 ListにListを代入するという発想がなかったので、勉強になりました。参考にさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問