1.はじめに

このクイックチュートリアルでは、ワンライナーを使用して

List

を初期化する方法について説明します。

2.配列から作成する

配列から

List

を作成することができ、配列リテラルのおかげで1行でそれらを初期化することができます。

List<String> list = Arrays.asList(new String[]{"foo", "bar"});

配列の作成を処理するための可変引数メカニズムを信頼できます。それによって、より簡潔で読みやすいコードを書くことができます。

@Test
public void givenArrayAsList__thenInitialiseList() {
    List<String> list = Arrays.asList("foo", "bar");

    assertTrue(list.contains("foo"));
}

  • このコードの結果インスタンスは

    List

    インターフェースを実装していますが、

    java.util.ArrayList



    LinkedList

    ** ではありません。代わりに、それは2つの意味を持つ元の配列に裏打ちされた

    List

    です。

ただし、クラスの名前はたまたま

ArrayList

ですが、

java.util.Arrays

パッケージにあります。

2.1. 固定サイズ


Arrays.asList

の結果インスタンスは固定サイズになります。

@Test(expected = UnsupportedOperationException.class)
public void givenArraysAsList__whenAdd__thenUnsupportedException() {
    List<String> list = Arrays.asList("foo", "bar");

    list.add("baz");
}

2.2. 共有参照

元の配列とリストは、オブジェクトへの同じ参照を共有します。

@Test
public void givenArraysAsList__whenCreated__thenShareReference(){
    String[]array = {"foo", "bar"};
    List<String> list = Arrays.asList(array);
    array[0]= "baz";

    assertEquals("baz", list.get(0));
}

3.ストリームから作成する(Java 8)


Stream

をあらゆる種類の

Collection.

に簡単に変換できます。

したがって、

Streams

のファクトリメソッドを使用すると、リストを1行で作成および初期化できます。

@Test
public void givenStream__thenInitializeList(){
    List<String> list = Stream.of("foo", "bar")
      .collect(Collectors.toList());

    assertTrue(list.contains("foo"));
}

ここで、

Collectors.toList()は、返された

List__の正確な実装を保証するものではありません。

  • 返されるインスタンスの可変性、直列化可能性、またはスレッドセーフ性についての一般的な契約はありません。したがって、私たちのコードはこれらのプロパティのいずれにも依存するべきではありません。


Stream.of(…​)。collect(…​)



Arrays.asList()

よりもメモリとパフォーマンスのフットプリントが大きい可能性があると強調しているソースもありますが、ほとんどの場合、ほとんど最適化されていません差。

4.ファクトリメソッド(Java 9)

JDK 9では、コレクションに対していくつかの便利なファクトリメソッドが導入されました。

List<String> list = List.of("foo", "bar", "baz");
Set<String> set = Set.of("foo", "bar", "baz");

  • 1つの重要な詳細は返されたインスタンスが不変であることです** 。それを超えて、ファクトリーメソッドはスペース効率とスレッドの安全性においていくつかの利点があります。

このトピックについては、https://www.baeldung.com/java-9-collections-factory-methods[この記事]を参照してください。

5.ダブルブレースの初期化

いくつかの場所で、「二重括弧の初期化」というメソッドがあります。

@Test
public void givenAnonymousInnerClass__thenInitialiseList() {
    List<String> cities = new ArrayList() {{
        add("New York");
        add("Rio");
        add("Tokyo");
    }};

    assertTrue(cities.contains("New York"));
}

「二重括弧の初期化」という名前は非常に誤解を招くものです。構文は簡潔でエレガントに見えるかもしれませんが、それは危険なことに何が起こっているのかを隠しています。

Javaには実際には「二重括弧」の構文要素はありません。それらは意図的にこの方法でフォーマットされた2つのブロックです。

  • 外側の中括弧を使って、

    ArrayList

    のサブクラスになる無名の内部クラスを宣言します。** これらの中括弧の中に、サブクラスの詳細を宣言できます。

いつものように、インスタンス初期化子ブロックを使うことができます、そしてそれは中括弧の内側のペアが由来するところです。

  • この構文の簡潔さは魅力的ですが、アンチパターンと見なされています。**

二重括弧の初期化についてもっと読むために、私達の記事https://www.baeldung.com/java-double-brace-initialization[ここ]を見てください。

6.まとめ

  • Modern Javaには、1行で

    Collection

    を作成するためのいくつかのオプションがあります。

重要なのは、優美に見えますが、匿名内部クラス初期化のアンチパターン(別名「二重中括弧」)には、多くの悪影響があることです。

いつものように、コードはhttps://github.com/eugenp/tutorials/tree/master/core-java-collections[over on GitHub]から入手できます。