数组与集合

数组与集合都是用来存储对象的容器,前者性质单一,方便易用,后者类型安全,功能强大,且两者之间必然有互相转换的方式。毕竟它们的性格迥异,在转换过程中,如果不注意转换背后的实现方式,很容易产生意料之外的问题。数组转集合和集合转数姐。在数组转集合的过程中,注意是否使用了视图方式直接返回数组中的数据。我们以 Arrays.asList() 为例,它把数组转换成集合时,不能使用其修改集合相关的方法 它的add/remove clear 方法会抛出UnsupportedOperationException 异常。示例源码如下:
package com.wjl.ssmdemo;

import java.util.Arrays;
import java.util.List;

public class ArraysAsList {
    public static void main(String[] args) {
        String[]  stringArray = new String[3];
        stringArray[0] = "one";
        stringArray[1] = "two";
        stringArray[2] = "three";

        List<String> stringList = Arrays.asList(stringArray);
        //修改转换后的集合,成功地把第一个元素改成“onelist”
        stringList.set(0,"onelist");
        //运行结果是1,数组地值随着改变
        System.out.println(stringArray[0]);

        //编译正确,但是抛出运行时异常
        stringList.add("four");
        stringList.remove(2);
        stringList.clear();
    }
}

Arrays.asList 体现的是适配器模式,后台的数据仍是原有数组, set()方法即间接对数组进行值的修改操作。 asList 的返回对象是一个Arrays的内部类,它并没有实现集合个数的相关修改方法,这也正是抛出异常的原因。Arrays.asList 的源码如下:
public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
返回的明明是 ArrayList 对象,怎么就不可以随心所欲地对此集合进行修改呢?注意此 ArrayList 非彼 ArrayList ,虽然 Arrays 与ArrayList 同属于一个包,但是在Arrays 类中还定义了一个 ArrayList 的内部类(或许命名为 InnerArray List 更容易识别),根据作用域就近原则,此处的 ArrayList 是李鬼,即这是个内部类。此李鬼十分简单,只提供了个别方法的实现,如下所示:
 private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
    //final修饰不准修改其应用
private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); } @Override
//实现了修改特定位置元素的方法
public E set(int index, E element) { E oldValue = a[index]; a[index] = element;
  //注意set成功返回的是此位置上的旧值。  
return oldValue; } }
第一处的 final 引用,用于存储集合的数组引用始终被强制指向原有数组。这个内部类并没有实现任何修改集合元素个数的相关方法 那这个UnsupportedOperatonException 异常是从哪里抛出来的呢?是李鬼的父类AbstractList
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {

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

}
如果李鬼 Arrays .ArrayList 内部类写这些方法不抛出异常,避免使用者踩进这个坑会不会更好。数组具有不为五斗米折腰的气节,传递的信息是“要么直接用我,要么小心异常| ”数组转集合引发的故障还是十分常见的。比如,某业务调用某接口时,对方以这样的方式返回 List 类型的集合对象,本方获取集合数据时, 99.9% 是只读操作,但在小概率情况下需要增加一个元素,从而引发故障。在使用数组转集合时,需要使用 java util.ArrayList 直接创建一个新集合,参数就是Arrays .asList 返回的不可变集合,源码如下:
List<Object>  objectList = new java.util.ArrayList<Object>(Arrays.asList(数组));
相对于数组转集合来说 集合转数组更加可控,毕竟是从相对自由的集合容器转为更加苛刻的数组。什么情况下集合需要转成数组呢?适配到人的数组接口,或者进行局部方法计算等。
 
 
原文地址:https://www.cnblogs.com/Dream-chasingGirl/p/11338178.html