Java ArrayList и HashMap на лету

Может ли кто-нибудь привести пример создания Java ArrayList и HashMap на лету? Итак, вместо того, чтобы выполнять add() или put(), фактически предоставлять начальные данные для массива/хэша при создании экземпляра класса?

Чтобы привести пример, что-то похожее на PHP, например:

$array = array (3, 1, 2);
$assoc_array = array( 'key' => 'value' );

person Steve M    schedule 12.05.2009    source источник
comment
Вы просите синтаксис того, как это сделать, или реальный пример того, почему вы хотели бы этого?   -  person Bill the Lizard    schedule 12.05.2009


Ответы (8)


Хороший способ сделать это — использовать List.of() и Map.of() (начиная с Java 8):

List<String> list = List.of("A", "B", "C");
    
Map<Integer, String> map = Map.of(1, "A",
                                  2, "B",
                                  3, "C");

Java 7 и более ранние версии могут использовать Коллекции Google:

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

Map<Integer, String> map = ImmutableMap.of(
  1, "A",
  2, "B",
  3, "C");
person Steve McLeod    schedule 12.05.2009
comment
500 КБ — это высокая цена, которую нужно заплатить только за это. Если единственное, что нужно, - это заполнить Коллекцию на лету, принятый ответ будет ИМХО самым приятным. - person Damien B; 12.05.2009
comment
Еще одна причина не любить этот подход заключается в том, что это неизменяемый список, хотя я предполагаю (не читая документацию), что существует изменяемый список? - person cgp; 12.05.2009
comment
Это неизменно по замыслу! Но да, есть и другие варианты. Если он неизменяем, вы можете легко разделить один экземпляр между потоками и, следовательно, между веб-запросами. 500 Кб — это высокая цена. Но в Google Collections так много других вкусностей, что за это стоит заплатить. - person Steve McLeod; 12.05.2009
comment
@Damien- Достаточно справедливо, но ничто не мешает пользователям написать свою собственную версию этого метода. - person Philip Guin; 14.12.2012
comment
Map.of — это функция Java 9, а не 8! - person vahid kh; 20.06.2021

Массивы можно преобразовать в Lists:

List<String> al = Arrays.asList("vote", "for", "me"); //pandering

Обратите внимание, что это не возвращает не ArrayList, а произвольный экземпляр List (в данном случае это Array.ArrayList)!

Подход Бруно работает лучше всего и может быть рассмотрен на лету для карт. Я предпочитаю другой метод для списков (см. выше):

Map<String,String> map = new HashMap<String,String>() {
 {
    put("key1", "value1");
    put("key2", "value2");
 }
};
person cgp    schedule 12.05.2009
comment
имейте в виду, что Arrays.asList возвращает не java.util.ArrayList, а java.util.Arrays$ArrayList фиксированного размера! - person user85421; 12.05.2009

для коротких списков:

    List<String> ab = Arrays.asList("a","b");
person Andreas Petersson    schedule 12.05.2009
comment
не совсем .. из java.util.Arrays.java: public static ‹T› List‹T› asList(T... a) { return new ArrayList‹T›(a); } поэтому он просто возвращает предварительно инициализированный ArrayList - person Andreas Petersson; 12.05.2009
comment
Смотрите дальше в источнике. Массивы имеют собственный внутренний класс ArrayList, который не поддерживает add() или remove(). - person Michael Myers; 12.05.2009
comment
и из документации asList: возвращает список фиксированного размера, поддерживаемый указанным массивом. - person user85421; 12.05.2009

Используйте хороший анонимный инициализатор:

List<String> list = new ArrayList<String>() {{
    add("a");
    add("b");
}};

То же самое касается карты:

Map<String, String> map = new HashMap<String, String>() {{
    put("a", "a");
    put("b", "b");
}};

Я нахожу это самым элегантным и читаемым.

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

person Yuval Adam    schedule 12.05.2009

Для списков вы можете использовать Arrays.asList следующим образом:

List<String> stringList = Arrays.asList("one", "two");
List<Integer> intList = Arrays.asList(1, 2);

Для Карт вы можете использовать это:

public static <K, V> Map<K, V> mapOf(Object... keyValues) {
    Map<K, V> map = new HashMap<>();

    K key = null;
    for (int index = 0; index < keyValues.length; index++) {
        if (index % 2 == 0) {
            key = (K)keyValues[index];
        }
        else {
            map.put(key, (V)keyValues[index]);
        }
    }

    return map;
}

Map<Integer, String> map1 = mapOf(1, "value1", 2, "value2");
Map<String, String> map2 = mapOf("key1", "value1", "key2", "value2");

Примечание: в Java 9 вы можете использовать Map.of
Примечание 2: Double Brace Initialization для создания HashMaps, как это предлагается в других ответах, имеет предостережения

person R. Oosterholt    schedule 23.05.2017

Вы имеете в виду вот так?

public List<String> buildList(String first, String second)
{
     List<String> ret = new ArrayList<String>();
     ret.add(first);
     ret.add(second);
     return ret;
}

...

List<String> names = buildList("Jon", "Marc");

Или вас интересует конструктор ArrayList, который принимает Collection<? extends E>? Например:

String[] items = new String[] { "First", "Second", "Third" };
// Here's one way of creating a List...
Collection<String> itemCollection = Arrays.asList(items);
// And here's another
ArrayList<String> itemList = new ArrayList<String>(itemCollection);
person Jon Skeet    schedule 12.05.2009
comment
Небольшое улучшение предложения Джона: работает для любого количества элементов: public List‹String› buildList(String... items) { return new ArrayList‹String›(Arrays.asList(items)); } - person Steve McLeod; 12.05.2009
comment
(Код примера можно немного упростить, используя varags Arrays.asList(); stackoverflow.com/questions/258954/) - person Jonik; 12.05.2009
comment
Я показывал отдельные шаги, чтобы было понятно, как что-то делать, когда у вас уже есть массив. - person Jon Skeet; 12.05.2009
comment
Почему бы не использовать var-args, чтобы вы могли передавать любое количество элементов? - person sal; 12.05.2009

Как насчет этого?

ArrayList<String> array = new ArrayList<String>(Arrays.asList("value1", "value2"));

Я знаю, что многие ответы давали аналогичные решения, но я думаю, что этот ответ немного точнее и лаконичнее. Если у вас много значений, вы можете сделать это:

ArrayList<String> array = new ArrayList<String>(Arrays.asList(
    "value1",
    "value2",
    "value3",
    ...
));
person ahmadPH    schedule 01.04.2021

person    schedule
comment
Эти подходы хороши. Но содержимое может быть изменено после создания. Неизменяемые подходы — это оооочень приятно! - person Steve McLeod; 12.05.2009
comment
это иногда опасно. вы получите ссылку на окружающий класс, поскольку анонимный внутренний класс поддерживает ссылку на свой родительский объект. это может вызвать проблемы со сборкой мусора и сериализацией. - person Andreas Petersson; 12.05.2009
comment
Мне вообще не нравится инициализация с двойными скобками. Зачем создавать новый (нестатический) внутренний класс, если подойдет и простой инициализатор? - person Michael Myers; 12.05.2009
comment
Я всегда думал, что подход с двойной скобкой был хорош (особенно для построения графического интерфейса), но комментарий к ссылке на родительский объект сделан очень хорошо. Здесь действуйте осторожно. Возможно, было бы лучше создать небольшой класс построителя карт, который принимает vararg объектов (ключ, значение, значение ключа и т. д.). - person Kevin Day; 13.05.2009
comment
Есть ли проблемы с производительностью? Я имею в виду, что вы каждый раз создаете анонимный класс, расширяющий ArrayList. Если вы создадите экземпляр массива, а затем добавите в него элементы, подумайте, что это будет более круто для производительности. Или эти классы появляются после компиляции? - person degr; 09.07.2015
comment
Если вы создадите его таким образом, его больше нельзя будет сериализовать! - person clankill3r; 11.08.2015