46

I would like to use simpleJdbcInsert class and executeBatch method

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

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

So I need to pass an array of Map<String,Object> as parameter. How to create such an array? What I tried is

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

It is error: Cannot create generic array of Map<String, Object>

A List<Map<String, Object>> would be easier, but I guess I need an array. So how to create an array of Map<String, Object> ? Thanks

user2079650
  • 463
  • 1
  • 4
  • 4
  • I would likely start with a List and [turn it into an array as needed](http://docs.oracle.com/javase/6/docs/api/java/util/List.html#toArray(T[])), since I dislike dealing with Java arrays .. but this is still a valid question nevertheless. –  Feb 17 '13 at 02:32
  • @pst: Post that as an answer. I hate casting generic arrays (my last attempt at an answer was incorrect because I forgot how broken generics were). – nneonneo Feb 17 '13 at 02:44

6 Answers6

78

Because of how generics in Java work, you cannot directly create an array of a generic type (such as Map<String, Object>[]). Instead, you create an array of the raw type (Map[]) and cast it to Map<String, Object>[]. This will cause an unavoidable (but suppressible) compiler warning.

This should work for what you need:

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

You may want to annotate the method this occurs in with @SuppressWarnings("unchecked"), to prevent the warning from being shown.

TMG
  • 2,620
  • 1
  • 17
  • 40
Jonathan Callen
  • 11,301
  • 2
  • 23
  • 44
  • when i use LinkedHashMapmap_array[] = new LinkedHashMap[2]; , it also gives this error? Now i dont understand what is 'generic' here? – Diffy Jun 21 '14 at 19:47
  • @Diffy The "generic" part is the type parameters ``. To remove the error (and replace it with a warning), use `LinkedHashMap[] map_array = (LinkedHashMap) new LinkedHashMap[2];` – Jonathan Callen Jun 22 '14 at 01:20
  • Yes, i got out of the error by using simply new LinkedHashMap[2], but it would have been generic if i would have used an Object datatype or "T" (generic tmplate ). How come is generic? I am specifying the proper datatype here – Diffy Jun 22 '14 at 10:52
  • "Generic" in this case means "Type that has type parameters, or is defined by a type parameter". So `LinkedHashMap` becomes `LinkedHashMap`, `T` becomes `Object` (normally), etc. – Jonathan Callen Jun 22 '14 at 21:21
1

You can create generic array of map.

  1. Create a list of maps.

    List<Map<String, ?>> myData = new ArrayList<Map<String, ?>>();
    
  2. Initialize array.

    Map<String,?>[] myDataArray = new HashMap[myData.size()];
    
  3. Populate data in array from list.

    myDataArray = myData.toArray(myDataArray);
    
Ruju
  • 961
  • 1
  • 12
  • 24
0

I have had some difficulty with this, but I have figured out a few things that I will share as simply as possible.

My experience with generics is limited to collections, so I use them in the class definitions, such as:

public class CircularArray<E> {

which contains the data member:

private E[] data;

But you can't make and array of type generic, so it has the method:

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

In the constructor:

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

This works for generic generics, but I needed a list that could be sorted: a list of Comparables.

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

which contains the data member:

private E[] data;

But our new class throws 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
}

In the constructor everything is the same:

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

I hope this helps and I hope our more experienced users will correct me if I've made mistakes.

0

From Oracle tutorial [sic]:

You cannot create arrays of parameterized types. For example, the following code does not compile:

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

The following code illustrates what happens when different types are inserted into an array:

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

If you try the same thing with a generic list, there would be a problem:

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.

If arrays of parameterized lists were allowed, the previous code would fail to throw the desired ArrayStoreException.

To me, it sounds very weak. I think that any programmer with a sufficient understanding of generics, would be perfectly fine, and even expect, that the ArrayStoredException is not thrown in such case.

Even more, most programmers will simply do:

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

which will put them in exactly the same risk of ArrayStoreException not thrown.

Stick Hero
  • 31
  • 1
0

As far my knowledge

Frist try to create an array of java.lang.Object and then cast to Generic type T

Example:

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

In this way, you can create an array of generic datatype

Mr. Suryaa Jha
  • 1,516
  • 16
  • 10
0
@SuppressWarnings("unchecked")
private Map<String,?>[] newArray(int n) {
  return new Map[n];
}

using with a Stream of Map<String,?>:

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

using with a List of Map<String,?>:

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

NOTE: the SuppressWarnings trick is actively used in JDK src - https://github.com/AdoptOpenJDK/openjdk-jdk14/blob/master/src/java.base/share/classes/java/util/ArrayList.java#L395:L404

Credits to: @JonathanCallen

epox
  • 9,236
  • 1
  • 55
  • 38