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

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

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

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

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

4b9b3361

Ответ 1

На самом деле, возможно, лучшим способом инициализации 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, у которого есть инициализатор экземпляра, и этот класс создается только для создания одного объекта - это просто похоже на немного переборщить со мной.

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

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

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

Ответ 2

Было бы проще, если бы вы просто объявили его как 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"));

Ответ 3

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

В Java 10, 11, 12 или более поздней версии:

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

В Java 9 или более поздней версии:

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

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


Java 8 или более ранняя версия:

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

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


Вы можете сделать Arrays.asList еще короче с помощью статического импорта:

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

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

import static java.util.Arrays.asList;  

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


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


Использование Stream s

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

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

Вы можете объединить Stream s:

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

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

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

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

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


Если вам действительно нужен java.util.ArrayList

(Вы, вероятно, не.)
Процитирую JEP 269 (выделение мое):

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


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

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

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

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

или используя Stream:

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

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

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


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

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

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

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

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

Например, если вы передаете ArrayList в 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
}

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

Ответ 4

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

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

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

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

Ответ 5

С Guava вы можете написать:

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

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

Ответ 6

Литералы коллекции не попали в Java 8, но можно использовать Stream API для инициализации списка в одной довольно длинной строке:

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

Если вам нужно, чтобы ваш List был ArrayList:

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

Ответ 7

import com.google.common.collect.ImmutableList;

....

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

Ответ 8

В Java 9, как предложено в предложении по усовершенствованию JDK - 269, этого можно достичь, используя теперь литералы коллекций как -

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

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

Также аналогичный подход будет применяться к Map -

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

что аналогично предложению Collection Literals, как заявлено @coobird. Также уточняется в документе JEP -


альтернативы

Языковые изменения были рассмотрены несколько раз и отклонены:

Проект монетного предложения, 29 марта 2009 г.

Проект монетного предложения, 30 марта 2009 г.

JEP 186 дискуссия по лямбда-деву, январь-март 2014

Языковые предложения были отложены в предпочтении перед библиотечным предложением, как показано в этом сообщении.

Related => В чем смысл перегруженных методов фабрики удобства для коллекций в Java 9

Ответ 9

Вы можете создать фабричный метод:

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

Но это не намного лучше, чем ваш первый рефакторинг.

Для большей гибкости он может быть общим:

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

Ответ 10

В Java 9 мы можем легко инициализировать ArrayList в одну строку:

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

или же

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

Этот новый подход Java 9 имеет много преимуществ по сравнению с предыдущими:

  1. Космическая эффективность
  2. неизменность
  3. Поток Сейф

Смотрите этот пост для более подробной информации → В чем разница между List.of и Arrays.asList?

Ответ 11

Просто используйте приведенный ниже код следующим образом.

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

Ответ 12

С Eclipse Collections вы можете написать следующее:

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

Вы также можете более точно указать типы, а также то, являются ли они изменяемыми или неизменяемыми.

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

Вы также можете сделать то же самое с наборами и сумками:

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

Примечание: я являюсь коммиттером для Eclipse Collections.

Ответ 13

О самом компактном способе сделать это:

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

Ответ 14

Вот еще один способ:

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

Ответ 15

(Должен быть комментарий, но слишком длинный, поэтому новый ответ). Как уже упоминалось, метод Arrays.asList имеет фиксированный размер, но это не единственная проблема с ним. Он также не очень хорошо обрабатывает наследование. Например, предположим, у вас есть следующее:

class A{}
class B extends A{}

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

Вышеуказанное приводит к ошибке компилятора, потому что List<B> (то, что возвращает Arrays.asList) не является подклассом List<A>, даже если вы можете добавить объекты типа B в объект List<A>, Чтобы обойти это, вам нужно сделать что-то вроде:

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

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

Ответ 16

Вы можете использовать приведенные ниже инструкции:

Фрагмент кода:

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

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

Ответ 17

Как Том сказал:

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

Но поскольку вы жаловались на желание ArrayList, вы должны сначала знать, что ArrayList является подклассом List, и вы можете просто добавить эту строку:

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

Хотя, это может заставить вас жаловаться на "производительность".

В этом случае для меня это не имеет смысла, почему, поскольку ваш список предопределен, он не был определен как массив (поскольку размер известен во время инициализации). И если это вариант для вас:

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

Если вы не заботитесь о незначительных различиях в производительности, вы можете просто скопировать массив в ArrayList очень просто:

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

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

enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}

станет:

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 имеет статический метод values, который возвращает массив, содержащий все значения перечисления в том порядке, в котором они объявлены, например:

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

В этом случае, я думаю, вам не понадобится ваш ArrayList.

P.S. Randyaa продемонстрировал еще один хороший способ, используя статический метод утилиты Collections.addAll.

Ответ 18

Java 9 имеет следующий способ создания неизменяемого списка:

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

который легко адаптируется для создания изменяемого списка, если требуется:

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

Аналогичные методы доступны для Set и Map.

Ответ 19

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

Ответ 20

Да с помощью массивов вы можете инициализировать список массивов в одной строке,

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

Ответ 21

Вы можете использовать StickyList из Cactoos:

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

Ответ 22

Попробуйте использовать эту строку кода:

Collections.singletonList(provider)

Ответ 23

В Java вы не можете делать

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

Как указывалось, вам нужно выполнить инициализацию с двойной привязкой:

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

Но это может заставить вас добавить аннотацию @SuppressWarnings("serial") или создать серийный UUID, который раздражает. Также большинство форматировщиков кода разворачивают это на несколько операторов/строк.

В качестве альтернативы вы можете сделать

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

но тогда вы можете сделать @SuppressWarnings("unchecked").

Также, согласно javadoc, вы должны это сделать:

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

Но я не могу его скомпилировать с JDK 1.6.

Ответ 24

Collections.singletonList(messageBody)

Если вам нужно будет иметь список одного элемента!

Коллекции из пакета java.util.

Ответ 25

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

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

Просто создайте функцию, которая может иметь столько элементов, сколько вы хотите, и вызовите ее, чтобы добавить их в одну строку.

Ответ 26

Вот код от 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");

Декларация: я разработчик AbacusUtil.

Ответ 27

Иногда я просто чувствую, что люди просто должны использовать Groovy и пусть Java остается в покое. Хорошо, что он работает на JVM, поэтому вы можете скопировать чистый Java-код в любом месте в файле Groovy, и он будет работать.

О объявлении списка в одной строке, вот как он выглядит в Groovy:

def list1 = [1,2,3]

Что это, maan!!!

Ниже приведен список Groovy.

Дополнительно

Объявление карты в Groovy в одной строке:

def map1 = [key1:1,key2:2]

Подробнее о Groovy maps.

Чтение файла JSON,

{ "map1":{"map2":{"key":"value1"}}}

в одной строке:

String value = new JsonSlurper().parse("path\\to\\file")["map1"]["map2"]["key"]

или

String value = new JsonSlurper().parse("path\\to\\file").map1.map2.key

Оба набора value - value1.

Представьте, что вы делаете то же самое с Jackson API. Вы должны написать соответствующие POJOs для map1 и map2. Затем скомпилируйте. Также каждый раз, когда JSON изменяется, вы должны отражать эти изменения в POJO. Это полностью поражает цель создания функциональности JSON. Это смертельная цепочка перекомпиляции кода-кода. Не просто настроить и уйти.

Я плачу, когда меня попросили использовать Java. Почему мир почему???? (или, пожалуйста, просветите меня, если я ошибаюсь... уменьшит большую часть моей боли в Java World)

Ответ 28

Для меня Arrays.asList() - лучший и удобный. Мне всегда нравится инициализировать этот путь. Если вы новичок в сборниках Java, я хотел бы, чтобы вы ссылались на ArrayList инициализацию

Ответ 29

Почему бы не сделать простую служебную функцию, которая делает это?

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

" ll " означает "буквальный список".

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

Ответ 30

Интересно, что в списке нет одной строки с другим перегруженным методом Stream::collect

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