Pergunta

Eu quero criar uma lista de opções para fins de teste. No início, eu fiz isso:

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

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

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

Existe uma maneira melhor de fazer isso?

Foi útil?

Solução

Na verdade, provavelmente o "melhor" maneira de inicializar o ArrayList é o método que você escreveu, como ele não precisa criar um novo List de qualquer maneira:

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

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

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

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

No entanto, eu não gosto muito desse método, porque o que você acaba com é uma subclasse de ArrayList que tem um inicializador de instância, e que classe é criada apenas para criar um objeto - que só parece um pouco exagero para mim.

O que teria sido bom era se os Coleção literais proposta Projeto Coin foi aceito (foi programado para ser introduzido no Java 7, mas não é provável que seja parte do Java 8 quer):.

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

Infelizmente não vai ajudá-lo aqui, uma vez que irá inicializar um List imutáveis ??em vez de um ArrayList e, além disso, ele não está disponível ainda, se ele nunca será.

Outras dicas

Seria mais simples se você fosse apenas declará-lo como um List -? Que tem que 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");

Isto significaria que places é imutável (tentar mudá-lo fará com que uma exceção UnsupportedOperationException para ser jogado).

Para fazer uma lista mutável que é um ArrayList concreto você pode criar um ArrayList da lista imutável:

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

A resposta simples

Em Java 10, 11, 12, ou mais tarde:

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

Em Java 9 ou posterior:

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

Isto lhe dará uma List imutável, por isso não pode ser mudado.
Que é o que você quer na maioria dos casos em que você está prepopulating-lo.


Java 8 ou anterior:

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

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


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

List<String> 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ê pressionar Alt+Enter e selecione Static import method....


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


Usando Streams

Por que tem que ser um List
Com Java 8 ou mais tarde você pode usar um Stream que é 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 um Stream a um 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 Stream sem recolher-lo para um List.


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

(Você provavelmente não.)
(Grifo meu) para citação PEC 269 :

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 estar em uma coleção imutável, e depois para inicializar a coleção mutável através de um construtor de cópia.


Se você quiser ambos preencher previamente um ArrayList e adicionar a ele posteriormente (por quê?), Uso

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

ou em 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 apenas o Stream diretamente em vez de coletá-la a um List.


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

Você disse que você declarou a lista como um ArrayList em seu código, mas você só deve fazer isso se você estiver usando algum membro da ArrayList que não está em 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 usar (por exemplo Iterable, Collection, ou List), e inicialize-los com a aplicação específica (por exemplo ArrayList, LinkedList ou Arrays.asList()).

Caso contrário, você está limitando seu código para esse tipo específico, e ele vai ser mais difícil de mudar quando você quiser.

Por exemplo, se você estiver passando um ArrayList a 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 uma variável de InputStream embora seja geralmente um FileInputStream ou um BufferedInputStream, porque um dia, em breve você ou alguém vai querer usar algum outro tipo de InputStream.

Se precisar de uma lista simples de tamanho 1:

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

Se precisar de uma lista de vários objetos:

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

Com Goiaba você pode escrever:

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

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

literais Coleção não fazê-lo em 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 o seu List é um ArrayList:

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

....

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

Com Java 9, como sugerido na JDK Enhancement Proposal - 269 , isso poderia ser conseguido usando literais coleção agora como -

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

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

Também uma abordagem semelhante se aplica a Map bem -

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

que é semelhante ao proposta Coleção literais como afirma @coobird também. Clarificado no doc JEP, bem como -


Alternativas

Alterações na Linguagem foram consideradas várias vezes, e rejeitada:

Projeto Coin Proposta, 29 de março de 2009

Projeto Coin Proposta, 30 de março de 2009

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

A linguagem propostas foram postos de lado em detrimento de uma proposta baseada na biblioteca como resumida nesta mensagem.

Related => Qual é o ponto de métodos de fábrica de conveniência sobrecarregados das coletas em Java 9

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 o seu primeiro refatoração.

Para uma 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;
}

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

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

ou

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

Esta nova abordagem de Java 9 tem muitas vantagens sobre os anteriores:

  1. Eficiência espaço
  2. imutabilidade
  3. thread-safe

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

Com Eclipse coleções 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:. Eu sou um committer para Eclipse coleções

Sobre a forma mais compacta de fazer isso é:

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

Aqui é uma outra maneira:

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

Basta usar o código abaixo como segue.

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

Você pode usar o abaixo instruções:

trecho de código:

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

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

(Deve ser um comentário, mas muito longo, tão nova resposta). Como já foi mencionado, o método Arrays.asList é tamanho fixo, mas isso não é o único problema com ele. Ele também não lidar com a herança muito bem. Por exemplo, suponha que você tenha o seguinte:

class A{}
class B extends A{}

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

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

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

Esta é provavelmente a melhor maneira de ir sobre como fazer isso, esp. se você precisar de uma lista ilimitada ou necessidade de herança uso.

Como Tom disse :

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

Mas desde que você queixou-se de querer um ArrayList, você deve primeiramente saber que ArrayList é uma subclasse da lista e você poderia simplesmente adicionar esta linha:

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

Embora, isso pode fazer com que você se queixam de 'performance'.

Nesse caso, não faz sentido para mim, por isso, uma vez que a sua lista é predefinido não foi definido como um array (uma vez que o tamanho é conhecido em tempo de inicialização). E se isso é uma opção para você:

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

No caso de você não se importa das diferenças de desempenho menor, então você também pode copiar um array para um ArrayList de maneira muito simples:

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

Tudo bem, mas, no futuro, você precisa de um pouco mais do que apenas o nome do lugar, você precisa de um código de país também. Assumindo que esta é ainda uma lista predefinida que nunca vai mudar durante o tempo de execução, então é justo usar um conjunto enum, o que exigiria re-compilação se a lista precisava ser mudado 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 de ter um método values estática que retorna um array contendo todos os valores da enumeração na ordem em que são declaradas, por exemplo:.

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

Nesse caso, eu acho que você não iria precisar do seu ArrayList.

P.S. Randyaa demonstrado outra maneira agradável usando o método utilitário estático Collections.addAll .

Java 9 tem o seguinte método para criar um imutável lista:

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 similares estão disponíveis para Set e Map.

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

Você pode usar StickyList de Cactoos :

List<String> 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 lista de matriz em uma linha,

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

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ê precisa fazer uma inicialização dupla cinta:

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

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

Como alternativa, você pode fazer

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

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

Ainda de acordo com javadoc você deve ser capaz de fazer isso:

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

Mas eu não sou capaz de obtê-lo para compilar com JDK 1.6.

Collections.singletonList(messageBody)

Se você precisa ter uma lista de um item !

Collections é de java.util pacote.

A melhor maneira de fazê-lo:

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);
    }
}

Apenas criar uma função que pode ter tantos elementos como você quer e chamá-lo para adicioná-los em uma linha.

Aqui está o código por 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: Eu sou o desenvolvedor AbacusUtil

.

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

Por que não fazer uma função de utilidade simples que faz 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");

Estou criando uma lista de messageTemplate de um arquivo XML armazenados em caminho antes no contexto estático

public final class TemplateStore {

    private TemplateStore(){}

    private static final String [] VERSIONS = {"081"};
    private static final String TEMPLATE_FILE_MASK = "template/EdiTemplates_v%s.xml";
    private static final String ERROR = "Error In Building Edifact Message Template Store";

    public static final List<MessageTemplate> TEMPLATE_LIST = Arrays.stream(VERSIONS)
            .map(version -> TemplateStore.class
                    .getClassLoader().getResourceAsStream(String.format(TEMPLATE_FILE_MASK, version)))
            .map(inputStream -> {
                try {
                    return ((EdiTemplates) JAXBContext.newInstance(EdiTemplates.class).createUnmarshaller()
                            .unmarshal(inputStream)).getMessageTemplate();
                } catch (JAXBException e) {
                    throw new IllegalArgumentException(ERROR, e);
                }})
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
}

Na verdade, é possível fazê-lo em uma linha:

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top