Collections.emptyList()と新しいインスタンス


241

実際には、それが良いように空のリストを返すことですこの

return Collections.emptyList();

またはこのように:

return new ArrayList<Foo>();

それとも、返されたリストをどう処理するかに完全に依存していますか?

回答:


300

主な違いはCollections.emptyList()不変のリスト、つまり要素を追加できないリストを返すことです。(List.of()Java 9で導入されたものと同じです。)

あなたはまれなケースではない返されたリストを変更したい、Collections.emptyList()List.of()このようにしているではない良い選択。

不変のリストを返すことは、コントラクト(ドキュメント)が明確に異なる状態を示さない限り、完全に(そして推奨される方法でも)良いと思います。


さらに、emptyList() 呼び出しごとに新しいオブジェクトを作成しない場合があります。

このメソッドの実装では、呼び出しごとに個別のListオブジェクトを作成する必要はありません。この方法を使用すると、同じ名前のフィールドを使用する場合と同等のコストがかかる可能性があります。(このメソッドとは異なり、このフィールドはタイプセーフを提供しません。)

の実装はemptyList次のようになります。

public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

したがって、メソッド(空のリストを返す)が頻繁に呼び出される場合、このアプローチでは、CPUとメモリの両方のパフォーマンスがわずかに向上する可能性があります。


4
だから、Collections.emptyList()たとえばエラーチェックなどにもっと適していますか?
mre

1
APIクライアントは、の代わりにNullPointerException戻ることによって取得しません。Collections.emptyList()null
realPK 2016

@PK_Jは重要なポイントになります。 Collections.emptyList()反復可能で長さを返すため、例外をスローすることなくforループで使用できます。
ndm13 2017

使用についてはList.of()どうですか?

4
@AJW、はい。しかし、たとえば、new ArrayList<>()それと比較すると、設計の決定が明確になります。要素はこのリストに追加されません。
aioobe

51

Java 5.0以降では、コンテナ内の要素のタイプを指定できます。

Collections.<Foo>emptyList()

空のままの空のリストを返したい場合は、このアプローチを使用する必要があるという他の応答にも同意します。


38
:Javaの7以降では、ターゲット・タイプから汎用的なメソッド呼び出しの型パラメータを推測コンパイラを聞かせすることができますList<Foo> list = Collections.emptyList()
ポール・ジャクソン

28

Collections.emptyList は不変なので、2つのバージョンには違いがあるため、戻り値のユーザーを考慮する必要があります。

戻るとnew ArrayList<Foo>常にオブジェクトの新しいインスタンスが作成されるため、それに関連する非常にわずかな追加コストが発生し、使用する理由が得られる場合がありますCollections.emptyListemptyList読みやすいからといって使うのが好きです。


14

ただし注意してください。あなたが戻ってCollections.emptyList()、それのように、add()またはそのようなsmth でいくつかの変更を行おうとすると、不変のオブジェクトを返すUnsupportedOperationException()ので、uにはCollections.emptyList()


7

私は行くだろうCollections.emptyList()そうでない場合、私はオプション2となるだろう、返されたリストは、(リストは不変であるように)何らかの方法で変更されていない場合。

の利点Collections.emptyList()は、毎回同じ静的インスタンスが返されるため、呼び出しごとにインスタンスが作成されないことです。


3

返されたリストが変更されないようにする場合は、Collections.emptyList()を使用します。emptyList()を呼び出すと、以下が返されます。

/**
 * The empty list (immutable). 
 */
public static final List EMPTY_LIST = new EmptyList();

私は、呼び出しにCollections.emptyList()建設費がかかっているかどうかを調べようとしてここに到着しました。実装の詳細を確認すると(おそらくすべてのJVMで同じではありません)、そうではないことが確認されます。@Atul、これはどのJVMからのものですか?
wjl 2013

2

与えられた答えemptyList()は、不変を返すListが代替を与えないという事実を強調します。コンストラクタはArrayList(int initialCapacity)特別なケースな0ので、new ArrayList<>(0)代わりに返すnew ArrayList<>()ことも実行可能な解決策かもしれません:

/**
 * Shared empty array instance used for empty instances.
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

[...]

/**
 * Constructs an empty list with the specified initial capacity.
 *
 * @param  initialCapacity  the initial capacity of the list
 * @throws IllegalArgumentException if the specified initial capacity
 *         is negative
 */
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

(Java 1.8.0_72からのソース)


私はあなたのアプローチに同意しません。初期化時にメモリとCPUを少し節約できますが、返されたリストが変更されると、リストが新しい配列を再割り当てするときにその時間が失われます。時間の経過とともに多くの要素がリストに追加されると、成長速度が大幅に低下するため、パフォーマンスのボトルネックがさらに増える可能性があります。私は、変更不可能な空のリストまたは使用可能な変更可能なリストの慣習に固執することを好みます。
Patrick M

1
私の言い回しで強調しようとしたので(実行可能かもしれません):それはすべてあなたのユースケースに依存します。私は通常それらが空であるかどうかに応じて、混合ではなく、可変または非可変のコレクションを返します。そして、「はるかに遅い主張」に対抗するために、これは現在の実装です。
ルネ

ああ、私がJDK 2のメジャーバージョンが古くなっているのを見てください。したがって、java8は、初期サイズ0からデフォルトの容量にジャンプすることで、ボトルネックを完全に回避します。
Patrick M
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.