您现在的位置是:首页 > 文章详情

Java数组转集合与集合转数组的坑

日期:2019-07-23点击:549

Java数组转集合与集合转数组的坑
在Java中将数组转为集合,会用到Arrays.asList()的方法,然而,这个方法却与我们的预期期望存在一些出入,当用到asList方法将数组转化成List列表时,对得到的List列表进行add()和remove()操作, JVM会抛出异常:java.lang.UnsupportedOperationException异常

Arrays.asList返回的是同样的ArrayList,为什么就不能使用add和remove方法呢?

接下来我们来看一下Arrays.asList 源码

public static List asList(T... a) {

 return new ArrayList<>(a); }

复制代码
/**

 * @serial include */ private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); } @Override public int size() { return a.length; } @Override public Object[] toArray() { return a.clone(); } @Override @SuppressWarnings("unchecked")

复制代码
AbstractList源码:

复制代码
public abstract class AbstractList extends AbstractCollection implements List {

/** * Sole constructor. (For invocation by subclass constructors, typically * implicit.) */ protected AbstractList() { } /** * Appends the specified element to the end of this list (optional * operation). * * <p>Lists that support this operation may place limitations on what * elements may be added to this list. In particular, some * lists will refuse to add null elements, and others will impose * restrictions on the type of elements that may be added. List * classes should clearly specify in their documentation any restrictions * on what elements may be added. * * <p>This implementation calls {@code add(size(), e)}. * * <p>Note that this implementation throws an * {@code UnsupportedOperationException} unless * {@link #add(int, Object) add(int, E)} is overridden. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) * @throws UnsupportedOperationException if the {@code add} operation * is not supported by this list * @throws ClassCastException if the class of the specified element * prevents it from being added to this list * @throws NullPointerException if the specified element is null and this * list does not permit null elements * @throws IllegalArgumentException if some property of this element * prevents it from being added to this list */ public boolean add(E e) { add(size(), e); return true; } /** * {@inheritDoc} * * @throws IndexOutOfBoundsException {@inheritDoc} */ abstract public E get(int index); /** * {@inheritDoc} * * <p>This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ public E set(int index, E element) { throw new UnsupportedOperationException(); } /** * {@inheritDoc} * * <p>This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { throw new UnsupportedOperationException(); } /** * {@inheritDoc} * * <p>This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { throw new UnsupportedOperationException(); }

复制代码

由源码可见,UnsupportedOperationException 是AbstractList抛出的,因为Arrays中的ArrayList并没有实现remove()和add()方法,所以抛出了异常。
所以说 Arrays.asList 返回的 List 是一个不可变长度的列表,此列表不再具备原 List 的很多特性,因此慎用 Arrays.asList 方法。

ArrayList中构造方法:

ArrayList(E[] array) {

 a = Objects.requireNonNull(array); } 

看一段这样的代码:

复制代码
import java.util.Arrays;
import java.util.List;

public class Test2{

public static void main(String[] args) { int[] array = new int[]{1,2,3,4,5}; List list = Arrays.asList(array); System.out.println(list.size()); }

}
复制代码

Arrays 的内部类 ArrayList 构造方法接收的是一个泛型数组,即数组类型不能为基本类型,应该为其对应的包装类型(传即入引用类型),否则传入的基本类型的整个数组,将被编译器视为一个引用参数,

所以原始类型不能作为 Arrays.asList 方法的参数,否则会被当做一个参数

再来看看在Java中将集合转为数组,ArrayList提供了一个将List转为数组的一个非常方便的方法toArray。toArray有两个重载的方法:

@Override

 public Object[] toArray() { return a.clone(); }

复制代码
@Override

 @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) return Arrays.copyOf(this.a, size, (Class<? extends T[]>) a.getClass()); System.arraycopy(this.a, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }

复制代码
对于第一个重载方法,是将list直接转为Object[] 数组;

第二种方法是将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。

若采用第一种toArray方法,是这样写:

复制代码
1 ArrayList list=new ArrayList();
2 for (int i = 0; i < 10; i++) {
3 list.add(""+i);
4 }
5
6 String[] array= (String[]) list.toArray();
复制代码
结果一运行,报错:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

第一个方法不能将Object[] 转化为String[],我们需要修改为:

1 Object[] arr = list.toArray();
2 for (int i = 0; i < arr.length; i++) {
3 String e = (String) arr[i];
4 System.out.println(e);
5 }
建议用第二种方法:

复制代码
import java.util.ArrayList;
import java.util.List;

public class Test2{

public static void main(String[] args) { List<Integer> list = new ArrayList(); list.add(1); list.add(2); list.add(3); Integer[] array = new Integer[list.size()]; list.toArray(array); for (int i:array){ System.out.print(i+" "); } }

}
复制代码
或者

set.toArray(new Integer[set.size()]);
set好处是去除重复元素
原文地址https://www.cnblogs.com/hetaoyuan/archive/2019/07/24/11236999.html

原文链接:https://yq.aliyun.com/articles/710532
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章