45

我可以使用泛型声明一个映射数组来指定映射类型:

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 建议。

4

8 回答 8

47

严格来说不是您问题的答案,但您是否考虑过使用 aList代替?

List<Map<String,Integer>> maps = new ArrayList<Map<String,Integer>>();
...
maps.add(new HashMap<String,Integer>());

似乎工作得很好。

有关为什么不鼓励将数组与泛型混合使用的详细说明,请参阅Java 理论和实践:泛型陷阱

更新:

正如 Drew 在评论中提到的,使用Collection接口而不是List. 如果您需要更改为Set. 或 . 的其他子接口之一,这可能会派上用场Collection。示例代码:

Collection<Map<String,Integer>> maps = new HashSet<Map<String,Integer>>();
...
maps.add(new HashMap<String,Integer>());

从这个起点开始,您只需要更改HashSetArrayList,PriorityQueue或任何其他实现Collection.

于 2009-09-29T15:17:56.033 回答
26

您不能安全地创建通用数组。Effective Java 2nd Edition在泛型一章中详细介绍。从第 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>包含单个元素的 a。第 3 行将数组存储 List<String>Object 数组变量中,这是合法的,因为数组是协变的。第 4 行将 存储List<Integer>到数组的唯一元素中Object,这成功了,因为泛型是通过擦除实现的:实例的运行时类型List<Integer>是 simple ,实例List的运行时类型 List<String>[]List[],所以这个赋值不会生成 ArrayStoreException. 现在我们遇到了麻烦。我们已经将一个List<Integer> 实例存储到一个声明为仅保存的数组中List<String> 实例。在第 5 行,我们从这个数组的唯一列表中检索唯一元素。编译器会自动将检索到的元素转换为String,但它是 a Integer,所以我们 ClassCastException在运行时得到 a 。为了防止这种情况发生,第 1 行(它创建了一个泛型数组)会生成一个编译时错误。

因为数组和泛型不能很好地结合(以及其他原因),所以通常最好使用Collection对象(特别是List对象)而不是数组。

于 2009-09-29T15:22:19.723 回答
6

一般来说,在 Java 中混合泛型和数组并不是一个好主意,最好使用 ArrayList。

如果您必须使用数组,最好的处理方法是将数组创建(您的示例 2 或 3)放在单独的方法中,并使用 @SuppressWarnings("unchecked") 对其进行注释。

于 2009-09-29T15:11:23.080 回答
3

您可以创建地图的通用数组

  1. 创建地图列表。

     List<Map<String, ?>> myData = new ArrayList<Map<String, ?>>();
    
  2. 初始化数组。

     Map<String,?>[]myDataArray=new HashMap[myData .size()];
    
  3. 从列表中填充数组中的数据。

     myDataArray=myData.toArray(myDataArry);
    
于 2014-02-11T12:28:35.903 回答
2

简短的回答似乎是你真的不能。

有关它的博客,请参阅以下内容。 http://www.bloggingaboutjava.org/2006/01/java-generics-quirks/

该博客的其中一条评论指出:

实际上,工程师们使创建这样的 Array 是非法的。因此,从泛型 Class 创建数组失败。Collection.toArray 方法后跟 Cast to the Array 在编译时工作。

这不能解决问题,即在运行时无法完成 ArrayStoreCheck,但您可以通过这种方式创建一个泛型数组。

正如比尔蜥蜴所建议的那样,您最好使用

List<Map<String,Integer>>
于 2009-09-29T15:19:07.577 回答
2

我知道回复有点晚了,但我发现这个解决方法对我的情况很有帮助......希望它有帮助!

使用 HashMap 数组来存储 HashMaps..

public static void main(String[] args) {
    HashMap[] arr = new HashMap[1];//creating an array of size one..just for sake of example
    HashMap<String, String> arrMap = new HashMap<String, String>();

    //use loops to store desired key-value pairs into the HashMap which will be stored inside the array
    arrMap.put("ABC", "Name");

    //use loop to store your desired hashMap into the array at a particular index
    arr[0] = arrMap;

    //desired manipulation of the stored array.
    System.out.println(arr[0]);
}
于 2019-10-04T03:13:23.553 回答
-2

我有一个类似的问题,最好的回答是我提到这个

于 2009-09-29T15:23:19.350 回答
-5
myMaps = new HashMap<String, Integer>[10]();

所以这是错误的

为什么不制作地图列表而不是尝试制作数组?

List<Map<String, Integer>> mymaps = new ArrayList<Map<String, Integer>>(count);
于 2009-09-29T15:08:26.350 回答