Inicialização de um ArrayList em uma linha


2756

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

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

Em seguida, refatorei o código da seguinte maneira:

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

Existe uma maneira melhor de fazer isso?


34
Se isso se destina a testes de unidade, tente fazer um groovy para um balanço. Você pode escrever seu código de teste em que ao testar código java e usoArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"]
ripper234

3
No Java SE 7, você pode substituir o tipo parametrizado do construtor por um conjunto vazio de parâmetros de tipo (<>): Map <String, List <String>> myMap = new HashMap <> ();
Rose


2
usar dupla inicialização órtese :)
Mohammadreza Khatami

8
Stream.of ("val1", "val2"). Collect (Collectors.toList ()); // cria a solução ArrayList, Java8.
Torina

Respostas:


2025

Na verdade, provavelmente a melhor "maneira" de inicializar ArrayListé o método que você escreveu, pois não precisa criar um novo de Listforma alguma:

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

O problema é que há bastante digitação necessária para se referir a essa listinstância.

Existem alternativas, como criar uma classe interna anônima com um inicializador de instância (também conhecido como "inicialização entre chaves"):

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

No entanto, não gosto muito desse método, porque o que você acaba ArrayListcriando é uma subclasse com um inicializador de instância e essa classe é criada apenas para criar um objeto - isso me parece um pouco exagerado.

O que seria bom seria se a proposta da Collection Literals para o Project Coin fosse aceita (ela deveria ser introduzida no Java 7, mas também não é provável que faça parte do Java 8).

List<String> list = ["A", "B", "C"];

Infelizmente, não o ajudará aqui, pois inicializará um imutável em Listvez de um ArrayListe, além disso, ainda não está disponível, se for o caso.


172
Consulte stackoverflow.com/questions/924285 para obter mais informações sobre a inicialização entre chaves, prós e contras.
Eddie

6
@ Eddie: Boa chamada para o link - uma frase na inicialização entre chaves não é suficiente para descrevê-lo completamente.
coobird

2
Só funciona se você não estiver confiando na lista de boxe automático <Double> list = [1.0, 2.0, 3.0]; falha.
Richard B

1
Você está perdendo um ponto e vírgula na inicialização-list dupla
Don Laringe

6
Como esta resposta é o projeto Coin mais votado e mencionado, acho que você deve chamar o java 9 enviado com a sintaxe List.of (...): docs.oracle.com/javase/9/docs/api/java/util/ List.html # of-E ...-
Asaf

2155

Seria mais simples se você o declarasse apenas como List- precisa ser um ArrayList?

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

Ou se você tiver apenas um elemento:

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

Isso significa que placesé imutável (tentar alterá-lo fará com que uma UnsupportedOperationExceptionexceção seja lançada).

Para criar uma lista mutável que seja concreta, ArrayListvocê pode criar uma a ArrayListpartir da lista imutável:

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

18
@ Marcase: Você não pode alterar sua classe para usar uma lista em vez de ArrayList?
Lawrence Dol

74
De acordo com a minha resposta, se você não estiver usando métodos específicos ArrayList, seria melhor projetar alterar a declaração para List. Especifique interfaces, não implementações.
Christoffer Hammarström

9
@Christoffer Hammarström: se ele alterar a declaração para List e usar a lista <>> lugares = Arrays.asList (...); ele não será capaz de usar o places.add ("blabla")
maks

57
Só para esclarecer, asList(...)retorna um tamanho fixo Listque explode em operações mutantes como removee clear, coisas que o Listcontrato alega suporte. Mesmo que você tenha deixado a declaração como List, você precisará usar List l = new ArrayList(asList(...))para obter um objeto que não gere exceções OperationNotSupported. Princípio da substituição de Liskov alguém?
Splash

5
@ Splash: removee clearsão operações opcionais List, o mesmo asList(...)acontece com o contrato. Em nenhum lugar o OP diz que ele precisa adicionar mais elementos posteriormente, o exemplo é apenas um Listque precisa ser inicializado com três elementos.
Christoffer Hammarström

872

A resposta simples

No Java 9 ou posterior, depois List.of()foi adicionado:

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

Com o Java 10 ou posterior, isso pode ser reduzido com a varpalavra - chave.

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

Isso lhe dará um imutável List , por isso não pode ser alterado.
Qual é o que você deseja na maioria dos casos em que está pré-preenchendo-o.


Java 8 ou anterior:

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

Isso lhe dará um Listrespaldo por uma matriz, portanto, não pode alterar o comprimento.
Mas você pode ligar List.set, por isso ainda é mutável .


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

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

A importação estática:

import static java.util.Arrays.asList;  

O que qualquer IDE moderno sugerirá e fará automaticamente por você.
Por exemplo, no IntelliJ IDEA, você pressiona Alt+Entere seleciona Static import method....


No entanto, eu não recomendo encurtar o List.ofmétodo para of, porque isso se torna confuso.
List.ofjá é curto o suficiente e lê bem.


Usando Streams

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

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

Você pode concatenar Streams:

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

Ou você pode ir de a Streampara List:

import static java.util.stream.Collectors.toList;

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

Mas de preferência, basta usar o Streamsem coletá-lo para a List.


Se você realmente precisa especificamente de umjava.util.ArrayList

(Você provavelmente não.)
Para citar 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 ter esses valores predefinidos 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 tanto um pré-popular ArrayList e adicionar a ele posteriormente (por quê?), Uso

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

ou no Java 8 ou anterior:

ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");

ou usando Stream:

import static java.util.stream.Collectors.toCollection;

ArrayList<String> strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

Mas, novamente, é melhor usar o Streamdiretamente em vez de coletá-lo para a List.


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

Você disse que declarou a lista como ArrayListno seu código, mas você só deve fazer isso se estiver usando algum membro do ArrayListqual não esteja List.

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

Normalmente, você deve apenas declarar variáveis pela interface mais geral que você está indo para uso (por exemplo Iterable, Collectionou List), e inicialize-los com a aplicação específica (por exemplo ArrayList, LinkedListou Arrays.asList()).

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

Por exemplo, se você está passando um ArrayListpara um void method(...):

// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) { 
    for (String s : strings) { ... } 
}

// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
    if (!strings.isEmpty()) { strings.stream()... }
}

// List if you also need .get(index):
void method(List<String> strings) {
    strings.get(...)
}

// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
    ??? // You don't want to limit yourself to just ArrayList
}

Outro exemplo seria sempre declarar a variável an InputStreammesmo que seja geralmente uma FileInputStreamou a BufferedInputStream, porque um dia em breve você ou outra pessoa desejará usar algum outro tipo de InputStream.


3
@ jollyroger: Arrays.asListé um método estático. Veja docs.oracle.com/javase/1.5.0/docs/guide/language/…
Christoffer Hammarström

2
@ ChristofferHammarström Nesse caso, minha mente iniciante me diz que a importação estática mostra uma forte semelhança com variáveis ​​globais e os perigos que pertencem a esse uso. Essa suposição está correta e também é o motivo da resposta semelhante acima, que obteve mais votos?
precisa

2
A resposta acima, acho que você está falando, foi feita um ano antes. E não, o problema com variáveis ​​globais é que elas são mutáveis. Eles não têm nada a ver com importações estáticas.
Christoffer Hammarström

2
Se você não deseja a importação estática, também pode definir o caminho completo para o método asList estático, assim: List <String> strings = java.util.Arrays.asList ("", "");
Geert Weening

2
Ou você pode usar import java.util.Arrays; e Arrays.asList ("", ""); Você não precisa usar uma importação estática. Você não precisa usar um caminho completo. Os métodos estáticos não se importam com a importação. Eles ficam irritados se você usar uma instância para encontrá-los.
Candied_orange 12/09

111

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

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

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

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

57

Com o Goiaba, você pode escrever:

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

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


1
Eu tenho certeza que você pode fazer isso com apenas, java.util.Arraystais como,List<String> names = Arrays.asList("Beckah", "Sam", "Michael");
beckah 26/06

2
@beckah Arrays.asLists método cria objeto do tipo List, enquanto pergunta é sobre a criação de ArrayList
Paweł Adamski


34

Literais de coleção não chegaram ao Java 8, mas é possível usar a API Stream para inicializar uma lista em uma linha bastante longa:

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

Se você precisa garantir que você Listé um ArrayList:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));

34

Com e acima, conforme sugerido no JEP 269: Métodos de conveniência para coleções , isso pode ser alcançado usando literais de coleção agora com -

List<String> list = List.of("A", "B", "C");

Set<String> set = Set.of("A", "B", "C");

Uma abordagem semelhante se aplicaria a Map-

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

que é semelhante à proposta Literais de coleções, conforme declarado por @coobird. Mais esclarecido também no JEP -


Alternativas

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

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

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

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

As propostas de idioma foram separadas em preferência a uma proposta baseada em biblioteca, conforme resumido nesta mensagem.

Relacionado: Qual é o objetivo dos Métodos de Fábrica de Conveniência sobrecarregados para Coleções em Java 9


31
import com.google.common.collect.ImmutableList;

....

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

4
Não quero adicionar uma nova dependência apenas para fazer isso.
Macarse

6
É o mesmo Collections.unmodifiableList(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"))que acontece unmodifiableList(asList("Buenos Aires", "Córdoba", "La Plata"))com as importações estáticas. Você não precisa do Google Collections para isso.
Christoffer Hammarström

9
Não, não é o mesmo. Como ImmutableList está documentando sua imutabilidade no tipo de resultado, quando unmodifiableList a mascara como uma Lista normal.
David Pierre

2
Em vez da imutável, as coleções do Google também oferecem uma lista de matrizes mutáveis: List <> = Lists.newArrayList ("Buenos Aires", "Córdoba", "La Plata");
L. Holanda

3
Você passará isso ImmutableListpara outros métodos que usam a List, e então você perdeu essa documentação de qualquer maneira.
Christoffer Hammarström

23

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

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

....

ArrayList<String> places = createArrayList(
  "São Paulo", "Rio de Janeiro", "Brasília");

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

Para maior flexibilidade, pode ser genérico:

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

1
Olhe para o post original, ele está pedindo a inicialização do array em uma linha , não em 7 linhas adicionais.
L. Holanda

7
@LeoHolanda: Criar métodos de fábrica para cada coisinha é demais, eu concordo. Mas, dependendo da situação e do número de vezes que esse método será usado, pode fazer sentido criá-lo. A criação de camadas extras de abstração visa remover a complexidade, criando métodos mais significativos que capturam a intenção do designer.
Jordão


8

A maneira mais compacta de fazer isso é:

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

8

Basta usar o código abaixo da seguinte maneira.

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

2
@bsd Você pode usar este método para declarar a lista antes de inserir qualquer método. Portanto, ao definir variáveis ​​de classe, o conteúdo pode ser adicionado à lista sem a necessidade de chamar um método para fazer isso.
precisa saber é o seguinte

2
a inicialização entre chaves deve ser evitada o máximo possível. Veja: stackoverflow.com/a/924326/760393
Raúl

8

Com o Eclipse Collections, você pode escrever o seguinte:

List<String> 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<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Você também pode fazer o mesmo com conjuntos e bolsas:

Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Nota: Sou um colaborador das Coleções Eclipse.


7

Aqui está outra maneira:

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

7

(Deve ser um comentário, mas muito longo, para uma nova resposta). Como outros já mencionaram, o Arrays.asListmétodo é de tamanho fixo, mas esse não é o único problema. Também não lida muito bem com herança. Por exemplo, suponha que você tenha o seguinte:

class A{}
class B extends A{}

public List<A> getAList(){
    return Arrays.asList(new B());
}

O resultado acima resulta em um erro do compilador, porque List<B>(que é retornado por Arrays.asList) não é uma subclasse de List<A>, mesmo que você possa adicionar objetos do tipo B a um List<A>objeto. Para contornar isso, você precisa fazer algo como:

new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))

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


6

Você pode usar as instruções abaixo:

Fragmento de código:

String [] arr = {"Sharlock", "Homes", "Watson"};

List<String> names = Arrays.asList(arr);

Você pode incorporar a primeira expressão para ter uma solução compacta:letters = Arrays.asList(new String[]{"A", "B", "C"});
Pavel Repin

5

Como Tom disse :

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

Mas desde que você se queixou de querer um ArrayList, primeiro você deve saber que ArrayList é uma subclasse de List e você pode simplesmente adicionar esta linha:

ArrayList<String> myPlaces = new ArrayList(places);

Embora isso possa fazer você reclamar de 'desempenho'.

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

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

Caso você não se importe com as pequenas diferenças de desempenho, você também pode copiar uma matriz para um ArrayList de maneira muito simples:

ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));

Ok, mas no futuro você precisa um pouco mais do que apenas o nome do local, também precisa de um código de país. Supondo que ainda seja uma lista predefinida que nunca será alterada durante o tempo de execução, é adequado usar um enumconjunto, o que exigiria uma recompilação 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;
    }
}

Os enum têm um valuesmétodo estático que retorna uma matriz que contém 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 interessante de usar o método utilitário estático Collections.addAll .


5

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

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

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

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

Métodos semelhantes estão disponíveis para Sete Map.


1
É bom que você tenha explicitamente dito "lista imutável" e mostrado outro exemplo de lista mutável, porque deixa claro qual usar quando.
28519 Cherit

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

4

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

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

4

Você pode usar StickyListdo Cactoos :

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

3

Tente com esta linha de código:

Collections.singletonList(provider)

1
Adicione uma breve descrição da sua resposta.
Morales Batovski

2

Em Java, você não pode fazer

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

Como foi apontado, você precisaria fazer uma inicialização entre chaves:

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

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

Alternativamente, você pode fazer

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

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

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

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

Mas não consigo compilar com o JDK 1.6.


5
Errado! Você pode fazer a primeira linha, e essa é a resposta certa btw
Bohemian

1
Collections.singletonList(messageBody)

Se você precisa ter uma lista de um item !

Collections é do pacote java.util .


1

A melhor maneira de fazer isso:

package main_package;

import java.util.ArrayList;


public class Stackkkk {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<Object>();
        add(list, "1", "2", "3", "4", "5", "6");
        System.out.println("I added " + list.size() + " element in one line");
    }

    public static void add(ArrayList<Object> list,Object...objects){
        for(Object object:objects)
            list.add(object);
    }
}

Basta criar uma função que possa ter quantos elementos quiser e chamá-la para adicioná-los em uma linha.


1
Se você passar por todos os problemas, poderá torná-lo um método de modelo em vez de usar simples Object.
Robert

1

Aqui está o código de AbacusUtil

// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> 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<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");

Declaração: Sou o desenvolvedor do AbacusUtil.


0

Para mim, o Arrays.asList () é o melhor e mais conveniente. Eu sempre gosto de inicializar dessa maneira. Se você é iniciante em Java Collections, gostaria que você referisse a inicialização ArrayList


Por que Arrays.asList () é melhor do que criar um novo ArrayList em uma linha com add()métodos?
IgorGanapolsky

0

Por que não criar uma função utilitária simples que faça isso?

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

" ll" significa "lista literal".

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

0

Curiosamente, nenhum one-liner com o outro método sobrecarregado Stream::collect está listado

ArrayList<String> places = Stream.of( "Buenos Aires", "Córdoba", "La Plata" ).collect( ArrayList::new, ArrayList::add, ArrayList::addAll );

-1

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

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})

3
Posso perguntar o que isso acrescenta à pergunta? Esta resposta já foi abordada várias vezes por outras respostas.
Mysticial

Esta é realmente uma solução muito ruim, pois cria uma LISTA ABSTRATA. Você não poderá adicionar mais nada ao contêiner.
Atais 23/09/2015
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.