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

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

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

相关文章
|
19天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
33 3
|
19天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
31 2
|
4天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
4天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
4天前
|
Java 开发者
|
16天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
45 5
|
16天前
|
存储 缓存 算法
Java 数组
【10月更文挑战第19天】Java 数组是一种非常实用的数据结构,它为我们提供了一种简单而有效的方式来存储和管理数据。通过合理地使用数组,我们能够提高程序的运行效率和代码的可读性。更加深入地了解和掌握 Java 数组的特性和应用,为我们的编程之旅增添更多的精彩。
30 4
|
16天前
|
存储 缓存 算法
提高 Java 数组性能的方法
【10月更文挑战第19天】深入探讨了提高 Java 数组性能的多种方法。通过合理运用这些策略,我们可以在处理数组时获得更好的性能表现,提升程序的运行效率。
16 2
|
17天前
|
安全 Java 程序员
Java集合之战:ArrayList vs LinkedList,谁才是你的最佳选择?
本文介绍了 Java 中常用的两个集合类 ArrayList 和 LinkedList,分析了它们的底层实现、特点及适用场景。ArrayList 基于数组,适合频繁查询;LinkedList 基于链表,适合频繁增删。文章还讨论了如何实现线程安全,推荐使用 CopyOnWriteArrayList 来提升性能。希望帮助读者选择合适的数据结构,写出更高效的代码。
46 3
|
4天前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
6 0