Collections.emptyMap()と新しいHashMap()


143

使用できる状況にはどのようなものがありますCollections.emptyMap()か?ドキュメントには、コレクションを不変にしたい場合にこのメソッドを使用できると記載されています。

不変の空のコレクションが必要なのはなぜですか?ポイントは?


12
質問への+1、私は見たことがないので、その静的メソッドの前に
ティム・ベンダー

また、スカラレンズ、グーグルスカラレンズもご覧ください。emptyMapおよびimmutableMapを使用して、不変のオブジェクトを作成できます。emptyMapが最初のポイントです。要素が追加されるたびに、マップ自体は古い要素と新しい要素を含むマップに置き換えられます。ポイントは、オブジェクトへのアクセスが安全であることです。
michael_s 2013

1
Objective-Cのような[NSArray array]もので、使用できないが存在するオブジェクトを返します。そのため、通常のオブジェクトと同じように操作でき、エラーが発生しません。
Shane Hsu

回答:


144

より効果的なJavaのアイテム#43 - "Return empty arrays or collections, not null"おそらく空のコレクションを返すことを実証しても、これらを使用して実証しemptyList()emptySet()、およびemptyMap()コレクションクラスのメソッドも不変であることの追加の利点を持っていることを空のコレクションを取得します。アイテム#15 から "Minimize Mutability"

コレクション-emptySet-コレクション- emptyList-コレクション

その一種のプログラミングイディオム。これはnull変数を必要としない人向けです。したがって、セットが初期化される前に、空のセットを使用できます。

注:以下のコードは一例です(ユースケースに応じて変更してください)。

private Set myset = Collections.emptySet();

void initSet() {
   myset = new HashSet();
}
void deleteSet() {
   myset = Collections.emptySet();
}

これらの方法には、いくつかの利点があります。

  1. コレクションのジェネリック型を明示的に入力する必要がないため、より簡潔です。これは、通常、メソッド呼び出しのコンテキストから推測されるだけです。

  2. 新しいオブジェクトを作成する手間がかからないため、より効率的です。既存の空で不変のオブジェクトを再利用するだけです。この効果は一般に非常に小さいですが、時々(まあ、めったに)重要ではありません。


15
有効なJavaリファレンスの場合は+1。メソッドとフレンドの全体的なポイントは(定数などとは対照的に)ジェネリックでうまく機能するということなので、1つの要点:パラメータ化SetHashSetあなたの例をお勧めします。さらに、Java 5以降では非推奨となっている機能(rawタイプ)を使用することは、優れた教材にはなりません。emptySet()Collections.EMPTY_SET
Daniel Pryden 2013

4
私は確信が持てません... 次の操作でスローされるCollectionnullを避けるためにではなく、代わりにを使用することの全体的なポイントではありませんExceptionsか?不変コレクションを使用すると、他の種類の例外が発生すると思います。そして、代入nullは不変の定数を代入するよりも確かに効率が悪いわけではありません。
fgysinはモニカを2013

14
@fgysin:クライアントがコレクションを変更することが予想されるAPIがある場合、はい、不変のコレクションを返すことは意味がありません。しかし、クライアントが変更してはならない、ただ繰り返す必要があるコレクションを返すAPIがある場合、「悪い」クライアントが所有するコレクションを誤って変更しないようにするために、基になるコレクションにビューを返すことは完全に理にかなっています。あなたによって。nullではなく空のコレクションを返すと、クライアントはコレクションを使用する前にnullチェックを行う必要がなくなり、クライアントコードがより明確になります。
Jean Hominal 2013

4
public boolean setExists() { return !myset.equals(Collections.emptySet()); }
アサイリア2013

5
あなたの例では、空のセットを明示的にチェックし、それをセンチネル値として使用しており、クラスは変更可能です。小さな例では、センチネルと可変性を使用しています。これは、Collections.emptySet()が防止しようとしているものです。
Marc O'Morain 2013

33

私の個人的な経験では確かに、APIがパラメータのコレクションを必要とするが、何も提供しない場合に非常に役立ちます。たとえば、次のようなAPIがあり、null参照が許可されていない場合があります。

public ResultSet executeQuery(String query, Map<String, Object> queryParameters);

パラメータを取らないクエリがある場合、配列の割り当てを含むHashMapを作成することは確かに少し無駄です。実際には定数である「空のマップ」を単に渡すことができるとき、それは実装方法ですの中でjava.util.Collections


22

不変の空のコレクションが必要なのはなぜですか?ポイントは?

ここに2つの異なる概念があり、一緒に見ると奇妙に見えます。2つの概念を別々に扱うと、より意味があります。

  • まず、可能な限り変更可能なコレクションではなく、不変のコレクションを使用することをお勧めします。immuablityの利点は、他の場所で十分に文書化されています。

  • 次に、センチネルとしてnullを使用するのではなく、空のコレクションを使用することをお勧めします。これについては、ここ詳しく説明しています。つまり、バグを隠す場所が少なくなり、コードがよりクリーンで理解しやすくなります。

したがって、マップが必要なコードがある場合は、マップがないことを示すために、nullではなく空のマップを渡すことをお勧めします。そして、ほとんどの場合、マップを使用しているときは、不変マップを使用することをお勧めします。これが、不変の空のマップを作成するための便利な関数がある理由です。


8

不変のマップ、リスト、セット、またはその他のタイプのコレクションを使用したい場合がいくつかあります。

まず、間違いなく最も重要な使用例は、クエリの結果または結果のセット(またはリストやマップ)を返す計算の結果を返すときは常に、不変のデータ構造を使用することです。

この場合、計算の結果セットの実際の不変性をより明確に反映するため、これらの不変バージョンを返す方がはるかに好ましい-後でデータをどのように処理しても、クエリから受け取った結果のセットは変化する。

2番目の一般的な使用例は、メソッドまたはサービスへの入力として引数を提供する必要がある場合です。入力コレクションがサービスまたはメソッドによって変更されることを期待しない限り(これは通常、非常に悪い設計アイデアです)、可変コレクションの代わりに不変コレクションを渡すことは、多くの場合、合理的かつ安全な選択かもしれません。

私はそれを「値渡し」の慣例と考えています。

より一般的には、データがモジュールまたはサービスの境界を越えるときは常に不変のデータ構造を使用するのが賢明な方法です。これにより、(不変の)入力/出力と可変の内部状態の違いについて、はるかに簡単に推論できます。

これの非常に有益な副作用として、モジュール/サービスのセキュリティとスレッドの安全性が向上し、問題をより明確に分離できます。

Collections.empty*()メソッドを使用するもう1つの理由は、それらの冗長性が著しく不足していることです。Java7以前の時代には、ジェネリックコレクションがある場合、ジェネリック型注釈をあちこちに散らす必要がありました。

次の2つの宣言を比較してください。

Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();

対:

Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();

後者は、次の2つの重要な方法で読みやすさを明確に評価します。

  1. 最初の宣言では、空のマップのインスタンス化全体がジェネリック型宣言のノイズに埋もれており、本質的に些細な宣言を必要以上に不可解にしています。
  2. 右側にジェネリック型の注釈がないことに加えて、2番目のバージョンでは、マップが空のマップに初期化されることが明記されています。さらに、このメソッドが不変のマップを返すことを知っているため、検索するだけで、空でないfooBarMap別の値が割り当てられている場所を簡単に見つけることができます。/fooBarMap =/

5

1つは、参照の共有を回避することです。new HashMap()などが割り当てられたオブジェクトが必要になりますし、おそらくいくつかの余分な要素は、データを保持するために、しかし、あなたは唯一不変空のコレクション(リスト、セット、マップ、または任意の他のそのような)の一つのコピーを必要としています。これにより、呼び出すメソッドがマップを受け入れる必要があるが、編集する必要がない場合に、これは明白な選択になります。

不変オブジェクト(スレッドセーフティを含む)の非常に優れた属性がいくつかリストされているJosh BlochのEffective Javaをチェックすることをお勧めします。


3

を返す関数がimmutable collectionあり、状況によっては返すデータがない場合に役立つので、返す代わりに返すnullことができますemptyMap()

それはあなたのコードをより簡単にし、防ぎます NullPointerException


3

ほとんどの場合、constructorを使用して新しいを作成しますempty map。しかし、使用Collections methodsを作成するためのいくつかの利点を提供しますempty mapstatic method java.util.Collections.emptyMap()

  1. コレクションのジェネリック型を明示的に入力する必要がないため、より簡潔です。これは、通常、メソッド呼び出しのコンテキストから推測されるだけです。

  2. 新しいオブジェクトを作成する手間がかからないため、より効率的です。既存の空で不変のオブジェクトを再利用するだけです。この効果は一般に非常に小さいですが、時々(まあ、めったに)重要ではありません。


2

不変の空のコレクションが必要なのはなぜですか?ポイントは?

同じ理由Collections.unmodifiableMap()で、ある時点で使用します。ユーザーが変更しようとした場合に例外をスローするMapインスタンスを返します。これは特別なケースです。空のマップです。


1

不変の空のコレクションが必要なのはなぜですか?ポイントは?

不変オブジェクトが必要になるのと同じ理由で。主な理由は、複数のスレッドがオブジェクトの同じインスタンスにアクセスでき、すべてのスレッドが同じ値を見ることができるという知識で、夜間に安全にスリープできるからです。コレクションに項目がなくても、有効な値であり、維持する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.