ジェネリックを使用してマップの配列を宣言し、マップタイプを指定できます。
private Map<String, Integer>[] myMaps;
ただし、適切にインスタンス化する方法がわかりません。
myMaps = new HashMap<String, Integer>[count]; // gives "generic array creation" error
myMaps = new HashMap[count]; // gives an "unchecked or unsafe operation" warning
myMaps = (Map<String, Integer>[])new HashMap[count]; // also gives warning
コンパイラのエラーや警告を表示せずに、このマップの配列をインスタンス化するにはどうすればよいですか?
更新:
お返事ありがとうございます。私はリストの提案に行き着きました。
厳密にはあなたの質問に対する答えではありませんが、代わりにList
を使用することを検討しましたか?
List<Map<String,Integer>> maps = new ArrayList<Map<String,Integer>>();
...
maps.add(new HashMap<String,Integer>());
うまくいくようです。
配列をジェネリックと混合することが推奨されない理由の詳細な説明については、 Javaの理論と実践:ジェネリックスgotchas を参照してください。
Drewがコメントで述べたように、List
の代わりに Collection インターフェイスを使用した方が良いかもしれません。これは、Set
、またはCollection
の他のサブインターフェイスの1つに変更する必要がある場合に便利です。サンプルコード:
Collection<Map<String,Integer>> maps = new HashSet<Map<String,Integer>>();
...
maps.add(new HashMap<String,Integer>());
この開始点からは、HashSet
をArrayList
、PriorityQueue
、またはCollection
を実装する他のクラスに変更するだけで済みます。
汎用配列を安全に作成することはできません。 Effective Java 2nd Editionは Genericsの章 の詳細に入ります。119ページの最後の段落から始めます。
汎用配列を作成するのはなぜ違法ですか?タイプセーフではないからです。正当である場合、コンパイラによって生成されたキャストは、それ以外の場合は正しいプログラムで、実行時に
ClassCastException
で失敗する可能性があります。これは、ジェネリック型システムによって提供される基本的な保証に違反します。これをより具体的にするには、次のコードフラグメントを検討してください。
// Why generic array creation is illegal - won't compile! List<String>[] stringLists = new List<String>[1]; // (1) List<Integer> intList = Arrays.asList(42); // (2) Object[] objects = stringLists; // (3) objects[0] = intList; // (4) String s = stringLists[0].get(0); // (5)
汎用配列を作成する1行目が正当であるとしましょう。行2は、単一の要素を含む
List<Integer>
を作成して初期化します。行3は、List<String>
配列をObject
配列変数に格納します。これは配列が共変であるため有効です。行4は、List<Integer>
をObject
配列の唯一の要素に格納します。これは、ジェネリックが消去によって実装されるため成功します。List<Integer>
インスタンスの実行時型は、単にList
、およびList<String>[]
インスタンスのランタイムタイプはList[]
であるため、この割り当てはArrayStoreException
を生成しません。今は困っています。List<Integer>
インスタンスのみを保持するように宣言された配列にList<String>
インスタンスを保存しました。 5行目では、この配列の唯一のリストから唯一の要素を取得します。コンパイラは取得した要素をString
に自動的にキャストしますが、Integer
なので、実行時にClassCastException
を取得します。これを防ぐために、1行目(汎用配列を作成)はコンパイル時エラーを生成します。
配列とジェネリックはうまく結合しないため(他の理由も同様)、一般的には配列ではなくCollection
オブジェクト(特にList
オブジェクト)を使用する方が適切です。
一般に、Javaでジェネリックと配列を混在させることはお勧めできません。ArrayListを使用することをお勧めします。
配列を使用する必要がある場合、これを処理する最善の方法は、配列の作成(例2または3)を別のメソッドに配置し、@ SuppressWarnings( "unchecked")で注釈を付けることです。
簡単な答えは、実際にはできないということです。
それについてのブログについては、以下を参照してください。 http://www.bloggingaboutjava.org/2006/01/Java-generics-quirks/
ブログへのコメントの1つは次のように述べています:
実際、エンジニアはそのようなアレイの作成を違法にしました。したがって、汎用クラスからの配列の作成は失敗します。 Collection.toArrayメソッドとそれに続くCast to Arrayは、コンパイル時に機能します。
これにより、実行時にArrayStoreCheckを実行できないという問題は解決されませんが、この方法でジェネリックの配列を作成できます。
Bill the Lizardが示唆したように、おそらくあなたは
List<Map<String,Integer>>
マップの汎用配列を作成できます
マップのリストを作成します。
List<Map<String, ?>> myData = new ArrayList<Map<String, ?>>();
配列を初期化します。
Map<String,?>[]myDataArray=new HashMap[myData .size()];
リストから配列にデータを入力します。
myDataArray=myData.toArray(myDataArry);