【问题标题】:Create ArrayList from array从数组创建 ArrayList
【发布时间】:2010-09-14 13:12:02
【问题描述】:

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

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

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

ArrayList<Element> arraylist = ???;

【问题讨论】:

  • 在 Java9 中 --> List list = List.of(“Hello”, “World”, “from”, “Java”);
  • @MarekM 这个答案是错误的,因为它不会返回ArrayList。海报专门要求这样做。
  • 我认为他没有使用 List 接口进行挖掘,因为这是最佳实践。但如果你想要的是 - new ArrayList(List.of(“Hello”, “World”, “from”, “Java”));
  • 重点不是使用接口,重点是在您的解决方案中,返回的列表是不可修改的。这可能是一个更大的问题,也是他要求使用 ArrayList 的原因

标签: java arrays arraylist type-conversion


【解决方案1】:
new ArrayList<>(Arrays.asList(array));

【讨论】:

  • 是的。在(最常见的)您只需要一个列表的情况下,new ArrayList 调用也是不必要的。
  • @Luron - 只需使用List&lt;ClassName&gt; list = Arrays.asList(array)
  • @Calum 和@Pool - 如下亚历克斯米勒的回答中所述,使用Arrays.asList(array) 而不将其传递给新的ArrayList 对象将修复列表的大小。使用ArrayList 的更常见原因之一是能够动态更改其大小,而您的建议可以防止这种情况发生。
  • Arrays.asList() 是一个可怕的函数,你不应该只使用它的返回值。它破坏了 List 模板,因此请始终以此处指示的形式使用它,即使它看起来确实是多余的。很好的答案。
  • @Adam 请研究 java.util.List 的 javadoc。 add 的合同允许他们抛出 UnsupportedOperationException。 docs.oracle.com/javase/7/docs/api/java/util/… 诚然,从面向对象的角度来看,很多时候你必须知道具体的实现才能使用集合并不是很好 - 这是一个实用的设计选择,以保持框架简单。
【解决方案2】:

给定:

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

【讨论】:

  • Arrays.asList() 只是通过包装现有数组来创建一个 ArrayList,因此它是 O(1)。
  • 包装在一个新的 ArrayList() 中将导致固定大小列表的所有元素被迭代并添加到新的 ArrayList 中,O(n) 也是如此。
【解决方案3】:

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

如果可以,请使用番石榴

值得指出的是 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

Why Guava?

主要的吸引力可能是减少由于类型安全泛型导致的混乱,因为使用 Guava factory methods 允许在大多数时间推断类型。然而,自从 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() 的返回类型是使用具体的ArrayList 实现的List,但它不是 java.util.ArrayList。它是一种内部类型,它模拟 ArrayList 但实际上直接引用传递的数组并使其“直写”(修改反映在数组中)。

它禁止通过简单地扩展AbstractList 的方式通过List 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);
}

【讨论】:

  • +1 但请注意,Arrays.asList 返回的 List 是可变的,因为您仍然可以使用 set 元素 - 它只是无法调整大小。对于没有 Guava 的不可变列表,您可能会提到 Collections.unmodifiableList
【解决方案4】:

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

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

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

【讨论】:

  • 特别是List&lt;String&gt; a = Arrays.asList("first","second","third")
【解决方案5】:
new ArrayList<T>(Arrays.asList(myArray));

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

【讨论】:

    【解决方案6】:

    另一种方式(虽然在性能方面基本上等同于new ArrayList(Arrays.asList(array)) 解决方案:

    Collections.addAll(arraylist, array);
    

    【讨论】:

      【解决方案7】:

      Java 9

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

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

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

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

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

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

      【讨论】:

      • List.of() 不会按照原始问题的要求返回 java.util.ArrayList 的实例。因此,只有第二个选项是有效答案。
      【解决方案8】:

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

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

      【讨论】:

      • 这将由原始输入数组支持,这就是您(可能)想要将其包装在新的 ArrayList 中的原因。
      • 小心这个解决方案。如果你看,Arrays 不会返回一个真正的 java.util.ArrayList。它返回一个实现所需方法的内部类,但您不能更改列表中的成员。它只是一个数组的包装器。
      • 您可以将 List 项转换为 ArrayList
      • @Mikezx6r:小更正:这是一个固定大小的列表。可以更改列表的元素(set 方法),不能更改列表的大小(不是addremove 元素)!
      • 是的,但需要注意的是,这取决于您要对列表执行的操作。值得注意的是,如果 OP 只是想遍历元素,则根本不需要转换数组。
      【解决方案9】:

      另一个更新,即将于 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
      • 不正确使用 Stream.of(...);这将创建一个元素流。改用 Arrays.stream
      • 我不这么认为,这 2 个选项是有效的,但 Arrays.stream 稍微“更好”,因为您可以使用带有 'start'、'end 的重载方法以固定大小创建它' 参数。另见:stackoverflow.com/a/27888447/2619091
      【解决方案10】:

      如果你使用:

      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。但如果它不合适,或者你感觉不到,那就写另一条不雅的行来代替。

      【讨论】:

      • 我看不出答案末尾的循环与您不鼓励使用的 new ArrayList&lt;T&gt;(Arrays.asList(myArray)); 部分之间的根本区别。两者的功能完全相同,并且具有相同的复杂性。
      • 集合在数组的开头创建一个指针。我的循环创建了许多指针:每个数组成员一个。因此,如果原始数组发生变化,我的指针仍然指向以前的值。
      • new ArrayList&lt;T&gt;(Arrays.asList(myArray)); 做同样的事情,它将asList 复制到ArrayList...
      【解决方案11】:

      Java 9你可以使用:

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

      【讨论】:

      • 请注意,这不是一个 ArrayList,因为它是明确要求的。
      【解决方案12】:

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

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

      但最好始终使用该界面:

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

      【讨论】:

        【解决方案13】:
        // Guava
        import com.google.common.collect.ListsLists
        ...
        List<String> list = Lists.newArrayList(aStringArray); 
        

        【讨论】:

          【解决方案14】:

          从 Java 8 开始,有一种更简单的转换方式:

          import java.util.List;    
          import static java.util.stream.Collectors.toList;
          
          public static <T> List<T> fromArray(T[] array) {
              return Arrays.stream(array).collect(toList());
          }
          

          【讨论】:

            【解决方案15】:

            您可以使用不同的方法进行转换

            1. List&lt;Element&gt; list = Arrays.asList(array);

            2. List<Element> list = new ArrayList();
              Collections.addAll(list, array);

            3. Arraylist list = new Arraylist();
              list.addAll(Arrays.asList(array));

            更多详情可以参考http://javarevisited.blogspot.in/2011/06/converting-array-to-arraylist-in-java.html

            【讨论】:

              【解决方案16】:

              正如大家所说,这样做会这样做

               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 支持的新的空 observable 列表。 observableArrayList(E... 项目) 创建一个新的可观察数组列表,其中添加了项目。

              更新 Java 9

              在 Java 9 中也有点简单:

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

              【讨论】:

                【解决方案17】:

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

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

                【讨论】:

                • java 8 开始,Collectors.toList() 将返回一个 ArrayList。但是,这在 java 的未来版本中可能会有所不同。如果您想要特定类型的集合,请使用 Collectors.toCollection() 代替,您可以在其中指定要创建的确切集合类型。
                【解决方案18】:
                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);
                  

                【讨论】:

                  【解决方案19】:

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

                  ArrayList<Element> list = new ArrayList<>();
                  
                  for(Element e : array)
                      list.add(e);
                  

                  【讨论】:

                    【解决方案20】:

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

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

                    【讨论】:

                    • 这个解决方案似乎也不适用于char 数组。
                    【解决方案21】:

                    即使这个问题有很多完美的书面答案,我还是会添加我的意见。

                    假设你有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
                    

                    更多关于数组link的列表表示。

                    【讨论】:

                      【解决方案22】:

                      最简单的方法是添加以下代码。久经考验。

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

                      【讨论】:

                        【解决方案23】:

                        另一个 Java8 解决方案 (我可能错过了大集合中的答案。如果是这样,我很抱歉)。 这将创建一个 ArrayList(而不是 List),即可以删除元素 p>

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

                        输出是...
                        你好
                        世界

                        【讨论】:

                          【解决方案24】:

                          你可以在java 8中这样做

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

                          【讨论】:

                          • 投反对票,因为该演员表看起来非常危险。 nothing 指定返回的列表类型实际上是 ArrayList,正如 javadoc 所述:“无法保证返回的列表的类型、可变性、可序列化性或线程安全性”
                          • 如果你想显式创建一个 ArrayList,试试这个:ArrayList&lt;String&gt; list = Arrays.stream(array).collect(Collectors.toCollection(ArrayList::new));
                          【解决方案25】:

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

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

                          【讨论】:

                          • 这比公认的 9 岁答案效率低。
                          • ArrayLists 构造函数之一接受? extends Collection&lt;T&gt; 参数,从而使对addAll 的调用变得多余。
                          【解决方案26】:

                          使用以下代码将元素数组转换为 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]);
                          }
                          

                          【讨论】:

                            【解决方案27】:

                            给定对象数组:

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

                            将数组转换为列表:

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

                            将数组转换为数组列表

                                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

                            【讨论】:

                              【解决方案28】:

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

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

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

                                List&lt;Element&gt; elementList = Arrays.asList(array)

                              • 可变集合创建 :: 当您可能希望在创建后修改已创建的集合对象时。

                                List&lt;Element&gt; elementList = new ArrayList&lt;Element&gt;(Arrays.asList(array));

                              【讨论】:

                              • List elementList = Arrays.asList(array) 在原始数组上创建一个包装器,使原始数组可用作列表。因此创建了一个包装对象,没有从原始数组中复制任何内容。因此,不允许添加或删除元素等操作。
                              • 请注意,您的“不可变集合”并不是真正不可变的 - Arrays.asList 返回的 List 只是原始数组的包装,并允许通过 @987654325 访问和修改单个项目@ 和 set。您可能应该澄清您的意思是“不添加或删除元素”而不是“不可变”,这意味着根本不改变。
                              【解决方案29】:

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

                              【讨论】:

                                【解决方案30】:

                                下面的代码看起来不错。

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

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 2016-01-24
                                  • 1970-01-01
                                  • 2013-08-19
                                  • 2013-07-05
                                  • 1970-01-01
                                  • 2016-04-06
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多