Inicialização da lista Java em uma linha
1. Introdução
Neste tutorial rápido, vamos investigar como podemos inicializar umList usando one-liners.
Leitura adicional:
Collections.emptyList() vs. Nova Instância da Lista
Aprenda as diferenças entre o Collections.emptyList () e uma nova instância da lista.
2. Criar a partir de uma matriz
Podemos criar umList a partir de uma matriz e, graças aos literais de matriz, podemos inicializá-los em uma linha:
List list = Arrays.asList(new String[]{"foo", "bar"});
Podemos confiar no mecanismo varargs para lidar com a criação da matriz. Com isso, podemos escrever um código mais conciso e legível:
@Test
public void givenArraysAsList_thenInitialiseList() {
List list = Arrays.asList("foo", "bar");
assertTrue(list.contains("foo"));
}
The result instance of this code implements the List interface but it isn’t a java.util.ArrayList nor a LinkedList. Em vez disso, é umList apoiado pela matriz original, que tem duas implicações.
Embora o nome da classe sejaArrayList, mas está no pacotejava.util.Arrays.
2.1. Tamanho fixo
A instância de resultado deArrays.asList terá um tamanho fixo:
@Test(expected = UnsupportedOperationException.class)
public void givenArraysAsList_whenAdd_thenUnsupportedException() {
List list = Arrays.asList("foo", "bar");
list.add("baz");
}
2.2. Referência compartilhada
A matriz original e a lista compartilham as mesmas referências aos objetos:
@Test
public void givenArraysAsList_whenCreated_thenShareReference(){
String[] array = {"foo", "bar"};
List list = Arrays.asList(array);
array[0] = "baz";
assertEquals("baz", list.get(0));
}
3. Criar a partir de um fluxo (Java 8)
Podemos facilmente converter umStream em qualquer tipo deCollection.
Portanto, com os métodos de fábrica paraStreams, podemos criar e inicializar listas em uma linha:
@Test
public void givenStream_thenInitializeList(){
List list = Stream.of("foo", "bar")
.collect(Collectors.toList());
assertTrue(list.contains("foo"));
}
Devemos marcar aqui queCollectors.toList() não garante a implementação exata doList retornado.
There’s no general contract about the mutability, serializability or thread-safety of the returned instance. Portanto, nosso código não deve depender de nenhuma dessas propriedades.
Algumas fontes destacam queStream.of(…).collect(…) pode ter maior memória e pegada de desempenho do queArrays.asList(), mas em quase todos os casos, é uma micro-otimização que há pouca diferença.
4. Métodos de fábrica (Java 9)
No JDK 9, vários métodos convenientes de fábrica foram introduzidos para coleções:
List list = List.of("foo", "bar", "baz");
Set set = Set.of("foo", "bar", "baz");
One important detail is the returned instances are immutable. Além disso, os métodos de fábrica têm várias vantagens em eficiência de espaço e segurança de linhas.
Este tópico é mais explorado emthis article.
5. Inicialização de chaves duplas
Em vários lugares, podemos encontrar um método chamado‘double brace initialization' que se parece com:
@Test
public void givenAnonymousInnerClass_thenInitialiseList() {
List cities = new ArrayList() {{
add("New York");
add("Rio");
add("Tokyo");
}};
assertTrue(cities.contains("New York"));
}
O nome‘double brace initialization' é bastante enganador. A sintaxe pode parecer compacta e elegante, mas esconde perigosamente o que está acontecendo sob o capô.
Na verdade, não há um elemento de sintaxe‘double brace' em Java, esses são dois blocos formatados intencionalmente desta forma.
With the outer braces, we declare an anonymous inner class which will be a subclass of the ArrayList. Dentro dessas chaves, podemos declarar os detalhes de nossa subclasse.
Como sempre, podemos usar blocos inicializadores de instância e é daí que o par interno de chaves vem.
A brevidade desta sintaxe é tentadora, mas é considerada um antipadrão.
Para ler mais sobre a inicialização de chave dupla, dê uma olhada em nosso artigohere.
6. Conclusão
Modern Java offers several options to create a Collection in one line. O método que escolhemos se deve quase inteiramente à preferência pessoal, ao invés de raciocínio técnico.
Uma lição importante é que, embora pareça elegante,the anti-pattern of anonymous inner class initialization (a.k.a. ‘double brace') has many negative side-effects.
Como sempre, o código está disponívelover on GitHub.