【问题标题】:"Cannot create generic array of .." - how to create an Array of Map<String, Object>?“无法创建 .. 的通用数组” - 如何创建 Map<String, Object> 的数组?
【发布时间】:2013-02-01 18:23:40
【问题描述】:

我想使用 simpleJdbcInsert 类和 executeBatch 方法

public int[] executeBatch(Map<String,Object>[] batch)

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/jdbc/core/simple/SimpleJdbcInsert.html

所以我需要传递一个Map&lt;String,Object&gt; 的数组作为参数。如何创建这样的数组? 我尝试的是

Map<String, Object>[] myArray = new HashMap<String, Object>[10]

错误:无法创建Map&lt;String, Object&gt;的泛型数组

List&lt;Map&lt;String, Object&gt;&gt; 会更容易,但我想我需要一个数组。那么如何创建Map&lt;String, Object&gt; 的数组呢? 谢谢

【问题讨论】:

  • 我可能会从 List 和 turn it into an array as needed 开始,因为我不喜欢处理 Java 数组..但这仍然是一个有效的问题。
  • @pst:将其发布为答案。我讨厌强制转换泛型数组(我最后一次尝试的答案是不正确的,因为我忘记了泛型是如何损坏的)。

标签: java arrays map hashmap


【解决方案1】:

由于 Java 中泛型的工作方式,您不能直接创建泛型类型的数组(例如 Map&lt;String, Object&gt;[])。相反,您创建一个原始类型 (Map[]) 的数组并将其转换为 Map&lt;String, Object&gt;[]。这将导致不可避免(但可抑制)的编译器警告。

这应该可以满足您的需要:

Map<String, Object>[] myArray = (Map<String, Object>[]) new Map[10];

您可能希望使用@SuppressWarnings("unchecked") 注释发生这种情况的方法,以防止显示警告。

【讨论】:

  • 当我使用 LinkedHashMapma​​p_array[] = new LinkedHashMap[2]; ,它也给出了这个错误?现在我不明白这里的“通用”是什么?
  • @Diffy “通用”部分是类型参数&lt;String,String&gt;。要删除错误(并将其替换为警告),请使用 LinkedHashMap&lt;String, String&gt;[] map_array = (LinkedHashMap&lt;String, String&gt;) new LinkedHashMap[2];
  • 是的,我通过简单地使用 new LinkedHashMap[2] 摆脱了错误,但如果我使用 Object 数据类型或“T”(通用 tmplate),它就会是通用的。为什么 是通用的?我在这里指定了正确的数据类型
  • “通用”在这种情况下是指“具有类型参数或由类型参数定义的类型”。所以LinkedHashMap&lt;String, String&gt;变成LinkedHashMapT变成Object(通常),等等。
【解决方案2】:

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

  1. 创建地图列表。

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

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

    myDataArray = myData.toArray(myDataArray);
    

【讨论】:

    【解决方案3】:

    我在这方面遇到了一些困难,但我想出了一些我会尽可能简单地分享的东西。

    我对泛型的经验仅限于集合,所以我在类定义中使用它们,例如:

    public class CircularArray<E> {
    

    其中包含数据成员:

    private E[] data;
    

    但是你不能把和数组的类型设为泛型,所以它有方法:

    @SuppressWarnings("unchecked")
    private E[] newArray(int size)
    {
        return (E[]) new Object[size];  //Create an array of Objects then cast it as E[]
    }
    

    在构造函数中:

    data = newArray(INITIAL_CAPACITY);  //Done for reusability
    

    这适用于泛型,但我需要一个可以排序的列表:Comparables 列表。

    public class SortedCircularArray<E extends Comparable<E>> { 
    //any E that implements Comparable or extends a Comparable class
    

    其中包含数据成员:

    private E[] data;
    

    但是我们的新类抛出 java.lang.ClassCastException:

    @SuppressWarnings("unchecked")
    private E[] newArray(int size)
    {
        //Old: return (E[]) new Object[size];  //Create an array of Objects then cast it as E[]
        return (E[]) new Comparable[size];  //A comparable is an object, but the converse may not be
    }
    

    在构造函数中一切都是一样的:

    data = newArray(INITIAL_CAPACITY);  //Done for reusability
    

    我希望这会有所帮助,如果我犯了错误,我希望我们更有经验的用户能纠正我。

    【讨论】:

      【解决方案4】:

      来自Oracle tutorial [原文]:

      您不能创建参数化类型的数组。例如,以下代码无法编译:

      List<Integer>[] arrayOfLists = new List<Integer>[2];  // compile-time error
      

      以下代码说明了将不同类型插入数组时会发生什么:

      Object[] strings = new String[2];
      strings[0] = "hi";   // OK
      strings[1] = 100;    // An ArrayStoreException is thrown.
      

      如果你用通用列表尝试同样的事情,就会出现问题:

      Object[] stringLists = new List<String>[];  // compiler error, but pretend it's allowed
      stringLists[0] = new ArrayList<String>();   // OK
      stringLists[1] = new ArrayList<Integer>();  // An ArrayStoreException should be thrown,
                                                  // but the runtime can't detect it.
      

      如果允许参数化列表的数组,则前面的代码将无法抛出所需的 ArrayStoreException。

      对我来说,这听起来很弱。我认为任何对泛型有足够了解的程序员都会很好,甚至期望在这种情况下不会抛出 ArrayStoredException。

      更重要的是,大多数程序员只会这样做:

      List<Integer> arrayOfLists = (List<Integer>) new List[2];
      

      这将使它们处于完全相同的风险中,即未抛出 ArrayStoreException。

      【讨论】:

        【解决方案5】:

        据我所知

        首先尝试创建一个 java.lang.Object 数组,然后转换为通用类型 T

        例子:

        class Example<DataType>{
            public DataType array = (DataType[]) new Object[5] ; 
        }
        

        这样,你可以创建一个泛型数据类型的数组

        【讨论】:

          【解决方案6】:
          @SuppressWarnings("unchecked")
          private Map<String,?>[] newArray(int n) {
            return new Map[n];
          }
          

          StreamMap&lt;String,?&gt; 一起使用:

            sql.executeBatch(myStream.toArray(this::newArray));
          

          ListMap&lt;String,?&gt; 一起使用:

            sql.executeBatch(myList.toArray(newArray(0));
          

          注意:JDK src 中积极使用了 SuppressWarnings 技巧 - https://github.com/AdoptOpenJDK/openjdk-jdk14/blob/master/src/java.base/share/classes/java/util/ArrayList.java#L395:L404

          致谢:@JonathanCallen

          【讨论】:

            猜你喜欢
            • 2011-07-31
            • 1970-01-01
            • 1970-01-01
            • 2013-03-26
            • 1970-01-01
            • 2022-08-02
            • 2018-05-06
            相关资源
            最近更新 更多