Создать ArrayList из массива - PullRequest
       287

Создать ArrayList из массива

3295 голосов
/ 01 октября 2008

У меня есть массив, который инициализируется как:

Element[] array = {new Element(1), new Element(2), new Element(3)};

Я хотел бы преобразовать этот массив в объект класса ArrayList.

ArrayList<Element> arraylist = ???;

Ответы [ 32 ]

4299 голосов
/ 01 октября 2008
new ArrayList<>(Arrays.asList(array))
840 голосов
/ 01 октября 2008

Дано:

Element[] array = new Element[] { new Element(1), new Element(2), new Element(3) };

Самый простой ответ:

List<Element> list = Arrays.asList(array);

Это будет хорошо работать. Но некоторые предостережения:

  1. Список, возвращаемый из asList, имеет фиксированный размер . Итак, если вы хотите иметь возможность добавлять или удалять элементы из возвращенного списка в вашем коде, вам нужно обернуть его в новый ArrayList. В противном случае вы получите UnsupportedOperationException.
  2. Список, возвращаемый из asList(), поддерживается исходным массивом. Если вы измените исходный массив, список также будет изменен. Это может быть удивительно.
320 голосов
/ 16 ноября 2012

(старая тема, но всего 2 цента, так как никто не упоминает Guava или другие библиотеки и некоторые другие детали)

Если можете, используйте гуаву

Стоит указать путь гуавы, который значительно упрощает эти махинации:

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

Для неизменного списка

Используйте класс ImmutableList и его of() и copyOf() фабричные методы (элементы не могут быть нулевыми)

List<String> il = ImmutableList.of("string", "elements");  // from varargs
List<String> il = ImmutableList.copyOf(aStringArray);      // from array

Для изменяемого списка

Используйте класс Lists и его newArrayList() фабричные методы:

List<String> l1 = Lists.newArrayList(anotherListOrCollection);    // from collection
List<String> l2 = Lists.newArrayList(aStringArray);               // from array
List<String> l3 = Lists.newArrayList("or", "string", "elements"); // from varargs

Также обратите внимание на аналогичные методы для других структур данных в других классах, например, в Sets.

Почему гуава?

Основная привлекательность может заключаться в уменьшении беспорядка из-за обобщений для безопасности типов, так как использование фабричных методов Guava позволяет выводить типы в большинстве случаев. Однако этот аргумент содержит меньше воды, так как Java 7 появилась с новым оператором diamond.

Но это не единственная причина (и Java 7 еще не везде): сокращенный синтаксис также очень удобен, а инициализаторы методов, как видно выше, позволяют писать более выразительный код. Вы делаете в одном вызове Guava то, что занимает 2 с текущими коллекциями Java.


Если не умеешь ...

Для неизменного списка

Используйте класс JDK Arrays и его asList() фабричный метод, завернутый в Collections.unmodifiableList():

List<String> l1 = Collections.unmodifiableList(Arrays.asList(anArrayOfElements));
List<String> l2 = Collections.unmodifiableList(Arrays.asList("element1", "element2"));

Обратите внимание, что возвращаемый тип для asList() - это List, использующий конкретную ArrayList реализацию, но это НЕ java.util.ArrayList. Это внутренний тип, который эмулирует ArrayList, но на самом деле напрямую ссылается на переданный массив и делает его «записывающим» (изменения отражаются в массиве).

Он запрещает модификации через некоторые из методов List API путем простого расширения AbstractList (поэтому добавление или удаление элементов не поддерживается), однако он позволяет вызовам set() переопределять элементы. Таким образом, этот список не является действительно неизменным, и вызов asList() должен быть заключен в Collections.unmodifiableList().

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

Для изменяемого списка

То же, что и выше, но завернуто с фактическим java.util.ArrayList:

List<String> l1  = new ArrayList<String>(Arrays.asList(array));    // Java 1.5 to 1.6
List<String> l1b = new ArrayList<>(Arrays.asList(array));          // Java 1.7+
List<String> l2  = new ArrayList<String>(Arrays.asList("a", "b")); // Java 1.5 to 1.6
List<String> l2b = new ArrayList<>(Arrays.asList("a", "b"));       // Java 1.7+

Для образовательных целей: Хороший старый ручной путь

// for Java 1.5+
static <T> List<T> arrayToList(final T[] array) {
  final List<T> l = new ArrayList<T>(array.length);

  for (final T s : array) {
    l.add(s);
  }
  return (l);
}

// for Java < 1.5 (no generics, no compile-time type-safety, boo!)
static List arrayToList(final Object[] array) {
  final List l = new ArrayList(array.length);

  for (int i = 0; i < array.length; i++) {
    l.add(array[i]);
  }
  return (l);
}
212 голосов
/ 22 июня 2011

Поскольку этот вопрос довольно старый, меня удивляет, что никто еще не предложил простейшую форму:

List<Element> arraylist = Arrays.asList(new Element(1), new Element(2), new Element(3));

Начиная с Java 5, Arrays.asList() принимает параметр varargs, и вам не нужно явно создавать массив.

185 голосов
/ 01 октября 2008
new ArrayList<T>(Arrays.asList(myArray));

Убедитесь, что myArray соответствует типу T. Вы получите ошибку компилятора, если попытаетесь создать List<Integer> из массива int, например.

86 голосов
/ 04 апреля 2012

Другой способ (хотя по существу эквивалентный new ArrayList(Arrays.asList(array)) решению с точки зрения производительности:

Collections.addAll(arraylist, array);
74 голосов
/ 17 апреля 2016

Java 9

В Java 9 вы можете использовать List.of статический фабричный метод для создания литерала List. Примерно так:

List<Element> elements = List.of(new Element(1), new Element(2), new Element(3));

Это вернет неизменный список, содержащий три элемента. Если вам нужен список mutable , передайте этот список конструктору ArrayList:

new ArrayList<>(List.of(// elements vararg))

JEP 269: методы фабрики удобства для коллекций

JEP 269 предоставляет некоторые удобные фабричные методы для Java Collections API. Эти неизменяемые статические фабричные методы встроены в интерфейсы List, Set и Map в Java 9 и более поздних версиях.

67 голосов
/ 01 октября 2008

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

List<Element> arraylist = Arrays.asList(array);
58 голосов
/ 25 ноября 2014

Еще одно обновление, почти заканчивающееся в 2014 году, вы можете сделать это и с Java 8:

ArrayList<Element> arrayList = Stream.of(myArray).collect(Collectors.toCollection(ArrayList::new));

Несколько символов будут сохранены, если это может быть просто List

List<Element> list = Stream.of(myArray).collect(Collectors.toList());
32 голосов
/ 18 января 2014

Если вы используете:

new ArrayList<T>(Arrays.asList(myArray));

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

К счастью, реализация JDK быстра и Arrays.asList(a[]) очень хорошо сделана. Он создает вид ArrayList с именем Arrays.ArrayList, где данные Object [] указывают непосредственно на массив.

// in Arrays
@SafeVarargs
public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}
//still in Arrays, creating a private unseen class
private static class ArrayList<E>

    private final E[] a;    
    ArrayList(E[] array) {
        a = array; // you point to the previous array
    }
    ....
}

Опасная сторона в том, что если вы измените исходный массив, вы измените список! Вы уверены, что хотите этого? Может да, а может и нет.

Если нет, то самый понятный способ сделать это:

ArrayList<Element> list = new ArrayList<Element>(myArray.length); // you know the initial capacity
for (Element element : myArray) {
    list.add(element);
}

Или, как сказал @glglgl, вы можете создать еще один независимый ArrayList с помощью:

new ArrayList<T>(Arrays.asList(myArray));

Я люблю использовать Collections, Arrays или Гуаву. Но если он не подходит или вы его не чувствуете, просто напишите еще одну не элегантную строку.

...