【问题标题】:How does one instantiate an array of maps in Java?如何在 Java 中实例化一组地图?
【发布时间】:2010-12-02 08:45:34
【问题描述】:

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

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

【问题讨论】:

    标签: java arrays generics map instantiation


    【解决方案1】:
    myMaps = new HashMap<String, Integer>[10]();
    

    那就错了

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

    List<Map<String, Integer>> mymaps = new ArrayList<Map<String, Integer>>(count);
    

    【讨论】:

    • 不对:“类型不匹配:无法从 Map 转换为 Map[]”。
    • 奇怪,你是对的 - 猜我在实践中从未这样做过。
    【解决方案2】:

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

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

    【讨论】:

    • @SuppressWarnings 是唯一不会收到警告的方法,但为什么要使用单独的方法呢?我觉得注释作业是一个更好的选择。
    • 警告是说有些事情做错了。仅仅压制它是一个非常糟糕的主意。
    • @Tom Hawtin 如果它总是错误的,那将是错误而不是警告。因此,如果没有更好的方法来实现相同的目标,有时(很少)可以抑制警告。
    【解决方案3】:

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

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

    似乎工作得很好。

    请参阅Java theory and practice: Generics gotchas,详细了解为什么不鼓励将数组与泛型混合使用。

    更新:

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

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

    从此开始,您只需将HashSet 更改为ArrayListPriorityQueue 或任何其他实现Collection 的类。

    【讨论】:

    • 你秒杀我。我可能会建议您改用 Collection,这样您也可以根据需要切换到 Set 实现。
    • @Drew:好主意!作为替代,我会将其添加到我的答案中。
    • 您发布的链接表明执行 OP 所需的合法方法是 myMaps = new Map&lt;?,?&gt;[count]。但它也说这是一件危险的事情,将数组和通用容器混合在一起通常是一件坏事。
    • 有人应该告诉 Springframework 团队,他们希望您为他们提供一组用于 JDBC 批处理操作的通用 Maps:NamedParameterJdbcTemplate.batchUpdate(String sql, Map&lt;String, ?&gt;[] batchValues)docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
    【解决方案4】:

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

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

    博客中的一位 cmet 指出:

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

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

    根据蜥蜴比尔的建议,您可能最好使用 a

    List<Map<String,Integer>>
    

    【讨论】:

      【解决方案5】:

      您无法安全地创建泛型数组。 Effective Java 2nd Edition 在chapter on 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&lt;Integer&gt; 包含一个 元素。第 3 行存储 List&lt;String&gt; 数组转换为 Object 数组变量,这是合法的,因为 数组是协变的。 4号线门店 将List&lt;Integer&gt; 放入鞋底 Object 数组的元素,其中 成功是因为泛型是 通过擦除实现:运行时 List&lt;Integer&gt; 实例的类型是 简单的List,以及运行时类型 List&lt;String&gt;[] 实例是 List[],所以 此作业不会生成 ArrayStoreException。现在我们在 麻烦。我们存储了一个List&lt;Integer&gt; 实例到一个数组中 宣布仅持有List&lt;String&gt; 实例。在第 5 行,我们检索 唯一列表中的唯一元素 这个数组。编译器自动 将检索到的元素转换为String, 但它是一个Integer,所以我们得到一个 ClassCastException 在运行时。在 为了防止这种情况发生, 第 1 行(创建一个通用数组) 生成编译时错误。

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

      【讨论】:

      • 这个例子在 IMO 上没有说服力。您已经可以使用普通数组更轻松地破坏类型安全 - 查看 ArrayStoreException。
      • 这是重点。数组可以说是被破坏的,因为它们是协变的——你可以将一个子类数组分配给需要一个超类数组的东西。至少当您尝试插入不应该在数组中的东西时,您会得到 ArrayStoreException。使用泛型,您甚至不会得到异常。由于擦除,List 不会执行运行时检查您插入的内容实际上是 T 类型的。检查都是在编译时完成的,因此类型是静态合理的更为重要。跨度>
      【解决方案6】:

      我有一个similar question,最好的回复是this

      【讨论】:

        【解决方案7】:

        您可以创建通用地图数组

        1. 创建地图列表。

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

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

           myDataArray=myData.toArray(myDataArry);
          

        【讨论】:

          【解决方案8】:

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

          使用一个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]);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-05-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-06-05
            • 2012-01-20
            • 1970-01-01
            • 2011-06-05
            相关资源
            最近更新 更多