Вопрос: Инициализация массива в одной строке


Я хочу создать список вариантов для тестирования. Сначала я сделал это:

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

Затем я реорганизовал код следующим образом:

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

Есть лучший способ сделать это?


2113


источник


Ответы:


На самом деле, возможно, «лучший» способ инициализировать ArrayListэто метод, который вы написали, так как ему не нужно создавать новую Listв любом случае:

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

Уловка состоит в том, что требуется довольно много ввода, чтобы ссылаться на это listпример.

Существуют альтернативы, такие как создание анонимного внутреннего класса с инициализатором экземпляра (также называемым «инициализацией двойной скобки»):

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

Тем не менее, я не слишком люблю этот метод, потому что в итоге вы являетесь подклассом ArrayListкоторый имеет инициализатор экземпляра, и этот класс создается только для создания одного объекта - это просто кажется мне немного лишним.

Было бы хорошо, если бы Предложение коллекции литератур для Монета проекта был принят (он должен был быть представлен на Java 7, но он вряд ли будет частью Java 8.):

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

К сожалению, это вам не поможет, поскольку оно инициализирует неизменяемый Listа не ArrayList, и, кроме того, он пока недоступен, если он когда-либо будет.


1595



Было бы проще, если бы вы просто объявили его как List- Это должен быть ArrayList?

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

Или, если у вас есть только один элемент:

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

Это означало бы, что placesявляется неизменный (попытка изменить это приведет к UnsupportedOperationExceptionисключение, которое нужно выбросить).

Сделать изменчивый список, который является конкретным ArrayListвы можете создать ArrayListиз непреложного списка:

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

1683



Простой ответ

В Java 8 или ранее:

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

Это даст вам Listподдерживаемый массивом, поэтому он не может изменить длину.
Но вы можете позвонить List.set, поэтому он все еще изменчив.


В Java 9:

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

Это даст вам непреложный List, поэтому его нельзя изменить.
Это то, что вы хотите, в большинстве случаев, когда вы его предварительно заполняете.


Более короткий ответ

Ты можешь сделать Arrays.asListдаже короче со статическим импортом:

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

Статический импорт:

import static java.util.Arrays.asList;  

Что любая современная IDE предложит и автоматически сделает для вас.
Например, в IntelliJ IDEA вы нажимаете Alt+Enterи выберите Static import method...,


Однако я не рекомендую сокращать Java 9 List.ofметода, поскольку ofстановится запутанным.
List.ofуже достаточно короткий и хорошо читается.


С помощью Streams

Почему это должно быть List?
С помощью Java 8 или более поздней версии вы можете использовать Streamкоторый является более гибким:

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

Вы можете конкатенировать Streams:

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

Или вы можете перейти от Streamк List:

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

Но предпочтительно, просто используйте Streamне собирая его List,


если ты действительно необходимо java.util.ArrayList

(Вероятно, вы этого не сделаете.)
Цитировать JEP 269 (внимание мое):

Eсть маленький набор вариантов использования для инициализации экземпляра mutable collection с предопределенным набором значений. Обычно предпочтительнее, чтобы эти предопределенные значения находились в неизменяемой коллекции, а затем инициализировали изменчивую коллекцию с помощью конструктора копирования.


Если ты хочешь и то и другое предустановить ArrayList а также добавить к нему впоследствии (почему?), использовать

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

или в Java 9:

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

или использования Stream:

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

Но опять же, лучше просто использовать Streamпрямо, а не собирать его List,


Программа для интерфейсов, а не для реализации

Вы сказали, что объявили список как ArrayListв вашем коде, но вы должны сделать это только в том случае, если вы используете какого-либо члена ArrayListэто не в List,

Скорее всего, вы этого не делаете.

Обычно вам нужно просто объявить переменные самым общим интерфейсом, который вы собираетесь использовать (например, Iterable, Collection, или List) и инициализировать их с помощью конкретной реализации (например, ArrayList, LinkedListили Arrays.asList()).

В противном случае вы ограничиваете свой код этим конкретным типом, и его будет сложнее изменить, когда захотите.

Например:

// Iterable if you just need iteration, for (String s : strings):
Iterable<String> strings = new ArrayList<>();   

// Collection if you also need .size() or .stream():
Collection<String> strings = new ArrayList<>(); 

// List if you also need .get(index):
List<String> strings = new ArrayList<>();       

// Don't declare a specific list implementation
// unless you're sure you need it:
ArrayList<String> strings = new ArrayList<>();  // You don't need ArrayList

Другим примером может быть объявление переменной InputStreamхотя обычно это FileInputStreamили BufferedInputStream, потому что однажды вы или кто-то еще захотите использовать какой-либо другой вид InputStream,


567



Если вам нужен простой список размером 1:

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

Если вам нужен список из нескольких объектов:

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

99



With Guava you can write:

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

In Guava there are also other useful static constructors. You can read about them here.


51



Collection literals didn't make it into Java 8, but it is possible to use the Stream API to initialize a list in one rather long line:

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

If you need to ensure that your List is an ArrayList:

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

31



import com.google.common.collect.ImmutableList;

....

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

25



You could create a factory method:

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

But it's not much better than your first refactoring.

For greater flexibility, it can be generic:

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

20



With Java 9, as suggested in JDK Enhancement Proposal - 269, this could be achieved using collection literals now as -

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

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

Also a similar approach would apply to Map as well -

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

which is similar to Collection Literals proposal as stated by @coobird as well. Further clarified in the JEP doc as well -


Alternatives

Language changes have been considered several times, and rejected:

Project Coin Proposal, 29 March 2009

Project Coin Proposal, 30 March 2009

JEP 186 discussion on lambda-dev, January-March 2014

The language proposals were set aside in preference to a library-based proposal as summarized in this message.

Chained read about the same ~> What is the point of overloaded Convenience Factory Methods


16



In Java 9 we can easily initialize an ArrayList in a single line:

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

or

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

This new approach of Java 9 has many advantages over the previous ones:

  1. Space Efficiency
  2. Immutability
  3. Thread Safe

See this post for more details -> What is the difference between List.of and Arrays.asList?


10



About the most compact way to do this is:

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

6



With Eclipse Collections (formerly GS Collections), you can write the following:

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

You can also be more specific about the types and whether they are Mutable or Immutable.

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

You can also do the same with Sets and Bags:

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

Note: I am a committer for Eclipse Collections.


6