• 数组与集合


    数组与集合都是用来存储对象的容器,前者性质单一,方便易用,后者类型安全,功能强大,且两者之间必然有互相转换的方式。毕竟它们的性格迥异,在转换过程中,如果不注意转换背后的实现方式,很容易产生意料之外的问题。数组转集合和集合转数姐。在数组转集合的过程中,注意是否使用了视图方式直接返回数组中的数据。我们以 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(数组));
    相对于数组转集合来说 集合转数组更加可控,毕竟是从相对自由的集合容器转为更加苛刻的数组。什么情况下集合需要转成数组呢?适配到人的数组接口,或者进行局部方法计算等。
     
     
  • 相关阅读:
    项目开发问题笔记
    HDU 1800——Flying to the Mars——————【字符串哈希】
    FZU 2122 ——又见LKity——————【KMP字符串匹配】
    FZU 2122——又见LKity——————【字符串匹配、暴力】
    POJ 3468——A Simple Problem with Integers——————【线段树区间更新, 区间查询】
    HRBUST 1909——理工门外的树——————【离线处理,差分前缀和】
    HRBUST 1161——Leyni——————【线段树单点更新,区间查询】
    用Gvim建立IDE编程环境 (Windows篇)
    FZU 2207 ——以撒的结合——————【LCA + 记录祖先】
    HDU 5635 ——LCP Array ——————【想法题】
  • 原文地址:https://www.cnblogs.com/Dream-chasingGirl/p/11338178.html
Copyright © 2020-2023  润新知