2

When I am trying to convert, I am getting below exception

java.lang.ArrayStoreException: java.util.HashSet
        at java.util.AbstractCollection.toArray(Unknown Source)

This is my code

Map<String, Set<String>> map = new HashMap<>();
String[] keySet = map.keySet().toArray(new String[map.size()]);
Collection<Set<String>> collections = map.values();
String[] values = collection.toArray(new String[collection.size()]);// In this line getting Exception
Naman
  • 23,555
  • 22
  • 173
  • 290
nahi Aata
  • 77
  • 2
  • 8
  • What is the desired result? Please give an example of original collection and desired array contents. – Ole V.V. Dec 07 '18 at 10:26
  • I was at first surprised that your code compiled at all. It should be known at compile time that no `Set` can be cast to `String`, so storing the sets from your original collection into a string array would be sure to fail. However, the argument is hard to generalize, so `Collection.toArray` accepts any array type on compile time (and will probably succeed even with incompatible types if the collection is empty or contains only nulls). – Ole V.V. Dec 07 '18 at 10:34

2 Answers2

2

What you're attempting to do is not possible. This is made explicit in the documentation.

The toArray method is documented to throw a java.lang.ArrayStoreException:

if the runtime type of the specified array is not a supertype of the runtime type of every element in this collection

instead, what you can do is create a stream from the map values, flatMap it! (i.e. collapse the nested sequences) then collect to an array:

 map.values()  // Collection<Set<String>>
    .stream()  // Stream<Set<String>>
    .flatMap(Collection::stream) // Stream<String>
    .toArray(String[]::new); // String[]
Ousmane D.
  • 50,173
  • 8
  • 66
  • 103
1

You can simply use Stream.flatMap as you stream over the values to collect them later into an array. This can be done as:

String[] values = map.values().stream()
                  .flatMap(Collection::stream)
                  .toArray(String[]::new);

Note: The reason why your code compiles successfully even with

toArray(new String[collection.size()])

is that Collection.toArray(T[] a) because its hard for the compiler to determine the type prior to execution for a generic type. This is the same reason why even

Integer[] values = collections.toArray(new Integer[collections.size()]);

would compile in your case, but as you can now clearly see that nowhere in your collections do you have an Integer type. Hence at runtime, a new array is allocated with the runtime type of the specified array and the size of this collection.

That is where the ArrayStoreException in your case results from since now you have a type mismatch as your collection is of type Set<String> instead of String.

Important: You cannot possibly convert to a generic array as you may further think of.

Naman
  • 23,555
  • 22
  • 173
  • 290