从数组创建ArrayList
我有一个初始化的数组,如:
Element[] array = {new Element(1), new Element(2), new Element(3)};
我想将此数组转换为ArrayList类的对象.
ArrayList<Element> arraylist = ???;
回答
new ArrayList<>(Arrays.asList(array))
- 是的.在(最常见的)你只想要一个列表的情况下,`new ArrayList`调用也是不必要的.
- @Calum和@Pool - 如下所述,在Alex Miller的回答中,使用`Arrays.asList(array)`而不将其传递给新的`ArrayList`对象将修复列表的大小.使用`ArrayList`的一个常见原因是能够动态地改变它的大小,你的建议会阻止这种情况.
- @Luron - 只需使用`List <ClassName> list = Arrays.asList(array)`
- Arrays.asList()是一个可怕的函数,你永远不应该只使用它的返回值.它打破了List模板,所以总是以这里指出的形式使用它,即使它看起来多余.好答案.
- @Adam请研究java.util.List的javadoc.add的合约允许它们抛出UnsupportedOperationException.http://docs.oracle.com/javase/7/docs/api/java/util/List.html#add%28E%29不可否认,从面向对象的角度来看,很多时候你不得不这么做了解具体实现以便使用集合 - 这是一个实用的设计选择,以保持框架简单.
- @Adam`Arrays.asList()`是一个非常有用的方法,当你想要一个特定数组支持的列表时.例如`Collections.shuffle(Arrays.asList(myarray))`shuffle*original*array.
- 我想指出,如果要使用迭代器执行mutative(如remove)操作,则需要新的ArrayList <Element>(...)部分.
- 需要注意的是:我只是遇到了Java 6的不当行为:当Element是一个原语(例如数组是int [])时,asList创建了List <int []>.
- @Arkadiy当`a`是`int []`时,`Arrays.asList(a).get(0)== a`并不是一个错误.这是因为`asList(Object ...)`varargs如何解析.一个类型为`int []`的对象是一个`Object`,而不是一个`Object []`,所以`Arrays.asList`正在传递一个带有一个元素的`Object`数组:一个`int`数组.
- 当数组的类型为`int []`并且等效的用例如下时,这不会编译:`List <Integer> intList = new ArrayList <Integer>(Arrays.asList(intArray));`
- @lbalazscs是真的,但我会说这非常接近黑客(即使shuffle方法是打算以这种方式使用),因为你基本上是在欺骗它,因为它认为它处理的是List而不是.很方便,但我仍然说这是一个可怕的功能.我的论点基本上是asList()方法具有误导性,因为它看起来像返回给定数组的List表示,而实际上它返回一个仅部分实现的List表示.
- @AndrewF我明白为什么会这样.这只是为我打破DWIM,就是这样.
- Arrays.asList(array).remove(key)将抛出:`java.util.AbstractList.remove(AbstractList.java:161)中的线程"main"java.lang.UnsupportedOperationException中的异常...` - dunno how [ `AbstractList`](http://docs.oracle.com/javase/7/docs/api/java/util/AbstractList.html)进入那里,但是在调用remove时你不想要它
- 对于数组为基本类型(例如int [])的情况,请参见以下问题:http://stackoverflow.com/questions/1073919/how-to-convert-int-into-listinteger-in-java
- 另外,`List <Element> list = new ArrayList <>(Arrays.asList(array));`就足够了.[diamond](http://stackoverflow.com/questions/4166966/what-is-the-point-of-the-diamond-operator-in-java-7)运算符将为您执行类型推断.
- 这对Java 1.8不起作用.在Java 1.8中,`Arrays.asList(array)`将创建一个列表,其唯一的元素是`array`.结果列表不包含`array`的元素.
鉴于:
Element[] array = new Element[] { new Element(1), new Element(2), new Element(3) };
最简单的答案是:
List<Element> list = Arrays.asList(array);
这样可以正常工作.但有些警告:
- 从asList返回的列表具有固定大小.因此,如果您希望能够在代码中添加或删除返回列表中的元素,则需要将其包装在新代码中
ArrayList
.否则你会得到一个UnsupportedOperationException
. - 返回的列表
asList()
由原始数组支持.如果修改原始数组,则也会修改列表.这可能会令人惊讶.
- Arrays.asList()只是通过包装现有数组来创建一个ArrayList,因此它是O(1).
- 包装新的ArrayList()将导致固定大小列表的所有元素被迭代并添加到新的ArrayList,因此是O(n).
- asList()返回的List的实现没有实现List的几个方法(如add(),remove(),clear()等等),这解释了UnsupportedOperationException.绝对是一个警告......
- 当问题要求"ArrayList类的一个对象"时,我认为假设它引用的类是`java.util.ArrayList`是合理的.Arrays.asList实际上返回一个`java.util.Arrays.ArrayList`,它不是另一个类的`instanceof`.所以第三个警告是,如果你试图在需要上述内容的环境中使用它,它将无法工作.
- 两种操作的时间复杂度是多少?我的意思是使用和不使用明确的arraylist结构.
(老线程,但只有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与新的钻石操作员到达以来,这个论点持有的水量更少.
但这并不是唯一的原因(并且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()
是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);
}
- +1但请注意,`Arrays.asList`返回的`List`是可变的,因为你仍然可以`set`元素 - 它只是不可调整大小.对于没有Guava的不可变列表,你可能会提到[`Collections.unmodifiableList`](http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#unmodifiableList (java.util.List) )).
由于这个问题已经很久了,所以没有人提出最简单的表格让我感到惊讶:
List<Element> arraylist = Arrays.asList(new Element(1), new Element(2), new Element(3));
从Java 5开始,Arrays.asList()
采用varargs参数,您不必显式构造数组.
- 特别是,`List <String> a = Arrays.asList("first","second","third")`
new ArrayList<T>(Arrays.asList(myArray));
new ArrayList<T>(Arrays.asList(myArray));
new ArrayList<T>(Arrays.asList(myArray));
new ArrayList<T>(Arrays.asList(myArray));
确保它myArray
的类型相同T
.例如,如果您尝试List<Integer>
从数组中创建一个数组,则会出现编译器错误int
.
Collections.addAll(arraylist, array);
>
另一种方式(尽管基本上等同于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 269为Java Collections API 提供了一些便利工厂方法.这些一成不变的静态工厂方法被内置到List
,Set
和Map
Java中9以及更高的接口.
您可能只需要一个List,而不是ArrayList.在这种情况下,您可以这样做:
List<Element> arraylist = Arrays.asList(array);
- 小心这个解决方案.如果你看,Arrays不会返回一个真正的java.util.ArrayList.它返回一个实现所需方法的内部类,但您无法更改列表中的成员.它只是一个数组的包装器.
- @ Mikezx6r:小**校正**:这是一个固定大小的列表.你可以改变列表的元素(`set`方法),你不能改变列表的大小(不是'add`或`remove`元素)!
- 这将由原始输入数组支持,这就是您(可能)想要将其包装在新的ArrayList中的原因.
另一个更新,即将结束的2014年,您也可以使用Java 8:
ArrayList<Element> arrayList = Stream.of(myArray).collect(Collectors.toCollection(ArrayList::new));
如果这可能只是一个字符,那么会保存几个字符 List
List<Element> list = Stream.of(myArray).collect(Collectors.toList());
- 最好不要依赖于实现,但`Collectors.toList()`实际上返回一个`ArrayList`.
如果您使用:
你可以创建并填写两个列表!填充两次大清单正是您不想做的事情,因为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
}
....
}
危险的一面是,如果更改初始数组,则更改列表!你确定要的吗?可能是可能不是.
如果没有,最容易理解的方法是这样做:
ArrayList<Element> list = new ArrayList<Element>(myArray.length); // you know the initial capacity
for (Element element : myArray) {
list.add(element);
}
或者如所述@glglgl,您可以使用以下命令创建另一个独立的ArrayList:
我爱用Collections
,Arrays
或番石榴.但如果它不适合,或者你感觉不适合,那就改写另一条不优雅的线.
在Java 9
你可以使用:
List<String> list = List.of("Hello", "World", "from", "Java");
List<Integer> list = List.of(1, 2, 3, 4, 5);
根据问题,使用java 1.7的答案是:
ArrayList<Element> arraylist = new ArrayList<Element>(Arrays.<Element>asList(array));
但是最好总是使用界面:
List<Element> arraylist = Arrays.<Element>asList(array);
// Guava
import com.google.common.collect.ListsLists
...
List<String> list = Lists.newArrayList(aStringArray);
您可以使用不同的方法转换
有关更多详细信息,请参阅http://javarevisited.blogspot.in/2011/06/converting-array-to-arraylist-in-java.html
正如所有人所说,这样做会
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
更新Java 9
在Java 9中它也有点简单:
List<String> list = List.of("element 1", "element 2", "element 3");
从Java 8开始,有一种更简单的转换方法:
public static <T> List<T> fromArray(T[] array) {
return Arrays.stream(array).collect(toList());
}
您也可以使用Java 8中的流来完成.
List<Element> elements = Arrays.stream(array).collect(Collectors.toList());
- 从** java 8 **开始,`Collectors.toList()`将返回`ArrayList`。但是这在Java的未来版本中可能会有所不同。如果您想要特定类型的集合,请使用Collectors.toCollection()代替,在那里您可以指定要创建的确切集合类型。
-
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));
-
public static <T> boolean addAll(Collection<? super T> c, T... a);
所以,这段代码也很有用
另一种简单的方法是使用for-each循环将数组中的所有元素添加到新的ArrayList中.
ArrayList<Element> list = new ArrayList<>();
for(Element e : array)
list.add(e);
如果数组是原始类型,则给定的答案将不起作用.但是从Java 8开始,您可以使用:
int[] array = new int[5];
Arrays.stream(array).boxed().collect(Collectors.toList());
使用以下代码将元素数组转换为 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]);
}
我们可以轻松地将数组转换为ArrayList
.我们使用Collection接口的addAll()
方法将内容从一个列表复制到另一个列表.
Arraylist arr = new Arraylist();
arr.addAll(Arrays.asList(asset));
- ArrayList的一个构造函数接受`?扩展Collection <T>参数,使对addAll的调用变得多余。
给定对象数组:
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<Element> linkedList = Arrays.stream(array)
.collect(Collectors.toCollection(LinkedList::new));
打印列表:
list.forEach(element -> {
System.out.println(element.i);
});
输出
1
2
3
每个人都已经为您的问题提供了足够好的答案。现在,从所有建议中,您需要决定哪个适合您的要求。您需要了解两种类型的集合。一个是未修改的集合,另一个是允许您稍后修改对象的集合。
所以,在这里我将给出两个用例的简短示例。
-
List<Element> elementList = Arrays.asList(array)
-
List<Element> elementList = new ArrayList<Element>(Arrays.asList(array));
- 请注意,您的“不可变集合”并不是真正不可变的 - `Arrays.asList` 返回的 `List` 只是原始数组的包装器,并允许通过 `get` 和 `set` 访问和修改单个项目。您可能应该澄清您的意思是“不添加或删除元素”而不是“不可变”,这意味着根本不改变。
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());
即使这个问题有很多写得很好的答案,我也会添加我的意见。
说你有 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
有关数组链接的列表表示的更多信息。
最简单的方法是添加以下代码。尝试和测试。
String[] Array1={"one","two","three"};
ArrayList<String> s1= new ArrayList<String>(Arrays.asList(Array1));
您可以在Java 8中执行以下操作
ArrayList<Element> list = (ArrayList<Element>)Arrays.stream(array).collect(Collectors.toList());
- 投反对票,因为那个演员看起来很危险。没有指定返回的列表类型实际上是一个 ArrayList,正如 javadoc 所述:“返回的列表的类型、可变性、可序列化性或线程安全性没有任何保证”
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
下面的代码似乎是这样做的好方法。