如何将List<>转换为ArrayList<>?

64
能否请问为什么我用第一种方法无法将 List<> 强制转换为 ArrayList<>,而用第二种方法却可以呢?谢谢。

第一种方法:

ArrayList<Task> tmp = ((ArrayList<Task>)mTrackytAdapter.getAllTasks(token));

第二种方法:

ArrayList<Task> tmp = new ArrayList<Task>(mTrackytAdapter.getAllTasks(token));
10个回答

45

当你执行第二个操作时,你正在创建一个新的arraylist,而不是试图假装其他列表是arraylist。

我的意思是,如果原始列表以linkedlist或某些自定义列表实现,你将不知道。如果你确实需要从结果中创建一个arraylist,则更喜欢第二种方法。但是你可以将其保留为列表,这是使用接口的最大优点之一!


25

当您使用第二种方法时,您会使用其预定义值初始化arraylist。 就像我们通常做的那样

**ArrayList listofStrings = new ArrayList<>(); **

假设您有一个带有值的数组,现在您想将此数组转换为arraylist。

您需要先使用Arrays utils从数组中获取列表。因为ArrayList是实现List接口的具体类型。不能保证asList方法会返回这种类型的实现。

List<String>  listofOptions = (List<String>) Arrays.asList(options);

那么您可以使用ArrayList的构造函数来实例化并预定义值。

ArrayList<String> arrlistofOptions = new ArrayList<String>(list);

所以你的第二种方法是可行的,你传递的值将实例化ArrayList与列表元素。

而且

从Arrays.asList返回的ArrayList不是真正的ArrayList,它只是一个包装器,不允许对列表进行任何修改。如果你尝试在Arrays.asList上添加或删除,它会给你UnsupportedOperationException。


6
尝试运行以下代码:
List<String> listOfString = Arrays.asList("Hello", "World");
ArrayList<String> arrayListOfString = new ArrayList(listOfString);
System.out.println(listOfString.getClass());
System.out.println(arrayListOfString.getClass());

您将会得到以下结果:
class java.util.Arrays$ArrayList
class java.util.ArrayList

因此,这意味着它们是两个不相互扩展的类。java.util.Arrays$ArrayList表示命名为ArrayList(Arrays类的内部类)的私有类,而java.util.ArrayList表示命名为ArrayList的公共类。因此,从java.util.Arrays$ArrayList转换为java.util.ArrayList以及反过来都是无关紧要/不可用的。

5
第二种方法如果你想进行转换,显然是错误的。它实例化了一个新的ArrayList。
然而,第一种方法应该可以正常工作,只要getAllTasks返回一个ArrayList。
你真的需要一个ArrayList吗?List接口不够用吗?如果类型不正确,你所做的事情可能会导致运行时异常。
如果getAllTasks()返回一个ArrayList,则应该在类定义中更改返回类型,然后您将不需要进行转换;如果返回其他内容,则无法转换为ArrayList。

5

只需尝试以下操作:

ArrayList<SomeClass> arrayList;

 public SomeConstructor(List<SomeClass> listData) {
        arrayList.addAll(listData);
}

3
如果你知道自己在做什么,可以将List<>强制转换为ArrayList<>,Java编译器不会阻止。
但是:
1. 在未检查的情况下将父类型强制转换为子类型(或接口强制转换为实现类型)是不好的实践。更好的方式是: if (list instanceof ArrayList<Task>) { ArrayList<Task> arraylist = (ArrayList<Task>) list; } 2. 也许你不需要实现类型作为引用。参见SonarQube警告https://sbforge.org/sonar/rules/show/squid:S1319。在大多数情况下,你可以避免这种强制转换。
3. 你可以使用Guava方法: ArrayList<Task> arraylist = Lists.newArrayList(list);

2

第一种方法是尝试转换列表,但这只适用于 List<>ArrayList<> 的情况。但事实并非如此。因此您需要第二种方法,即使用 List<> 的元素构建一个新的ArrayList<>


1

可能是:

ArrayList<ServiceModel> services = new ArrayList<>(parking.getServices());
intent.putExtra("servicios",services);

1

0
import java.util.List;
import java.util.Arrays;
import java.util.*;

public class Merge
{  
  public static void main(String[] args) {
  // This is normal way
  // List<Integer> l1 = new ArrayList<Integer>(); l1.add(2); l1.add(5); l1.add(10); l1.add(22); 
  // List<Integer> l2 = new ArrayList<Integer>(); l2.add(3); l2.add(8); l2.add(15); 

 //Array.asList only have the list interface, but ArrayList is inherited from List Interface with few more property like ArrayList.remove()
 List<Integer> templ1 = Arrays.asList(2,5,10,22); 
 List<Integer> templ2 =  Arrays.asList(3,8,12);
//So creation of ArrayList with the given list is required, then only ArrayList.remove function works. 
 List<Integer> l1 = new ArrayList<Integer>(templ1);
 List<Integer> l2 = new ArrayList<Integer>(templ2);
 List<Integer> l3 = new ArrayList<Integer>();

 Iterator itr1 = l1.iterator();
 while(itr1.hasNext()){
    int x = (Integer) itr1.next();
    Iterator itr2 = l2.iterator();
    while(itr2.hasNext()) {
      int y = (Integer) itr2.next(); 
      if(x < y) {
        l3.add(x);
        break;
      }
      else{
        l3.add(y);
        itr2.remove();
         
      }
    }
 }
 
 Iterator it = l1.iterator(); 
 while (it.hasNext()){
  int k = (Integer) it.next();
  if (l3.contains(k)){
     continue;
  }
  else{
     l3.add(k);
     System.out.println(k);
  }
 }
 
 Iterator itr2 = l2.iterator();
 while (itr2.hasNext()){
  int k = (Integer) itr2.next();
  l3.add(k);
 }
 
 System.out.println(l3);
 }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接