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"));
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.
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.
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
.
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
.
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:
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:
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
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");