【Java】Map使用時、keySetでSetへのaddAllは注意!?
2つのMap変数のkeyを1発で重複値なく保持したい場合、ListではなくSetを使いますよね?
ただ実際実行してみると、問題があったのですよ…
【参考に】
・Setは重複要素を保持しない。
・Listは重複要素を保持する。
Set変数に対して、順番に「add」するのであれば問題ないようなのですが、「addAll」だと「UnsupportedOperationException」が発生してしまうのです
例の実装です
Map<Integer, List<String>> testMap1 = new HashMap<>();
Map<Integer, List<String>> testMap2 = new HashMap<>();
List<String> list1 = new ArrayList<String>(Arrays.asList("01", "02", "03"));
List<String> list2 = new ArrayList<String>(Arrays.asList("04", "05", "06"));
List<String> list3 = new ArrayList<String>(Arrays.asList("07", "08", "09"));
testMap1.put(1, list1);
testMap2.put(1, list2);
testMap2.put(2, list3);
// testMap1からkeyを全件取得
Set<Integer> numberList1 = testMap1.keySet();
// testMap2からkeyを全件取得(重複データである「1」は追加されない想定)
numberList1.addAll(testMap2.keySet()); // ← ここで「UnsupportedOperationException」発生
for (Integer number : numberList1) {
System.out.println(number);
}
はい、「その処理はできないよ!」って感じですね
※ なんでかは原因は不明(笑)
今回の事案の場合の2通り解決案を提示したいと思います
【解決案1】
Listで保持してから、重複を削除します
Map<Integer, List<String>> testMap1 = new HashMap<>();
Map<Integer, List<String>> testMap2 = new HashMap<>();
List<String> list1 = new ArrayList<String>(Arrays.asList("01", "02", "03"));
List<String> list2 = new ArrayList<String>(Arrays.asList("04", "05", "06"));
List<String> list3 = new ArrayList<String>(Arrays.asList("07", "08", "09"));
testMap1.put(1, list1);
testMap2.put(1, list2);
testMap2.put(2, list3);
// testMap1からkeyを全件取得し、List型に格納
List<Integer> numberList1 = new ArrayList<>(testMap1.keySet());
// testMap2からkeyを全件取得し、List型に格納(「1」が2件ある状態)
numberList1.addAll(new ArrayList<>(testMap2.keySet()));
// 「stream().distinct()」関数を使用し、重複データ(「1」)を削除する。
List<Integer> distinctNumberList1 =
numberList1.stream().distinct().collect(Collectors.toList());
for (Integer number : distinctNumberList1) {
System.out.println(number);
}
// 出力結果
// 1
// 2
【解決案2】
Setを維持でも使う!
順番にaddしていこう作戦
List<String> list1 = new ArrayList<String>(Arrays.asList("01", "02", "03"));
List<String> list2 = new ArrayList<String>(Arrays.asList("04", "05", "06"));
List<String> list3 = new ArrayList<String>(Arrays.asList("07", "08", "09"));
testMap1.put(1, list1);
testMap2.put(1, list2);
testMap2.put(2, list3);
// testMap1からkeyを全件取得
Set<Integer> mergeNumberSet = testMap1.keySet();
// testMap2からkeyを全件取得し、順番にaddしていく
for (Integer number : testMap2.keySet()) {
mergeNumberSet.add(number);
}
for (Integer mergeNumber : mergeNumberSet) {
System.out.println(mergeNumber);
}
// 出力結果
// 1
// 2
私的にはstreamのほうがきれいに見えますし、行数が2行ということでオススメさせていただきます
(個人的にfor文がいっぱいあるのは好きでない…www)
他に何か実装案があるという方がいらっしゃいましたら、コメント欄にメッセージを頂けましたら幸いです
ではっ
是非フォローしてください
最新の情報をお伝えします