Java 9 introduziu novos métodos de fábrica para listas List.of
:
List<String> strings = List.of("first", "second");
Qual é a diferença entre a opção anterior e a nova? Ou seja, qual é a diferença entre isso:
Arrays.asList(1, 2, 3);
e isto:
List.of(1, 2, 3);
Respostas:
Arrays.asList
retorna uma lista mutável enquanto a lista retornada porList.of
é imutável :Arrays.asList
permite elementos nulos enquantoList.of
não:contains
se comporta de maneira diferente com nulos:Arrays.asList
retorna uma visão do array passado, então as mudanças no array serão refletidas na lista também. PoisList.of
isso não é verdade:fonte
List.contains(Object o)
javadoc de : "Lança [...] NullPointerException - se o elemento especificado for nulo e esta lista não permitir elementos nulos (opcional)". Ou na introdução longa da interface que poucos lêem: "Algumas implementações de coleção têm restrições sobre os elementos que podem conter"List.of
não retornar algumImmutableList
tipo, seu nome real é apenas um detalhe de implementação não-pública. Se fosse público e alguém o publicasseList
novamente, qual seria a diferença? Onde está a diferença paraArrays.asList
, que retorna umaList
implementação não pública , que lança uma exceção ao tentaradd
ouremove
, ou a lista retornada porCollections.unmodifiableList
que não permite nenhuma modificação? É tudo sobre contratos especificados naList
interface. As interfaces de coleções com métodos opcionais sempre foram OOP impuras desde Java 1.2 ...As diferenças entre
Arrays.asList
eList.of
Veja os JavaDocs e esta palestra de Stuart Marks (ou versões anteriores).
Usarei o seguinte para os exemplos de código:
Imutabilidade estrutural (Ou: inalterabilidade)
Qualquer tentativa de mudança estrutural
List.of
resultará em umUnsupportedOperationException
. Isso inclui operações como adicionar , definir e remover . Você pode, entretanto, alterar o conteúdo dos objetos na lista (se os objetos não forem imutáveis), para que a lista não seja "completamente imutável".Este é o mesmo destino para listas não modificáveis criadas com
Collections.unmodifiableList
. Apenas esta lista é uma visualização da lista original, portanto, ela pode mudar se você alterar a lista original.Arrays.asList
não é completamente imutável, não tem uma restrição sobreset
.Da mesma forma, alterar a matriz de apoio (se você a mantiver) mudará a lista.
A imutabilidade estrutural vem com muitos efeitos colaterais relacionados à codificação defensiva, simultaneidade e segurança que estão além do escopo desta resposta.
Hostilidade nula
List.of
e qualquer coleção desde Java 1.5 não permitenull
como um elemento. A tentativa de passarnull
como um elemento ou mesmo uma pesquisa resultará em umNullPointerException
.Como
Arrays.asList
é uma coleção de 1.2 (o Framework de coleções), ele permitenull
s.Formulário serializado
Como
List.of
foi introduzido no Java 9 e as listas criadas por esse método têm sua própria forma serializada (binária), elas não podem ser desserializadas em versões anteriores do JDK (sem compatibilidade binária ). No entanto, você pode cancelar / serializar com JSON, por exemplo.Identidade
Arrays.asList
chamadas internamentenew ArrayList
, o que garante a desigualdade de referência.List.of
depende da implementação interna. As instâncias retornadas podem ter igualdade de referência, mas como isso não é garantido, você não pode confiar nela.Vale ressaltar que as listas são iguais (via
List.equals
) se contiverem os mesmos elementos na mesma ordem, independentemente de como foram criadas ou das operações que suportam.Implementação (aviso: os detalhes podem mudar nas versões)
Se o número de elementos na lista de
List.of
for 2 ou menos, os elementos serão armazenados em campos de uma classe especializada (interna). Um exemplo é a lista que armazena 2 elementos (fonte parcial):Caso contrário, eles são armazenados em uma matriz de maneira semelhante a
Arrays.asList
.Eficiência de tempo e espaço
As
List.of
implementações baseadas em campo (tamanho <2) têm um desempenho ligeiramente mais rápido em algumas operações. Como exemplos,size()
pode retornar uma constante sem buscar o comprimento do array econtains(E e)
não requer sobrecarga de iteração.Construir uma lista não modificável via
List.of
também é mais rápido. Compare o construtor acima com 2 atribuições de referência (e até mesmo aquele para quantidade arbitrária de elementos) paraque cria 2 listas mais outra sobrecarga. Em termos de espaço, você economiza o
UnmodifiableList
invólucro e alguns centavos. Em última análise, a economia noHashSet
equivalente é mais convincente.Tempo de conclusão: use
List.of
quando quiser uma lista que não muda eArrays.asList
quando quiser uma lista que pode mudar (como mostrado acima).fonte
Arrays.asList
não é totalmente mutável.asList.add(1);
joga umUnsupportedOperationException
.List.of
nenhum momento que as pessoas possam querer chamarcontains
e não ficar surpreso com um NullPointerException.Vamos resumir as diferenças entre List.of e Arrays.asList
List.of
pode ser usado melhor quando o conjunto de dados é menor e inalterado, enquantoArrays.asList
pode ser usado melhor no caso de um conjunto de dados grande e dinâmico.List.of
ocupa muito menos espaço de sobrecarga porque tem implementação baseada em campo e consome menos espaço de heap, tanto em termos de sobrecarga fixa quanto em uma base por elemento. enquantoArrays.asList
ocupa mais espaço de overhead porque durante a inicialização cria mais objetos no heap.A coleção retornada por
List.of
é imutável e, portanto, segura para threads, enquanto a coleção retornada porArrays.asList
é mutável e não segura para threads. (Instâncias de coleção imutáveis geralmente consomem muito menos memória do que suas contrapartes mutáveis.)List.of
não permite elementos nulos enquantoArrays.asList
permite elementos nulos .fonte
Arrays.asList
versusList.of
, visto que o primeiro é literalmente apenas um invólucro em torno de um array. Pelo menos a implementação do OpenJDK parece ter uma sobrecarga extremamente pequena. Na verdade,List.of
seria necessário fazer cópias de qualquer array passado, então, a menos que o próprio array seja submetido a GC em breve, parece queList.of
tem uma pegada de memória significativamente maior.List.of(x)
eList.of(x, y)
são mais eficientes porque não alocam matrizesList.of
métodos não precisam retornar novas listas a cada vez. Essas listas têm uma identidade não especificada, portanto, pode haver armazenamento em cache, deduplicação ou escalarização tratada no nível da JVM. Se não nesta versão, talvez na próxima. É permitido pelo contrato. Em contraste,Array.asList
depende da identidade do array que você está passando, já que a lista resultante é uma visualização mutável no array, refletindo todas as mudanças bidirecionais.Além das respostas acima, existem certas operações nas quais
List::of
eArrays::asList
diferem:Mais sobre Coleções :: singletonList vs. Lista de
fonte