Skip to content

Instantly share code, notes, and snippets.

@yanaokahiroki
Last active October 22, 2022 09:31
Show Gist options
  • Save yanaokahiroki/728a70b945cd5247940eb5ca667e1a81 to your computer and use it in GitHub Desktop.
Save yanaokahiroki/728a70b945cd5247940eb5ca667e1a81 to your computer and use it in GitHub Desktop.
2つのListを結合

概要

実装している中で2つのリストを1つのリストに結合する際にList.addAll以外で何かないのか調べたのでメモ。

List.addAll()

これは元々知っていた方法。 結合後のListを定義してそのListに対して addAll() で追加する。 これはこれでシンプルでいいが addAll() を2回呼び出す必要がある上、 結合後のListを返すようなメソッドの場合、 addAll() の後にreturnが必要なのが少し手間。

public class Combine_1 {
  public static void main(String[] args) {
    // 1つ目のリスト
    List<String> list1 = new ArrayList<>();
    list1.add("a1");
    list1.add("a2");

    // 2つ目のリスト
    List<String> list2 = new ArrayList<>();
    list2.add("b1");
    list2.add("b2");

    // 結合後リスト
    List<String> combinedList = new ArrayList<>();
    combinedList.addAll(list1);
    combinedList.addAll(list2);

    System.out.println(combinedList);
  }
}

推奨されないが結合後Listの初期化でaddAll() を使うこともできる。

// 結合後リスト
    List<String> combinedList =
        new ArrayList<>() {
          {
            addAll(list1);
            addAll(list2);
          }
        };

Stream.concat()

調べて最初に出てきたのがStreamの concat() メソッド。 Java8以上であれば使える。 concat() は引数にStreamを取るため、結合したいListをStreamにして渡す。 その後はtoListの終端処理をすれば結合後のListを取得できる。 またconcat() した後、 map()filter() など中間操作を追加してデータの加工ができるのも嬉しい。

個人的にはこれが一番好き。

public class Combine_2 {
  public static void main(String[] args) {
    // 1つ目のリスト
    List<String> list1 = new ArrayList<>();
    list1.add("a1");
    list1.add("a2");

    // 2つ目のリスト
    List<String> list2 = new ArrayList<>();
    list2.add("b1");
    list2.add("b2");

    // 結合後リスト
    List<String> combinedList =
        Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());

    System.out.println(combinedList);
  }
}

Java16以上で結合後のListに変更を加えないのであれば Stream.toList() で少しだけシンプルに書ける。

// 結合後リスト
    List<String> combinedList =
        Stream.concat(list1.stream(), list2.stream()).toList();

Stream.of().forEach()

StreamでforEachを使って結合することもできる。

public class Combine_2 {
  public static void main(String[] args) {
    // 1つ目のリスト
    List<String> list1 = new ArrayList<>();
    list1.add("a1");
    list1.add("a2");

    // 2つ目のリスト
    List<String> list2 = new ArrayList<>();
    list2.add("b1");
    list2.add("b2");

    // 結合後リスト
    List<String> combinedList = new ArrayList<>();
    Stream.of(list1, list2).forEach(combinedList::addAll);

    System.out.println(combinedList);
  }
}

ListUtils.union()

Apache Commons CollectionsのListUtilsなんてのもある。 Apacheのライブラリを入れる手間はあるが便利なメソッドがたくさんあるので入れても損はなさそう。 union() を使うとStream.concat()よりもさらに短く書ける。 Listをそのまま引数に渡せるし、 union は日本語で「結合」を意味する単語なので直感的。

import org.apache.commons.collections4.ListUtils;

public class Combine_4 {
  public static void main(String[] args) {
    // 1つ目のリスト
    List<String> list1 = new ArrayList<>();
    list1.add("a1");
    list1.add("a2");

    // 2つ目のリスト
    List<String> list2 = new ArrayList<>();
    list2.add("b1");
    list2.add("b2");

    // 結合後リスト
    List<String> combinedList = ListUtils.union(list1, list2);

    System.out.println(combinedList);
  }
}

GuavaのIterablesとLists

最後はGoogle Guava。Googleが開発しているJavaのライブラリ。 これは少し読みにくいので苦手。

public class Combine_5 {
  public static void main(String[] args) {
    // 1つ目のリスト
    List<String> list1 = new ArrayList<>();
    list1.add("a1");
    list1.add("a2");

    // 2つ目のリスト
    List<String> list2 = new ArrayList<>();
    list2.add("b1");
    list2.add("b2");

    // 結合後リスト
    Iterable<String> combinedIterable =
        Iterables.unmodifiableIterable(Iterables.concat(list1, list2));
    List<String> combinedList = Lists.newArrayList(combinedIterable);

    System.out.println(combinedList);
  }
}

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment