Inicialização de uma ArrayList em uma linha

Eu quero criar uma lista de opções para fins de teste. No começo eu fiz isso:

ArrayList places = new ArrayList(); places.add("Buenos Aires"); places.add("Córdoba"); places.add("La Plata"); 

Então eu refatorei o código da seguinte forma:

 ArrayList places = new ArrayList( Arrays.asList("Buenos Aires", "Córdoba", "La Plata")); 

Existe uma maneira melhor de fazer isso?

Na verdade, provavelmente a “melhor” maneira de inicializar o ArrayList é o método que você escreveu, já que ele não precisa criar uma nova List forma alguma:

 ArrayList list = new ArrayList(); list.add("A"); list.add("B"); list.add("C"); 

O problema é que há um pouco de digitação necessária para se referir a essa instância da list .

Existem alternativas, como criar uma class interna anônima com um inicializador de instância (também conhecido como “boot de chave dupla”):

 ArrayList list = new ArrayList() {{ add("A"); add("B"); add("C"); }}; 

No entanto, eu não gosto muito desse método porque o que você tem é uma subclass de ArrayList que tem um inicializador de instância, e essa class é criada apenas para criar um object – isso parece um pouco exagerado para mim .

O que teria sido bom foi se a proposta da Coleção Literals para o Project Coin foi aceita (estava programada para ser introduzida no Java 7, mas também não é provável que seja parte do Java 8).

 List list = ["A", "B", "C"]; 

Infelizmente, isso não o ajudará aqui, pois irá inicializar uma List imutável em vez de uma ArrayList e, além disso, ainda não está disponível, se é que será.

Seria mais simples se você declarasse apenas como uma List – tem que ser uma ArrayList?

 List places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata"); 

Ou se você tiver apenas um elemento:

 List places = Collections.singletonList("Buenos Aires"); 

Isso significaria que os places são imutáveis (tentar alterá-lo fará com que uma exceção UnsupportedOperationException seja lançada).

Para criar uma lista mutável que seja uma ArrayList concreta, você pode criar uma ArrayList na lista imutável:

 ArrayList places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata")); 

A resposta simples

No Java 8 ou anterior:

 List strings = Arrays.asList("foo", "bar", "baz"); 

Isto lhe dará uma List apoiada pela matriz, por isso não pode mudar o comprimento.
Mas você pode chamar List.set , então ainda é mutável.


No Java 9:

 List strings = List.of("foo", "bar", "baz"); 

Isso lhe dará uma List imutável, por isso não pode ser alterada.
Qual é o que você quer na maioria dos casos em que você está pré-populando.


A resposta mais curta

Você pode tornar o Arrays.asList ainda mais curto com uma importação estática:

 List strings = asList("foo", "bar", "baz"); 

A importação estática:

 import static java.util.Arrays.asList; 

Que qualquer IDE moderno irá sugerir e automaticamente fazer por você.
Por exemplo, no IntelliJ IDEA você pressiona Alt+Enter e seleciona o Static import method...


No entanto, eu não recomendo encurtar o método Java 9 List.of , porque apenas se torna confuso.
List.of já é curto o suficiente e lê bem.


Usando o Stream s

Por que tem que ser uma List ?
Com o Java 8 ou posterior, você pode usar um Stream mais flexível:

 Stream strings = Stream.of("foo", "bar", "baz"); 

Você pode concatenar os Stream s:

 Stream strings = Stream.concat(Stream.of("foo", "bar"), Stream.of("baz", "qux")); 

Ou você pode ir de um Stream para uma List :

 List strings = Stream.of("foo", "bar", "baz").collect(toList()); 

Mas, de preferência, basta usar o Stream sem coletá-lo em uma List .


Se você realmente precisa especificamente de um java.util.ArrayList

(Você provavelmente não faz isso.)
Para citar o JEP 269 (ênfase minha):

Há um pequeno conjunto de casos de uso para inicializar uma instância de coleção mutável com um conjunto predefinido de valores. Geralmente é preferível que esses valores predefinidos estejam em uma coleção imutável e, em seguida, inicializar a coleção mutável por meio de um construtor de cópia.


Se você quer pré-preencher um ArrayList e adicioná-lo depois (por quê?), Use

 List strings = new ArrayList<>(asList("foo", "bar", "baz")); 

ou no Java 9:

 List strings = new ArrayList<>(List.of("foo", "bar", "baz")); 

ou usando o Stream :

 List strings = Stream.of("foo", "bar", "baz") .collect(toCollection(ArrayList::new)); 

Mas, novamente, é melhor simplesmente usar o Stream diretamente, em vez de coletá-lo em uma List .


Programa para interfaces, não para implementações

Você disse que declarou a lista como uma ArrayList em seu código, mas deve fazer isso apenas se estiver usando algum membro do ArrayList que não esteja na List .

O que você provavelmente não está fazendo.

Normalmente você deve apenas declarar as variables ​​pela interface mais geral que você vai usar (por exemplo, Iterable , Collection ou List ), e inicializá-las com a implementação específica (por exemplo, ArrayList , LinkedList ou Arrays.asList() ).

Caso contrário, você está limitando seu código a esse tipo específico e será mais difícil alterá-lo quando quiser.

Por exemplo:

 // Iterable if you just need iteration, for (String s : strings): Iterable strings = new ArrayList<>(); // Collection if you also need .size() or .stream(): Collection strings = new ArrayList<>(); // List if you also need .get(index): List strings = new ArrayList<>(); // Don't declare a specific list implementation // unless you're sure you need it: ArrayList strings = new ArrayList<>(); // You don't need ArrayList 

Outro exemplo seria sempre declarar a variável um InputStream , embora seja geralmente um FileInputStream ou um BufferedInputStream , porque um dia em breve você ou outra pessoa vai querer usar algum outro tipo de InputStream .

Se você precisar de uma lista simples de tamanho 1:

 List strings = new ArrayList(Collections.singletonList("A")); 

Se você precisar de uma lista de vários objects:

 List strings = new ArrayList(); Collections.addAll(strings,"A","B","C","D"); 

Com o Guava você pode escrever:

 ArrayList places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata"); 

Em Guava também existem outros construtores estáticos úteis. Você pode ler sobre eles aqui .

Os literais de coleção não foram incluídos no Java 8, mas é possível usar a API de stream para inicializar uma lista em uma linha bastante longa:

 List places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList()); 

Se você precisa garantir que sua List seja uma ArrayList :

 ArrayList places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new)); 
 import com.google.common.collect.ImmutableList; .... List places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata"); 

Você poderia criar um método de fábrica:

 public static ArrayList createArrayList(String ... elements) { ArrayList list = new ArrayList(); for (String element : elements) { list.add(element); } return list; } .... ArrayList places = createArrayList( "São Paulo", "Rio de Janeiro", "Brasília"); 

Mas não é muito melhor que sua primeira refatoração.

Para maior flexibilidade, pode ser genérico:

 public static  ArrayList createArrayList(T ... elements) { ArrayList list = new ArrayList(); for (T element : elements) { list.add(element); } return list; } 

Com o Java 9 , como sugerido no JDK Enhancement Proposal – 269 , isso poderia ser alcançado usando literais de coleção agora como –

 List list = List.of("A", "B", "C"); Set set = Set.of("A", "B", "C"); 

Também uma abordagem semelhante se aplicaria ao Map também –

 Map map = Map.of("k1", "v1", "k2", "v2", "k3", "v3") 

que é similar à proposta da Coleção Literals, como afirmado por @coobird também. Esclarecido ainda mais no doc do JEP –


Alternativas

As alterações de idioma foram consideradas várias vezes e rejeitadas:

Proposta de Moeda de Projeto, 29 de março de 2009

Proposta de Moeda do Projeto, 30 de março de 2009

JEP 186 discussão sobre lambda-dev, janeiro-março de 2014

As propostas de linguagem foram postas de lado em detrimento de uma proposta baseada em biblioteca, conforme resumido nesta mensagem.

Acorrentado ler sobre o mesmo ~> Qual é o ponto de sobrecarga de methods de fábrica de conveniência

No Java 9, podemos inicializar facilmente um ArrayList em uma única linha:

 List places = List.of("Buenos Aires", "Córdoba", "La Plata"); 

ou

 List places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata")); 

Essa nova abordagem do Java 9 possui muitas vantagens em relação às anteriores:

  1. Eficiência Espacial
  2. Imutabilidade
  3. Discussão segura

Veja este post para mais detalhes -> Qual é a diferença entre List.of e Arrays.asList?

Sobre a maneira mais compacta de fazer isso é:

 Double array[] = { 1.0, 2.0, 3.0}; List list = Arrays.asList(array); 

Com o Eclipse Collections (anteriormente GS Collections ), você pode escrever o seguinte:

 List list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata"); 

Você também pode ser mais específico sobre os tipos e se eles são mutáveis ​​ou imutáveis.

 MutableList mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata"); ImmutableList iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata"); 

Você também pode fazer o mesmo com Conjuntos e Malas:

 Set set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata"); MutableSet mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata"); ImmutableSet iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata"); Bag bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata"); MutableBag mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata"); ImmutableBag iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata"); 

Nota: Eu sou um committer para collections do Eclipse.

Basta usar abaixo o código da seguinte maneira.

 List list = new ArrayList() {{ add("A"); add("B"); add("C"); }}; 

Aqui está outro jeito:

 List values = Stream.of("One", "Two").collect(Collectors.toList()); 

Você pode usar as declarações abaixo:

Fragmento de código:

 String [] arr = {"Sharlock", "Homes", "Watson"}; List names = Arrays.asList(arr); 

(Deve ser um comentário, mas muito longo, então nova resposta). Como outros mencionaram, o método Arrays.asList é de tamanho fixo, mas esse não é o único problema com ele. Ele também não manipula muito bem a inheritance. Por exemplo, suponha que você tenha o seguinte:

 class A{} class B extends A{} public List getAList(){ return Arrays.asList(new B()); } 

Os resultados acima em um erro do compilador, porque List (que é o que é retornado por Arrays.asList) não é uma subclass de List , mesmo que você possa adicionar objects do tipo B a um object List . Para contornar isso, você precisa fazer algo como:

 new ArrayList(Arrays.asList(b1, b2, b3)) 

Esta é provavelmente a melhor maneira de fazer isso, esp. se você precisar de uma lista ilimitada ou precisar usar inheritance.

Como o Tom disse :

 List places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata"); 

Mas desde que você reclamou de querer um ArrayList, você deve primeiramente saber que ArrayList é uma subclass de List e você poderia simplesmente adicionar esta linha:

 ArrayList myPlaces = new ArrayList(places); 

Embora isso possa fazer com que você se queixe de “desempenho”.

Nesse caso, não faz sentido para mim, porque, como sua lista é predefinida, ela não foi definida como uma matriz (já que o tamanho é conhecido no momento da boot). E se isso é uma opção para você:

 String[] places = {"Buenos Aires", "Córdoba", "La Plata"}; 

No caso de você não se importar com as pequenas diferenças de desempenho, então você também pode copiar uma matriz para uma ArrayList de forma muito simples:

 ArrayList myPlaces = new ArrayList(Arrays.asList(places)); 

Ok, mas no futuro você precisa de um pouco mais do que apenas o nome do lugar, você também precisa de um código de país. Supondo que essa ainda seja uma lista predefinida que nunca será alterada durante o tempo de execução, é adequado usar um conjunto de enum , o que exigiria recompilation se a lista precisar ser alterada no futuro.

 enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA} 

se tornaria:

 enum Places { BUENOS_AIRES("Buenos Aires",123), CORDOBA("Córdoba",456), LA_PLATA("La Plata",789); String name; int code; Places(String name, int code) { this.name=name; this.code=code; } } 

Enum tem um método de values estáticos que retorna um array contendo todos os valores do enum na ordem em que são declarados, por exemplo:

 for (Places p:Places.values()) { System.out.printf("The place %s has code %d%n", p.name, p.code); } 

Nesse caso, acho que você não precisaria da sua ArrayList.

PS Randyaa demonstrou outra maneira legal usando o método de utilitário estático Collections.addAll .

O Java 9 possui o seguinte método para criar uma lista imutável :

 List places = List.of("Buenos Aires", "Córdoba", "La Plata"); 

que é facilmente adaptável para criar uma lista mutável, se necessário:

 List places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata")); 

Métodos similares estão disponíveis para Set e Map .

 List names = Arrays.asList("2","@2234","21","11"); 

Você pode usar o StickyList da Cactoos :

 List names = new StickyList<>( "Scott Fitzgerald", "Fyodor Dostoyevsky" ); 

Tente com esta linha de código:

 Collections.singletonList(provider) 

Sim, com a ajuda de Arrays, você pode inicializar a lista de arrays em uma linha,

 List strlist= Arrays.asList("aaa", "bbb", "ccc"); 

Em Java, você não pode fazer

 ArrayList places = new ArrayList( Arrays.asList("Buenos Aires", "Córdoba", "La Plata")); 

Como foi apontado, você precisaria fazer uma boot de chave dupla:

 List places = new ArrayList() {{ add("x"); add("y"); }}; 

Mas isso pode forçá-lo a adicionar uma anotação @SuppressWarnings("serial") ou gerar um UUID serial que seja irritante. Além disso, a maioria dos formatadores de código irá desdobrar isso em várias instruções / linhas.

Alternativamente você pode fazer

 List places = Arrays.asList(new String[] {"x", "y" }); 

mas então você pode querer fazer um @SuppressWarnings("unchecked") .

Além disso, de acordo com o javadoc, você deve ser capaz de fazer isso:

 List stooges = Arrays.asList("Larry", "Moe", "Curly"); 

Mas eu não consigo fazer isso para compilar com o JDK 1.6.

 Collections.singletonList(messageBody) 

Se você precisa ter uma lista de um item !

Coleções é do pacote java.util .

Aqui está o código de AbacusUtil

 // ArrayList List list = N.asList("Buenos Aires", "Córdoba", "La Plata"); // HashSet Set set = N.asSet("Buenos Aires", "Córdoba", "La Plata"); // HashMap Map map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3); // Or for Immutable List/Set/Map ImmutableList.of("Buenos Aires", "Córdoba", "La Plata"); ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata"); ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3); // The most efficient way, which is similar with Arrays.asList(...) in JDK. // but returns a flexible-size list backed by the specified array. List set = Array.asList("Buenos Aires", "Córdoba", "La Plata"); 

Declaração: Eu sou o desenvolvedor do AbacusUtil.

Para mim, Arrays.asList () é o melhor e conveniente. Eu sempre gosto de inicializar dessa maneira. Se você é um iniciante no Java Collections, então eu gostaria que você consultasse a boot do ArrayList

A melhor maneira de fazer isso:

 package main_package; import java.util.ArrayList; public class Stackkkk { public static void main(String[] args) { ArrayList list = new ArrayList(); add(list, "1", "2", "3", "4", "5", "6"); System.out.println("I added " + list.size() + " element in one line"); } public static void add(ArrayList list,Object...objects){ for(Object object:objects) list.add(object); } } 

Basta criar uma function que possa ter quantos elementos desejar e chamá-la para adicioná-los em uma linha.

Por que não fazer uma function de utilidade simples que faz isso?

 static  ArrayList ll(A... a) { ArrayList l = new ArrayList(a.length); for (A x : a) l.add(x); return l; } 

ll ” significa “lista literal”.

 ArrayList places = ll("Buenos Aires", "Córdoba", "La Plata"); 

Na verdade, é possível fazer isso em uma linha:

 Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")}) 
 public static  List asList(T... a) { return new ArrayList(a); } 

Esta é a implementação do Arrays.asList , então você poderia ir com

 ArrayList arr = (ArrayList) Arrays.asList("1", "2");