web-dev-qa-db-ja.com

配列の初期化と同等のArrayListの初期化

インスタンス化中に次のように配列を初期化することができます。

String[] names = new String[] {"Ryan", "Julie", "Bob"};

ArrayListで同じことをする方法はありますか?それともarray.add()で内容を個別に追加する必要がありますか?

245
Jonathan

Arrays.asList こちらが役に立ちます。

new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
323
meriton

はい。

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

これが実際に行っていることはArrayList<String>から派生したクラスを作成し(外側のブレースセットでこれを行います)、次に静的イニシャライザ(内側のブレースセット)を宣言することです。これは実際には包含クラスの内部クラスであるため、暗黙のthisポインタを持ちます。直列化したくない場合、または外部クラスがガベージコレクションされることを期待している場合を除き、問題にはなりません。

私は、Java 7があなたが望むことを正確に行うために 追加の言語構成要素 を提供することを理解しています。

編集:最近のバージョンのJavaは、そのようなコレクションを作成するためのより使いやすい機能を提供しており、上記を調べる価値があります(これらのバージョンより前に提供されていました)。

60
Brian Agnew

これがあなたが得ることができる最も近いものです:

ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));

あなたはさらに簡単に行くことができます:

List<String> list = Arrays.asList("Ryan", "Julie", "Bob")

Arrays.asListのソースを見ると、ArrayListが作成されますが、デフォルトではListにキャストされます。そのため、これを行うことができます(ただし、新しいJDKの場合は確実ではありません)。

ArrayList<String> list = (ArrayList<String>)Arrays.asList("Ryan", "Julie", "Bob")
33
Fred Haslam
Arrays.asList("Ryan", "Julie", "Bob");
24
John D

まあ、Javaにはリストのためのリテラル構文がないので、あなたは.add()をしなければなりません。

あなたがたくさんの要素を持っているなら、それは少し冗長ですが、あなたはどちらかをすることができます:

  1. groovyなどを使う
  2. arrays.asList(配列)を使用してください。

2は次のようになります。

String[] elements = new String[] {"Ryan", "Julie", "Bob"};
List list = new ArrayList(Arrays.asList(elements));

ただし、これは不要なオブジェクト作成をもたらします。

8
jayshao

選択された答えは:ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));です。

ただし、選択した答えを理解して最終的な配列を作成する前に要素を内部で数回コピーすることが重要であり、その冗長性の一部を減らす方法があります。

何が起こっているのか理解することから始めましょう。

  1. まず、要素が静的ファクトリArrays.asList(T...)によって作成されたArrays.ArrayList<T>にコピーされます。

    単純なクラス名が同じでも、これはJava.lang.ArrayListと同じクラスを生成するわけではありません。 Listインタフェースがあるにもかかわらず、remove(int)のようなメソッドは実装されていません。これらのメソッドを呼び出すと、UnspportedMethodExceptionがスローされます。しかし、必要なのが固定サイズのリストだけであれば、ここでやめることができます。

  2. 次に#1で構築されたArrays.ArrayList<T>がコンストラクタArrayList<>(Collection<T>)に渡され、そこでcollection.toArray()メソッドがそれを複製するために呼び出されます。

    public ArrayList(Collection<? extends E> collection) {
    ......
    Object[] a = collection.toArray();
    }
    
  3. 次に、コンストラクタは、クローン配列を採用するか、サブクラス型を削除するために再度コピーするかを決定します。 Arrays.asList(T...)は内部的にはパラメータとして渡したT型の配列を使用しているので、Tが純粋なオブジェクトでない限り、コンストラクタは常にクローンの使用を拒否します。 (たとえば、String、Integerなどは、Objectを拡張するため、すべてコピーされます)。

    if (a.getClass() != Object[].class) {      
        //Arrays.asList(T...) is always true here 
        //when T subclasses object
        Object[] newArray = new Object[a.length];
        System.arraycopy(a, 0, newArray, 0, a.length);
        a = newArray;
    }
    array = a;
    size = a.length;
    

したがって、ArrayListを明示的に初期化するためだけに、データが3倍コピーされました。 Arrays.AsList(T...)がObject []配列を構築するように強制すると、2倍になる可能性があります。そのため、ArrayListは後でそれを採用できます。これは、次のように実行できます。

(List<Integer>)(List<?>) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5));

あるいは、作成後に要素を追加するだけでも、最も効率的な場合があります。

5
NameSpace

これはどう。

ArrayList<String> names = new ArrayList<String>();
Collections.addAll(names, "Ryan", "Julie", "Bob");
3
Ken de Guzman

これは op4j Javaライブラリの流暢なインターフェースを使って行われる方法です(1.1。Dec '10がリリースされた1.1): -

List<String> names = Op.onListFor("Ryan", "Julie", "Bob").get();

それはあなたに時間の節約になるとてもクールなライブラリです。

2
crsedgar