Jak przekonwertować zestaw <String> na String []?

281

Muszę się String[]z tego wydostać Set<String>, ale nie wiem, jak to zrobić. Następujące niepowodzenie:

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

Jak mogę to naprawić, aby działało?

suter
źródło
5
Dzięki toArray()metodzie wyraźnie wymienionej w Javadoc.
Markiz Lorne
1
Rozwiązanie Java 8: stackoverflow.com/questions/5982447/…
akhil_mittal
Java 11: Korzystanie z nowej toArray()domyślnej metody stackoverflow.com/a/32179686/1216775
akhil_mittal

Odpowiedzi:

461

Skorzystaj z Set#toArray(T[])metody biorąc argument tablicowy o tej samej wielkości.

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

Można również użyć innego rozmiaru, ale zmusiłoby to toArray()metodę do utworzenia nowej tablicy do powrotu zamiast ponownego użycia dostarczonego argumentu, co może okazać się mniej wydajne.

Zobacz także kod źródłowyAbstractCollection#toArray() .

BalusC
źródło
5
Możesz także podać tablicę o rozmiarze 0: String[] GPXFILES1 = myset.toArray(new String[0]);
sactiw
1
@sactiw: To już jest objęte inną odpowiedzią. Przeczytaj komentarz do drugiej odpowiedzi, dlaczego nie jest to zalecane.
BalusC
8
Z Java 7 możemy korzystać String[] GPXFILES1 = myset.toArray(new String[0])i jest to zalecane. Zaktualizuj odpowiedź. „Od czasu późnych aktualizacji OpenJDK 6 to wywołanie było nieodwracalne, dzięki czemu wydajność pustej tablicy jest taka sama, a czasem nawet lepsza w porównaniu z wersją o wcześniejszych rozmiarach. Również przekazywanie tablic o wcześniejszych rozmiarach jest niebezpieczne dla zbierania równoległego lub zsynchronizowanego, ponieważ możliwy jest wyścig danych między rozmową size a wywołaniem toArray, co może skutkować dodatkowymi wartościami null na końcu tablicy, jeśli kolekcja zostanie jednocześnie zmniejszona podczas operacji. ” - cytowane przez społeczność Java.
Chaitanya
6
Najpierw spotykając się z tą odpowiedzią, a następnie prowadząc dalsze badania, istnieją pewne dowody na poparcie poprawności powyższego komentarza; a zaakceptowana odpowiedź jest nieaktualna. Weź te przykładowe linki do tego, co będziesz: stackoverflow.com/questions/9863742/... , a także link z tego SO post shipilev.net/blog/2016/arrays-wisdom-ancients .
RMSD,
60

Java 11

Nowa domyślna toArraymetoda Collectioninterfejsu umożliwia przeniesienie elementów kolekcji do nowo utworzonej tablicy żądanego typu środowiska wykonawczego. To bierze IntFunction<T[]> generatorjako argument i mogą być wykorzystane jako:

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

Istnieje już podobna metoda Collection.toArray(T[])i to dodanie oznacza, że ​​nie będziemy już mogli przekazać jej nulljako argumentu, ponieważ w takim przypadku odwołanie do metody byłoby niejednoznaczne. Ale nadal jest w porządku, ponieważ obie metody i tak rzucają NPE.

Java 8

W Javie 8 możemy używać API strumieni:

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

Możemy również skorzystać z przeciążonej wersji toArray (), która przyjmuje IntFunction<A[]> generatorjako:

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

Celem funkcji generatora jest tutaj przyjęcie liczby całkowitej (rozmiar pożądanej tablicy) i utworzenie tablicy o pożądanym rozmiarze. Osobiście wolę pierwsze podejście z wykorzystaniem metody referencyjnej niż późniejsze z wykorzystaniem wyrażenia lambda.

akhil_mittal
źródło
nie musisz stream()używać toArray(). Może byćset.toArray(new String[0])
Jakub Pomykała
1
@ JakubPomykała To właściwie nie jest dobre. Gdy podasz tablicę o niewłaściwym rozmiarze, wewnętrznie ta funkcja musi użyć odbicia, aby uzyskać tablicę o prawidłowym rozmiarze. Jeśli ta metoda jest potrzebna, po prostu zróbset.toArray(new String[set.size()]);
Debosmit Ray
42

Użyj metody toArray (T [] a) :

String[] array = set.toArray(new String[0]);
JMelnik
źródło
26
Gdy przekazujesz doArray () tablicę o zbyt małym rozmiarze, metoda toArray () musi skonstruować nową tablicę o odpowiednim rozmiarze za pomocą odbicia. Ma to znacznie gorszą wydajność niż przekazywanie w tablicy przynajmniej wielkości samej kolekcji. Dlatego [0]należy go zastąpić [myset.size()]jak w przyjętej odpowiedzi.
k2col 28.04.16
10
@ k2col wydaje się, że teraz set.toArray(new String[0])ma lepszy występ niżset.toArray(new String[set.size()]
Xam
1
Od wersji Java 7 jest to preferowane podejście. Zobacz ten komentarz .
acdcjunior
1
Set<String> stringSet= new HashSet<>();
String[] s = (String[])stringSet.toArray();

źródło
0

Miałem taką samą sytuację.

Zaczynam od zadeklarowania potrzebnych struktur:

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

W moim przypadku mam obiekt JSON i potrzebuję wszystkich kluczy w tym JSON do przechowywania w tablicy ciągów. Korzystając z biblioteki GSON , używam JSON.keySet (), aby uzyskać klucze i przejść do mojego zestawu:

myKeysInSet = json_any.keySet();

Dzięki temu mam strukturę Set ze wszystkimi kluczami, tak jak potrzebowałem. Potrzebuję tylko wartości do mojej tablicy ciągów. Zobacz poniższy kod:

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

To była moja pierwsza odpowiedź w StackOverflow. Przepraszamy za jakikolwiek błąd: D

João Vitor Veronese Vieira
źródło