1行でのArrayListの初期化

2009年06月17日に質問されました。  ·  閲覧回数 3.1M回  ·  ソース

Macarse picture
2009年06月17日

テスト用のオプションのリストを作成したかったのです。 最初に、私はこれをしました:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

次に、コードを次のようにリファクタリングしました。

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

これを行うためのより良い方法はありますか?

回答

Tom picture
2009年06月17日
2223

Listとして宣言するだけの方が簡単ですが、ArrayListである必要がありますか?

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

または、要素が1つしかない場合:

List<String> places = Collections.singletonList("Buenos Aires");

これは、 places不変であることを意味します(変更しようとすると、 UnsupportedOperationException例外がスローされます)。

具体的なArrayListある可変リストを作成するには、不変リストからArrayListを作成できます。

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
coobird picture
2009年06月17日
2094

実際、 ArrayListを初期化する「最良の」方法は、新しいListを作成する必要がないため、作成したメソッドです。

ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");

問題は、そのlistインスタンスを参照するためにかなりの入力が必要になることです。

インスタンス初期化子(「二重中括弧の初期化」とも呼ばれます)を使用して匿名の内部クラスを作成するなど、別の方法があります。

ArrayList<String> list = new ArrayList<String>() {{
    add("A");
    add("B");
    add("C");
}};

ただし、最終的にはインスタンス初期化子を持つArrayListサブクラスであり、そのクラスは1つのオブジェクトを作成するためだけに作成されるため、このメソッドはあまり好きではありません。私には少しやり過ぎです。

場合はどうだったでしょう素敵でしたコレクションリテラルの提案のためのプロジェクトコインが受け入れられました(。それはJava 7で導入される予定が、それは、Java 8のいずれかの一部となる可能性はありませんして):

List<String> list = ["A", "B", "C"];

残念ながら、 ArrayListではなく不変のListを初期化するため、ここでは役に立ちません。さらに、まだ利用できない場合もあります。

Christoffer Hammarstr&#246;m picture
2010年09月09日
920

簡単な答え

Java 9以降では、 List.of()が追加された後:

List<String> strings = List.of("foo", "bar", "baz");

Java 10以降では、これはvarキーワードで短縮できます。

var strings = List.of("foo", "bar", "baz");

これにより、不変のListが得られるため、変更できません。
これは、事前入力しているほとんどの場合に必要なものです。


Java 8以前:

List<String> strings = Arrays.asList("foo", "bar", "baz");

これにより、配列に裏打ちされたList得られるため、長さを変更することはできません。
ただし、 List.setを呼び出すことができるため、変更可能です。


静的インポートを使用すると、 Arrays.asListさらに短くすることができます。

List<String> strings = asList("foo", "bar", "baz");

静的インポート:

import static java.util.Arrays.asList;  

最新のIDEが提案し、自動的に実行するもの。
たとえばのIntelliJ IDEAに、あなたは押すAlt+Enterと選択Static import method...


ただし、混乱を招くため、 List.ofメソッドをofに短縮することはお勧めしません。
List.ofはすでに十分に短く、よく読みます。


Streamを使用する

なぜListでなければならないのですか?
Java 8以降では、より柔軟なStreamを使用できます。

Stream<String> strings = Stream.of("foo", "bar", "baz");

Streamを連結できます:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

または、 StreamからListます:

import static java.util.stream.Collectors.toList;

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());

ただし、できれば、 Streamに収集せずに、 List


あなたは本当に、特に必要がある場合はjava.util.ArrayList

(おそらくそうではありません。)
JEP 269 (私の強調)を引用するには:

事前定義された値のセットを使用して可変コレクションインスタンスを初期化するためのユースケースの


あなたは両方の事前移入したい場合はArrayList(なぜ?)、その後、それに追加し、使用

ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");

またはJava8以前の場合:

ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");

またはStreamます:

import static java.util.stream.Collectors.toCollection;

ArrayList<String> strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

ただし、ここでも、 Listに収集するのではなく、 Stream直接使用することをおListます。


実装ではなく、インターフェースへのプログラム

コードでリストをArrayListとして宣言したとのことですが、 ListないArrayListメンバーを使用している場合にのみ宣言する必要があります。

あなたがしていない可能性が最も高いです。

通常は、使用する最も一般的なインターフェイス( IterableCollectionList )で変数を宣言し、特定の実装で初期化する必要があります(例: ArrayListLinkedListまたはArrays.asList() )。

そうしないと、コードをその特定のタイプに制限することになり、必要なときに変更するのが難しくなります。

たとえば、 ArrayListvoid method(...)渡す場合:

// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) { 
    for (String s : strings) { ... } 
}

// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
    if (!strings.isEmpty()) { strings.stream()... }
}

// List if you also need .get(index):
void method(List<String> strings) {
    strings.get(...)
}

// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
    ??? // You don't want to limit yourself to just ArrayList
}

別の例は、通常はFileInputStreamまたはBufferedInputStreamであるにもかかわらず、変数を常にInputStream宣言することです。これは、いつかあなたまたは他の誰かが他の種類を使用したいと思うからです。 InputStream

Randyaa picture
2011年08月30日
113

サイズ1の簡単なリストが必要な場合:

List<String> strings = new ArrayList<String>(Collections.singletonList("A"));

複数のオブジェクトのリストが必要な場合:

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
Paweł Adamski picture
2013年07月29日
57

Guavaを使用すると、次のように書くことができます。

ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

Guavaには、他にも便利な静的コンストラクターがあります。 あなたはここでそれらについて読むことができ

Naman picture
2017年02月03日
39

以降では、 JEP 269:コレクションのコンビニエンスファクトリメソッドで提案されているように、これはコレクションリテラルを使用して実現できます。

List<String> list = List.of("A", "B", "C");

Set<String> set = Set.of("A", "B", "C");

同様のアプローチがMapにも適用されます-

Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")

これは、@ coobirdが述べたCollectionLiteralsの提案に似ています。 JEPでもさらに明確に-


代替案

言語の変更は何度か検討され、拒否されました。

プロジェクトコイン提案、2009年3月29日

プロジェクトコイン提案、2009年3月30日

lambda-devに関するJEP186のディスカッション、2014年1月から3月

このメッセージに要約されているように、言語の提案は、ライブラリベースの提案よりも優先して取っておかれました

関連: Java9のコレクション用のオーバーロードされたコンビニエンスファクトリメソッドのポイントは何ですか

Mark picture
2014年04月04日
34

コレクションリテラルはJava8に組み込まれませんでしたが、Stream APIを使用して、リストを1つのかなり長い行で初期化することができます。

List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

ListArrayListあることを確認する必要がある場合:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
George picture
2010年05月12日
31
import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
Jord&#227;o picture
2010年05月04日
24

ファクトリメソッドを作成できます。

public static ArrayList<String> createArrayList(String ... elements) {
  ArrayList<String> list = new ArrayList<String>();
  for (String element : elements) {
    list.add(element);
  }
  return list;
}

....

ArrayList<String> places = createArrayList(
  "São Paulo", "Rio de Janeiro", "Brasília");

しかし、それは最初のリファクタリングよりもはるかに優れているわけではありません。

柔軟性を高めるために、一般的なものにすることができます。

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}
Mohit Tyagi picture
2017年10月06日
16

Java 9では、 ArrayListを1行で簡単に初期化できます。

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

または

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

Java 9のこの新しいアプローチには、以前のアプローチに比べて多くの利点があります。

  1. スペース効率
  2. 不変性
  3. スレッドセーフ

詳細については、この投稿を参照してください-> List.ofとArrays.asListの違いは何ですか?