从数组创建 ArrayList

我有一个像这样初始化的数组:

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

我想将此数组转换为 ArrayList 类的对象。

ArrayList<Element> arraylist = ???;

答案

new ArrayList<>(Arrays.asList(array))

鉴于:

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()返回的列表由原始数组支持。如果您修改原始数组,则列表也会被修改。这可能令人惊讶。

(旧线程,但只有 2 美分,因为没有人提到 Guava 或其他库以及其他一些细节)

如果可以,请使用番石榴

值得指出的是番石榴的方法,它大大简化了这些恶作剧:

用法

对于不可变的清单

使用ImmutableList类及其of()copyOf()工厂方法(元素不能为 null)

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其他数据结构的类似方法。

为什么是番石榴?

主要的吸引力可能是减少由于类型安全的泛型而造成的混乱,因为使用番石榴工厂方法可以在大多数时间推断类型。但是,自从 Java 7 随新的 Diamond 运算符一起发布以来,这种争论就少了。

但这不是唯一的原因(并且 Java 7 尚无处不在):速记语法也非常方便,并且如上所述的方法初始化器允许编写更具表现力的代码。您只需执行一次 Guava 调用即可完成当前 Java 集合需要 2 项操作。


如果你不能...

对于不可变的清单

使用 JDK 的Arrays类及其asList()工厂方法,并用Collections.unmodifiableList()包装:

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

请注意,返回的asList()类型是使用具体ArrayList实现的List ,但不是 java.util.ArrayList 。这是一个内部类型,它模拟ArrayList但实际上直接引用传递的数组并使它 “直写”(修改反映在数组中)。

它禁止通过简单扩展AbstractList的方式通过某些List API 的方法进行修改(因此,不支持添加或删除元素),但是它允许调用set()来覆盖元素。因此,此列表并不是真正不变的,应使用Collections.unmodifiableList()包装对asList()的调用。

如果需要可变列表,请参见下一步。

对于可变列表

与上述相同,但使用实际的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);
}

由于这个问题已经很老了,令我惊讶的是,没有人提出最简单的形式:

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

从 Java 5 开始, Arrays.asList()带有 varargs 参数,您不必显式构造数组。

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

确保myArrayT是相同的类型。例如,如果尝试从int数组创建List<Integer> ,则会出现编译器错误。

性能方面的另一种方法(尽管本质上等效于new ArrayList(Arrays.asList(array))

Collections.addAll(arraylist, array);

Java 9

Java 9 中 ,可以使用List.of静态工厂方法来创建List文字。类似于以下内容:

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

这将返回一个包含三个元素的不可变列表。如果您想要一个可变列表,则将该列表传递给ArrayList构造函数:

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

JEP 269:收集的便利工厂方法

JEP 269Java Collections API 提供了一些便利的工厂方法。这些不可变的静态工厂方法内置在 Java 9 及更高版本的ListSetMap接口中。

您可能只需要一个列表,而不是一个 ArrayList。在这种情况下,您可以执行以下操作:

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

另一个更新即将于 2014 年结束,您也可以使用 Java 8 进行更新:

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

如果这只是一个List ,将保存一些字符

List<Element> list = Stream.of(myArray).collect(Collectors.toList());

如果您使用:

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

可以创建并填写两个列表!填充两次大列表确实是您不希望执行的操作,因为每次需要扩展容量时,它都会创建另一个Object[]数组。

幸运的是,JDK 实现非常快,并且Arrays.asList(a[])做得很好。它创建了一种名为 Arrays.ArrayList 的 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
    }
    ....
}

危险的一面是, 如果更改初始数组,则更改 List!您确定要吗?可能是可能不是。

如果没有,最容易理解的方法是这样做:

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

我喜欢使用CollectionsArrays或 Guava。但是,如果不合适,或者您感觉不到,只需编写另一条不雅观的行即可。