Como converter Set <> em String []?

281

Preciso tirar um String[]a Set<String>, mas não sei como fazê-lo. O seguinte falha:

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

Como posso corrigi-lo para que funcione?

suter
fonte
5
Com o toArray()método que é claramente mencionado no Javadoc.
Marquês de Lorne
1
Solução Java 8: stackoverflow.com/questions/5982447/…
akhil_mittal
Java 11: Usando o novo toArray()método padrão stackoverflow.com/a/32179686/1216775
akhil_mittal

Respostas:

461

Use o Set#toArray(T[])método usando um argumento de matriz digitada do mesmo tamanho.

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

Um tamanho diferente também pode ser usado, mas isso forçaria o toArray()método a criar uma nova matriz para retornar em vez de reutilizar o argumento fornecido, que pode acabar sendo menos eficiente.

Veja também o código fonte deAbstractCollection#toArray() .

BalusC
fonte
5
Você também pode especificar matriz de tamanho 0: String[] GPXFILES1 = myset.toArray(new String[0]);
sactiw
1
@ sactiw: Isso já está coberto pela outra resposta. Leia o comentário na outra resposta por que isso não é recomendado.
BalusC
8
No Java 7, podemos usar String[] GPXFILES1 = myset.toArray(new String[0])e isso é recomendado. Atualize a resposta. "Desde as atualizações tardias do OpenJDK 6, essa chamada foi intrinsecificada, tornando o desempenho da versão do array vazio o mesmo e, às vezes, ainda melhor, comparado à versão pré-dimensionada. Também passar a matriz pré-dimensionada é perigoso para uma coleção simultânea ou sincronizada, pois é possível uma corrida de dados entre o tamanho e a chamada toArray, o que pode resultar em nulos extras no final da matriz, se a coleção tiver sido reduzida simultaneamente durante a operação ". - citado pela comunidade java.
Chaitanya
6
Encontrando esta resposta primeiro e depois fazendo mais pesquisas, há algumas evidências para apoiar que o comentário acima está correto; e a resposta aceita está desatualizada. Pegue estes exemplos de links para o que você deseja: stackoverflow.com/questions/9863742/… e um link dessa publicação do SO shipilev.net/blog/2016/arrays-wisdom-ancients .
RMSD 9/0318
60

Java 11

O novo toArraymétodo padrão na Collectioninterface permite que os elementos da coleção sejam transferidos para uma matriz recém-criada do tipo de tempo de execução desejado. Ele toma IntFunction<T[]> generatorcomo argumento e pode ser usado como:

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

Já existe um método semelhante Collection.toArray(T[])e essa adição significa que não podemos mais passar nullcomo argumento porque, nesse caso, a referência ao método seria ambígua. Mas ainda está tudo bem, pois os dois métodos lançam um NPE de qualquer maneira.

Java 8

No Java 8, podemos usar a API de fluxos:

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

Também podemos usar a versão sobrecarregada do toArray (), que assume IntFunction<A[]> generatorcomo:

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

O objetivo da função do gerador aqui é pegar um número inteiro (tamanho da matriz desejada) e produzir uma matriz do tamanho desejado. Pessoalmente, prefiro a primeira abordagem usando referência de método do que a posterior usando expressão lambda.

akhil_mittal
fonte
você não precisa stream()usar toArray(). Pode serset.toArray(new String[0])
Jakub Pomykała
1
@ JakubPomykała Isso realmente não é bom. Quando você fornece uma matriz de tamanho errado, internamente essa função precisa usar reflexão para obter uma matriz com o tamanho correto. Se esse método for necessário, basta fazer #set.toArray(new String[set.size()]);
Debosmit Ray 18/11/17
42

Use o método toArray (T [] a) :

String[] array = set.toArray(new String[0]);
JMelnik
fonte
26
Quando você passa para toArray () uma matriz de tamanho muito pequeno, o método toArray () precisa construir uma nova matriz do tamanho certo usando reflexão. Isso tem desempenho significativamente pior do que transmitir uma matriz de pelo menos o tamanho da própria coleção. Portanto, [0]deve ser substituído por [myset.size()]como na resposta aceita.
K2col
10
@ k2col parece que agora set.toArray(new String[0])tem uma perfomance melhor do queset.toArray(new String[set.size()]
Xam
1
Desde o Java 7, essa é a abordagem preferida. Veja este comentário .
acdcjunior
1
Set<String> stringSet= new HashSet<>();
String[] s = (String[])stringSet.toArray();

fonte
0

Eu estava enfrentando a mesma situação.

Começo declarando as estruturas necessárias:

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

No meu caso, eu tenho um objeto JSON e preciso que todas as chaves nesse JSON sejam armazenadas em uma matriz de cadeias. Usando a biblioteca GSON , uso JSON.keySet () para obter as chaves e mover para o meu conjunto:

myKeysInSet = json_any.keySet();

Com isso, tenho uma estrutura Set com todas as chaves, conforme necessário. Então, eu só preciso dos valores para minha matriz de strings. Veja o código abaixo:

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

Esta foi minha primeira resposta no StackOverflow. Desculpe por qualquer erro: D

João Vitor Veronese Vieira
fonte