web-dev-qa-db-ja.com

HashMapを初期化する正しい方法とHashMapは異なる値型を保持できますか?

したがって、JavaのHashMapsについて2つの質問があります。

  1. HashMapを初期化する正しい方法は何ですか?私の状況では次のものを使用するのが最善かもしれません:

    HashMap x = new HashMap();
    

    しかし、Eclipseは私が使用することを提案し続けます:

    HashMap<something, something> map = new HashMap();
    

    どちらが良いですか?

  2. HashMapは、異なる種類のオブジェクト/データ型を値として保持できますか?たとえば、これは機能しますか?

    map.put("one", 1);
    map.put("two", {1, 2});
    map.put("three", "hello");
    

    最初のput()では、intを値として、2番目ではint[]を、3番目では文字列を必要とします。 JavaでHashMapsを使用してこれを行うことはできますか?また、HashMapHashMap内の値として保存しても大丈夫ですか?

61
Tony Stark

本当に必要な型安全性に依存します。非一般的な方法は、次のように行うのが最適です。

 Map x = new HashMap();

xMapとして入力されることに注意してください。これにより、将来的に実装を(TreeMapまたはLinkedHashMapに)簡単に変更できます。

ジェネリックを使用して、特定のレベルのタイプセーフティを確保できます。

Map<String, Object> x = new HashMap<String, Object>();

Java 7以降では、次のことができます。

Map<String, Object> x = new HashMap<>();

上記はより冗長ですが、コンパイラの警告を回避します。この場合、HashMapのコンテンツは任意のObjectにすることができます。したがって、Integerint[]などにすることができます。

まだJava 6を使用している場合、 Guava Libraries (自分でやるのは簡単ですが) newHashMap() というメソッドがあり、 newを実行するときに、一般的な型付け情報を複製します。変数宣言から型を推測します(これは、Java 7より前のコンストラクターでは使用できないJava機能です)。

ちなみに、intまたは他のプリミティブを追加すると、Javaはそれをオートボクシングします。つまり、コードは次と同等です。

 x.put("one", Integer.valueOf(1));

確かにHashMapを別のHashMapの値として置くことはできますが、再帰的に行うと問題があると思います(つまり、HashMapを値として入れます)。

100
Yishai

これは、Java 1.5で行われた変更です。最初にリストするのは古い方法で、2番目は新しい方法です。

HashMapを使用すると、次のようなことができます。

HashMap<String, Doohickey> ourMap = new HashMap<String, Doohickey>();

....

Doohickey result = ourMap.get("bob");

マップ上にタイプがなかった場合、これを行う必要があります。

Doohickey result = (Doohickey) ourMap.get("bob");

とても便利です。バグをキャッチし、あらゆる種類の余分なキャストを書くことを避けます。 1.5(およびそれ以降)の私のお気に入りの機能の1つでした。

マップに複数のものを配置し、それをMapとして指定するだけで、任意のオブジェクト(String、別のMap、Integer、および必要に応じて3つのMyObject)を配置できます。

14
MBCook

Eclipseは、HashMapの型を宣言することを推奨しています。これにより、型の安全性が強化されます。もちろん、2番目の部分からタイプセーフを回避しようとしているように聞こえます。

後者の場合は、マップをHashMap<String,Object>として宣言してください。

4
Paul Tomblin

あなたがそれを書いている方法はと同等です

HashMap<Object, Object> map = new HashMap<Object, Object>();

括弧内にあるのは、HashMapに何を入れようとしているかをコンパイラーに伝えて、エラーチェックを行えるようにすることです。 Object、Objectが実際に必要な場合(おそらくそうではない場合)、明示的に宣言する必要があります。一般に、コンパイラーによるエラー検査を容易にするために、宣言でできる限り明示的にする必要があります。あなたが説明したことはおそらくこのように宣言されるべきです:

HashMap<String, Object> map = new HashMap<String, Object>();

そうすれば、少なくともキーは文字列になると宣言しますが、値は何でもかまいません。値を取得するときにキャストを使用することを忘れないでください。

3
Graphics Noob

2つ目は、Java 1.5に付属するジェネリックを使用しています。これにより、コード内のキャスト数が減り、実行時ではなくコンパイル時にエラーをキャッチできます。とはいえ、それはあなたがコーディングしているものに依存します。さまざまなタイプのいくつかのオブジェクトを保持するための高速でダーティなマップには、ジェネリックは必要ありません。ただし、マップがオブジェクト以外の型から派生したオブジェクトをすべて保持している場合は、価値があります。

前のポスターは、マップ内の配列について間違っています。配列は実際にはオブジェクトなので、有効な値です。

Map<String,Object> map = new HashMap<String,Object>();
map.put("one",1); // autoboxed to an object
map.put("two", new int[]{1,2} ); // array of ints is an object
map.put("three","hello"); // string is an object

また、HashMapはオブジェクトであるため、HashMapの値にすることもできます。

2
Billy Bob Bain

Eclipseはgeneric typeを定義して、type safetyを使用できるようにすることを提案しています。あなたは書ける

Map m = new HashMap();

型の安全性は保証されませんが、以下は型の安全性を保証します

Map<Object,Object> = new HashMap<Object,Object>();

Objectは、StringIntegerなどの任意のタイプです。

1
user6811894

HashMapは、別のHashMapであっても、値として任意のオブジェクトを保持できます。 Eclipseは、コレクションの推奨プラクティスであるため、型を宣言することを提案しています。 Javaの下5. Eclipseの提案は無視してかまいません。

Java 5では、コレクションに追加するときに、int(または任意のプリミティブ型)が 自動ボックス化 Integer(またはその他の対応する型)になります。ただし、オートボクシングの使用にはいくつかの問題があるため、これには注意してください。

1
Ken Liu

2番目の質問に対する答え:はい、HashMapはさまざまなタイプのオブジェクトを保持できます。それが良いアイデアであるかどうかは、あなたが解決しようとしている問題に依存します。

ただし、この例は機能しません。 int値はオブジェクトではありません。整数ラッパークラスを使用して、HashMapにint値を格納する必要があります

0
Luke