从数组创建ArrayList


3595

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

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

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

ArrayList<Element> arraylist = ???;

49
在Java9中-> List <String> list = List.of(“ Hello”,“ World”,“ from”,“ Java”);
MarekM'17年

18
@MarekM这个答案是错误的,因为它不会返回ArrayList。海报专门要求这一点。
多里安·格雷

4
我认为他没有使用List接口进行挖掘,因为这是最佳实践。但是,如果您想在这里-new ArrayList <>(List.of(“ Hello”,“ World”,“ from”,“ Java”)));
MarekM

10
关键不是使用接口,而是解决方案中返回的列表不可修改。那可能更多是一个问题,也是他要求ArrayList的原因
Dorian Gray

Answers:


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

361
是的 而且,在(最常见的)情况下,您只需要一个列表,该new ArrayList调用也是不必要的。
Calum

143
@Luron-仅使用List<ClassName> list = Arrays.asList(array)

247
@Calum和@Pool-正如下面在Alex Miller的答案中指出的那样,使用Arrays.asList(array)而不将其传递到新ArrayList对象中将固定列表的大小。使用an的更常见原因之一ArrayList是能够动态更改其大小,您的建议将阻止这种情况。
赛马会

130
Arrays.asList()是一个可怕的函数,永远不要照原样使用它的返回值。它破坏了列表模板,因此即使看起来确实多余,也请始终按此处指示的形式使用它。好答案。
亚当

83
@Adam请研究java.util.List的javadoc。添加协议允许他们抛出UnsupportedOperationException。docs.oracle.com/javase/7/docs/api/java/util/… 诚然,从面向对象的角度来看,要使用集合必须多次了解具体实现并不是一件好事-这为了使框架简单,这是一个务实的设计选择。
lbalazscs

918

鉴于:

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

最简单的答案是:

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

这样就可以了。但有一些警告:

  1. 从asList返回的列表具有固定大小。因此,如果您希望能够在代码的返回列表中添加或删除元素,则需要将其包装在new中ArrayList。否则你会得到一个UnsupportedOperationException
  2. 返回的列表asList()由原始数组支持。如果您修改原始数组,则列表也会被修改。这可能令人惊讶。

6
两种操作的时间复杂度是多少?我的意思是使用和不使用显式arraylist构造。
2012年

35
Arrays.asList()仅通过包装现有数组来创建ArrayList,因此它为O(1)。
亚历克斯·米勒

27
包装在新的ArrayList()中将导致迭代固定大小列表的所有元素并将其添加到新的ArrayList中,因此O(n)也是如此。
亚历克斯·米勒

8
asList()返回的List的实现未实现List的几种方法(如add(),remove(),clear()等),这些方法解释了UnsupportedOperationException。绝对是一个警告……
sethro 2012年

8
当问题要求“ ArrayList类的对象”时,我认为假定它引用的类是合理的java.util.ArrayList。Arrays.asList实际上返回的java.util.Arrays.ArrayList不是instanceof另一个类。因此,第三点警告是,如果您尝试在需要上述条件的环境中使用它,则将无法使用。
Dave L.

352

(旧线程,但只有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

为什么是番石榴?

主要的吸引力可能是减少由于类型安全的泛型而造成的混乱,因为使用番石榴工厂方法可以在大多数时间推断类型。但是,自从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"));

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

它禁止通过List简单扩展API AbstractList(因此不支持添加或删除元素)来通过某些API方法进行修改,但是它允许调用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);
}

27
+1但是请注意,return Listby Arrays.asList是可变的,因为您仍然可以设置set元素-只是无法调整大小。对于没有番石榴的不可变列表,您可能会提到Collections.unmodifiableList
Paul Bellora

1
@haylem在您的“ 用于教育目的:手动方法”部分中,您arrayToList的Java 1.5+版本不正确。您正在实例化的列表String,并尝试从给定数组中检索字符串,而不是使用通用参数类型T。除此之外,答案不错,而+1是包括手动方式在内的唯一答案。
afsantos

Id'将您的“如果无法... /对于不可变列表”部分重命名为“对于不可修改列表”,因为以后对包装的数组所做的更改可能会使它突变。它仍然存在O(1),但是为了保持不变,您必须进行复制,例如by Collections.unmodifiableList(new ArrayList<>(Arrays.asList(array)))
maaartinus

232

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

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

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


7
特别是List<String> a = Arrays.asList("first","second","third")
18446744073709551615 '16

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

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


103

另一种方式(尽管本质上等同于new ArrayList(Arrays.asList(array))解决方案的性能方面:

Collections.addAll(arraylist, array);

96

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 提供了一些便利的工厂方法。这些一成不变的静态工厂方法被内置到ListSetMapJava中9以及更高的接口。


List.of()将不会按照原始问题的要求返回java.util.ArrayList的实例。因此,仅第二个选项是有效答案。
tquadrat

84

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

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

8
那将得到原始输入数组的支持,这就是为什么(可能)想要将其包装在新的ArrayList中的原因。
比尔蜥蜴

16
请谨慎使用此解决方案。如果您看,Array ISN不会返回真实的java.util.ArrayList。它返回一个实现所需方法的内部类,但是您不能更改列表中的成员。它只是数组的包装。
Mikezx6r

1
您可以将List <Element>项目转换为ArrayList <Element>
monksy

12
@ Mikezx6r:稍作修正:这是一个固定大小的列表。您可以更改列表的元素(set方法),不能更改列表的大小(不是addremove元素)!
user85421 2009年

1
是的,请注意,这取决于您要对列表执行的操作。值得一提的是,如果OP仅想遍历元素,则根本不需要转换数组。
PaulMurrayCbr

69

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

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

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

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

8
最好不要依赖于实现,但Collectors.toList()实际上会返回ArrayList
bcsb1001 2014年

不正确使用Stream.of(...); 这将创建一个元素流。请改用Arrays.stream
Patrick Parker

我不认为这两个选项是有效的,但Arrays.stream稍好一点,因为您可以使用带有“ start”,“ end” args的重载方法以固定大小创建它。另请参见:stackoverflow.com/a/27888447/2619091
whyem '16

41

如果您使用:

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或番石榴。但是,如果不合适,或者您感觉不到,只需编写另一条不雅观的行即可。


1
我看不到答案结尾处的循环与new ArrayList<T>(Arrays.asList(myArray));不鼓励使用的部分之间的根本区别。两者的功能完全相同,复杂度也相同。
glglgl 2015年

Collections在数组的开头创建一个指针。我的循环创建了许多指针:每个数组成员一个。因此,如果原始数组发生变化,则我的观点仍然会朝着先前的价值观发展。
Nicolas Zozol

1
new ArrayList<T>(Arrays.asList(myArray));做同样的事情,它将复制asListArrayList...
glglgl 2015年

37

Java 9您可以使用:

List<String> list = List.of("Hello", "World", "from", "Java");
List<Integer> list = List.of(1, 2, 3, 4, 5);

请注意,这不是明确要求的ArrayList。
多里安·格雷

33

根据问题,使用Java 1.7的答案是:

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

但是最好总是使用以下接口:

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

30
// Guava
import com.google.common.collect.ListsLists
...
List<String> list = Lists.newArrayList(aStringArray); 


21

正如所有人所说的那样

 new ArrayList<>(Arrays.asList("1","2","3","4"));

创建数组的最常见的最新方法是observableArrays

ObservableList:一个列表,允许侦听器跟踪发生的更改。

对于Java SE,您可以尝试

FXCollections.observableArrayList(new Element(1), new Element(2), new Element(3));

根据Oracle Docs

observableArrayList()创建一个新的空可观察列表,该列表由arraylist支持。observableArrayList(E ... items)创建一个带有可添加项的新可观察数组列表。

更新Java 9

在Java 9中也很容易:

List<String> list = List.of("element 1", "element 2", "element 3");


18

您也可以使用Java 8中的流来实现。

 List<Element> elements = Arrays.stream(array).collect(Collectors.toList()); 

3
Java 8开始Collectors.toList()将返回ArrayList。但是,这在Java的未来版本中可能会有所不同。如果您想要特定的集合类型,请Collectors.toCollection()改用在哪里可以指定要创建的确切集合类型。
Raja Anbazhagan

14
  1. 如果我们看到Arrays.asList()方法的定义,您将得到以下内容:

     public static <T> List<T> asList(T... a) //varargs are of T type. 

    因此,您可以这样初始化arraylist

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

    注意:每个都new Element(int args)将被视为“单个对象”,并且可以作为传递var-args

  2. 这个问题可能还会有另一个答案。
    如果看到java.util.Collections.addAll()方法的声明,您将得到以下内容:

    public static <T> boolean addAll(Collection<? super T> c, T... a);

    因此,此代码也很有用

    Collections.addAll(arraylist, array);

10

另一种简单的方法是使用for-each循环将数组中的所有元素添加到新的ArrayList中。

ArrayList<Element> list = new ArrayList<>();

for(Element e : array)
    list.add(e);

10

如果数组是原始类型,则给出的答案将不起作用。但是从Java 8开始,您可以使用:

int[] array = new int[5];
Arrays.stream(array).boxed().collect(Collectors.toList());

该解决方案似乎也不适用于char数组。
PixelMaster

8

您可以在Java 8中执行以下操作

ArrayList<Element> list = (ArrayList<Element>)Arrays.stream(array).collect(Collectors.toList());

1
投票失败,因为该演员看来非常危险。没有任何东西指定返回的列表类型实际上是一个ArrayList,如javadoc所述:“对返回列表的类型,可变性,可序列化性或线程安全性没有任何保证”
Dorian Gray

1
如果要显式创建ArrayList,请尝试以下操作:ArrayList<String> list = Arrays.stream(array).collect(Collectors.toCollection(ArrayList::new));
Dorian Gray,

8

我们可以轻松地将数组转换为ArrayList。我们使用Collection接口的addAll()方法来将内容从一个列表复制到另一个列表。

 Arraylist arr = new Arraylist();
 arr.addAll(Arrays.asList(asset));

这比接受的9年老答案的效率低。
AjahnCharles

2
一个ArrayList小号的构造函数接受一个? extends Collection<T>参数,使得调用addAll冗余。
Tamoghna Chowdhury,

7

即使这个问题有很多写得很完美的答案,我也将添加我的意见。

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

可以通过以下方式创建新的ArrayList

ArrayList<Element> arraylist_1 = new ArrayList<>(Arrays.asList(array));
ArrayList<Element> arraylist_2 = new ArrayList<>(
    Arrays.asList(new Element[] { new Element(1), new Element(2), new Element(3) }));

// Add through a collection
ArrayList<Element> arraylist_3 = new ArrayList<>();
Collections.addAll(arraylist_3, array);

而且它们很好地支持ArrayList的所有操作

arraylist_1.add(new Element(4)); // or remove(): Success
arraylist_2.add(new Element(4)); // or remove(): Success
arraylist_3.add(new Element(4)); // or remove(): Success

但是以下操作仅返回ArrayList的List视图,而不返回实际的ArrayList。

// Returns a List view of array and not actual ArrayList
List<Element> listView_1 = (List<Element>) Arrays.asList(array);
List<Element> listView_2 = Arrays.asList(array);
List<Element> listView_3 = Arrays.asList(new Element(1), new Element(2), new Element(3));

因此,当尝试进行一些ArrayList操作时,它们将给出错误。

listView_1.add(new Element(4)); // Error
listView_2.add(new Element(4)); // Error
listView_3.add(new Element(4)); // Error

有关数组链接的列表表示的更多信息。


7

最简单的方法是添加以下代码。尝试和测试。

String[] Array1={"one","two","three"};
ArrayList<String> s1= new ArrayList<String>(Arrays.asList(Array1));

7

另一个Java8解决方案(我可能错过了大部分答案)。如果是这样,我表歉意。这将创建一个ArrayList(与List相对),即可以删除元素

package package org.something.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Junk {

    static <T> ArrayList<T>  arrToArrayList(T[] arr){
        return Arrays.asList(arr)
            .stream()
            .collect(Collectors.toCollection(ArrayList::new));
    }

    public static void main(String[] args) {
        String[] sArr = new String[]{"Hello", "cruel", "world"};
        List<String> ret = arrToArrayList(sArr);
        // Verify one can remove an item and print list to verify so
        ret.remove(1);
        ret.stream()
            .forEach(System.out::println);
    }
}

输出是...
Hello
world


7

使用以下代码将元素数组转换为ArrayList。

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

ArrayList<Element>elementArray=new ArrayList();
for(int i=0;i<array.length;i++) {
    elementArray.add(array[i]);
}

5

每个人都已经为您的问题提供了足够好的答案。现在,从所有建议中,您需要确定哪个将满足您的要求。您需要了解两种类型的集合。一种是未修改的集合,另一种是未修改的集合,可让您稍后修改对象。

因此,在这里我将给出两个用例的简短示例。

  • 不可变的集合创建::当您不想在创建后修改集合对象时

    List<Element> elementList = Arrays.asList(array)

  • 可变集合创建::在创建后可能想要修改创建的集合对象时。

    List<Element> elementList = new ArrayList<Element>(Arrays.asList(array));


List <Element> elementList = Arrays.asList(array)在原始数组上创建包装,从而使原始数组可用作List。因此,创建了一个包装对象,没有任何内容从原始数组复制。因此,不允许执行添加或删除元素之类的操作。
Priyanka

3
请注意,您的“不可变集合”并不是真正不变的- List返回的Arrays.asList仅仅是原始数组的包装,并且允许通过get和访问和修改单个项set。您可能应该澄清一下,您的意思是“不添加或删除元素”,而不是“不可变的”,这意味着根本不进行更改。
Tamoghna Chowdhury,

5

给定对象数组:

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

将数组转换为列表:

    List<Element> list = Arrays.stream(array).collect(Collectors.toList());

将数组转换为ArrayList

    ArrayList<Element> arrayList = Arrays.stream(array)
                                       .collect(Collectors.toCollection(ArrayList::new));

将数组转换为LinkedList

    LinkedList<Element> linkedList = Arrays.stream(array)
                     .collect(Collectors.toCollection(LinkedList::new));

列印清单:

    list.forEach(element -> {
        System.out.println(element.i);
    });

输出值

1个

2

3


4

Java 8的Arrays类提供了stream()方法,该方法具有接受原始数组和对象数组的重载版本。

/**** Converting a Primitive 'int' Array to List ****/

int intArray[] = {1, 2, 3, 4, 5};

List<Integer> integerList1 = Arrays.stream(intArray).boxed().collect(Collectors.toList());

/**** 'IntStream.of' or 'Arrays.stream' Gives The Same Output ****/

List<Integer> integerList2 = IntStream.of(intArray).boxed().collect(Collectors.toList());

/**** Converting an 'Integer' Array to List ****/

Integer integerArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

List<Integer> integerList3 = Arrays.stream(integerArray).collect(Collectors.toList());

3

下面的代码似乎是实现此目的的好方法。

new ArrayList<T>(Arrays.asList(myArray));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.