311

I need to get a String[] out of a Set<String>, but I don't know how to do it. The following fails:

Map<String, ?> myMap = gpxlist.getAll();
Set<String> myset = myMap.keySet();
String[] GPXFILES1 = (String[]) myset.toArray(); // Here it fails.

How can I fix it so that it works?

dmon
  • 30,048
  • 8
  • 87
  • 96
suter
  • 3,325
  • 3
  • 17
  • 9

7 Answers7

506

Use the Set#toArray(IntFunction<T[]>) method taking an IntFunction as generator.

String[] GPXFILES1 = myset.toArray(String[]::new);

If you're not on Java 11 yet, then use the Set#toArray(T[]) method taking a typed array argument of the same size.

String[] GPXFILES1 = myset.toArray(new String[myset.size()]);

While still not on Java 11, and you can't guarantee that myset is unmodifiable at the moment of conversion to array, then better specify an empty typed array.

String[] GPXFILES1 = myset.toArray(new String[0]);
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
66

Java 11

The new default toArray method in Collection interface allows the elements of the collection to be transferred to a newly created array of the desired runtime type. It takes IntFunction<T[]> generator as argument and can be used as:

 String[] array = set.toArray(String[]::new);

There is already a similar method Collection.toArray(T[]) and this addition means we no longer be able to pass null as argument because in that case reference to the method would be ambiguous. But it is still okay since both methods throw a NPE anyways.

Java 8

In Java 8 we can use streams API:

String[] array = set.stream().toArray(String[]::new);

We can also make use of the overloaded version of toArray() which takes IntFunction<A[]> generator as:

String[] array = set.stream().toArray(n -> new String[n]);

The purpose of the generator function here is to take an integer (size of desired array) and produce an array of desired size. I personally prefer the former approach using method reference than the later one using lambda expression.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
  • you don't need `stream()` to use `toArray()`. It can be `set.toArray(new String[0])` – Jakub Pomykała May 12 '17 at 10:21
  • 1
    @JakubPomykała That is actually not good. When you give an array of wrong size, internally that function has to use reflection to get an array correct size. If this method is needed, just do `set.toArray(new String[set.size()]);` – Debosmit Ray Nov 18 '17 at 03:02
  • 1
    @DebosmitRay [Giving an empty array is actually faster.](https://shipilev.net/blog/2016/arrays-wisdom-ancients/) – Johannes Kuhn Oct 28 '20 at 20:49
44

Use toArray(T[] a) method:

String[] array = set.toArray(new String[0]);
d1e
  • 6,372
  • 2
  • 28
  • 41
  • 26
    When you pass toArray() an array of too small size, the toArray() method has to construct a new array of the right size using reflection. This has significantly worse performance than passing in an array of at least the size of the collection itself. Therefore `[0]` should be replaced with `[myset.size()]` as in the accepted answer. – k2col Apr 28 '16 at 21:23
  • 13
    @k2col it seems that now `set.toArray(new String[0])` has a better perfomance than `set.toArray(new String[set.size()]` – Xam Apr 14 '18 at 20:13
  • 1
    Since Java 7 this is the preferred approach. See [this comment](https://stackoverflow.com/questions/5982447/how-to-convert-setstring-to-string#comment84904339_5982478). – acdcjunior Nov 22 '19 at 23:37
5

Guava style:

Set<String> myset = myMap.keySet();
FluentIterable.from(mySet).toArray(String.class);

more info: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/FluentIterable.html

Gene Bo
  • 11,284
  • 8
  • 90
  • 137
user7708
  • 131
  • 2
  • 3
2

In Java 11 we can use Collection.toArray(generator) method. The following code will create a new array of String:

Set<String> set = Set.of("one", "two", "three");
String[] array = set.toArray(String[]::new)

See: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Collection.html#toArray(java.util.function.IntFunction)

Rafal Borowiec
  • 5,124
  • 1
  • 24
  • 20
2
Set<String> stringSet= new HashSet<>();
String[] s = (String[])stringSet.toArray();
0

I was facing the same situation.

I begin by declaring the structures I need:

Set<String> myKeysInSet = null; String[] myArrayOfString = null;

In my case, I have a JSON object and I need all the keys in this JSON to be stored in an array of strings. Using the GSON library, I use JSON.keySet() to get the keys and move to my Set :

myKeysInSet = json_any.keySet();

With this, I have a Set structure with all the keys, as I needed it. So I just need to the values to my Array of Strings. See the code below:

myArrayOfString = myKeysInSet.toArray(new String[myKeysInSet.size()]);

This was my first answer in StackOverflow. Sorry for any error :D