Java Collections的emptyList、EMPTY_LIST详解与使用说明

目录
  • Collections的emptyList、EMPTY_LIST使用
  • Collections.emptyList()使用注意

Collections的emptyList、EMPTY_LIST使用

今天在看大佬写的代码的时候,结果集为空的情况,他返回的不是null,而是:

return Collections.EMPTY_LIST;

我们都知道返回null,很有可能造成空指针异常,可以使用emptyList或EMPTY_LIST就可以避免这个问题,除非你想捕获这个为空的信息

我们在使用emptyList空的方法返回空集合的时候要注意,这个空集合是不可变的。

空的集合不可以使用add方法,会报UnsupportedOperationException异常,看如下源码:

    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

空集合对象不可以使用put方法,会报IndexOutOfBoundsException异常,看如下源码:

 public E get(int index) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }

但是对于for循环都不会发生异常,如下的示例:

 List<String> list1 = Collections.emptyList();
        for(String s:list1) {
        }
        for(int i=0;i<list1.size();i++) {
        }

上面的两种for循环都可以正常的执行,第一种foreach循环,实际编译之后会变成迭代器的模式,这样我们就好理解为什么可以正常执行;第二种是只调用了size方法,我们可以看到源码直接返回0;

public int size() {return 0;}

emptyList和EMPTY_LIST的区别,我们看下源码:

    /**
     * The empty list (immutable).  This list is serializable.
     *
     * @see #emptyList()
     */
    @SuppressWarnings("unchecked")
    public static final List EMPTY_LIST = new EmptyList<>();
/**
     * Returns the empty list (immutable).  This list is serializable.
     *
     * <p>This example illustrates the type-safe way to obtain an empty list:
     * <pre>
     *     List&lt;String&gt; s = Collections.emptyList();
     * </pre>
     * Implementation note:  Implementations of this method need not
     * create a separate <tt>List</tt> object for each call.   Using this
     * method is likely to have comparable cost to using the like-named
     * field.  (Unlike this method, the field does not provide type safety.)
     *
     * @see #EMPTY_LIST
     * @since 1.5
     */
    @SuppressWarnings("unchecked")
    public static final <T> List<T> emptyList() {
        return (List<T>) EMPTY_LIST;
    }

我们看到EMPTY_LIST 是Collections类的一个静态常量,而emptyList是支持泛型的。若是不需要泛型的地方可以直接使用 EMPTY_LIST ,若是需要泛型的地方就需要使用emptyList。

通过上面的分析我们可以很清楚的知道什么时候使用emptyList;Collections集合中还有其它的几种空集合emptyMap、emptySet,他们的使用方法跟上面的大同小异。

Collections.emptyList()使用注意

偶然发现有小伙伴错误地使用了Collections.emptyList()方法,这里记录一下。它的使用方式是:

public void run() {
    ......
    List list = buildList(param);
    ......
    Object newNode = getNode(...);
    list.add(newNode);
    ......
}

public List buildList(Object param) {
    if (isInValid(param)) {
        return Collections.emptyList();
    } else {
        ......
    }
}

buildList方法中可能会返回一个"空的List",后续还可能往这个List添加元素(或者移除元素),但是没有注意Collections.emptyList方法返回的是一个EMPTY_LIST:

public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

它是一个static final修饰的成员变量,是一个EmptyList类的实例:

public static final List EMPTY_LIST = new EmptyList<>();

这个EmptyList是一个静态内部类,和ArrayList一样继承自AbstractList:

private static class EmptyList<E>
        extends AbstractList<E>
        implements RandomAccess, Serializable {
        private static final long serialVersionUID = 8842843931221139166L;
        public Iterator<E> iterator() {
            return emptyIterator();
        }
        public ListIterator<E> listIterator() {
            return emptyListIterator();
        }

        public int size() {return 0;}
        public boolean isEmpty() {return true;}
        public boolean contains(Object obj) {return false;}
        public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
        public Object[] toArray() { return new Object[0]; }
        public <T> T[] toArray(T[] a) {
            if (a.length > 0)
                a[0] = null;
            return a;
        }

        public E get(int index) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }

        public boolean equals(Object o) {
            return (o instanceof List) && ((List<?>)o).isEmpty();
        }

        public int hashCode() { return 1; }

        // Preserves singleton property
        private Object readResolve() {
            return EMPTY_LIST;
        }
    }

可以看到这个EmptList没有重写add方法,并且get方法也是直接抛出一个IndexOutOfBoundsException异常。既然没有重写add方法,那么看看父类AbstractList中的add方法:

public boolean add(E e) {
    add(size(), e);
    return true;
}

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

可以看到直接抛出的UnsupportedOperationException异常。再回到EmptyList类中,它对外提供的一些方法也很明显地限制了它的使用范围。

对于Collections.emptyList(),或者说Collections.EMPTY_LIST,最好只把它当做一个空列表的标识(可以想象成一个frozen过的空List),不要对其做一些增删改查的操作。如果程序中的一些分支逻辑返回了这种实例,测试的时候又没有覆盖到,在生产环境如果走到了这个分支逻辑,那就麻烦了~

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java中的collection集合类型总结

    Java集合是java提供的工具包,包含了常用的数据结构:集合.链表.队列.栈.数组.映射等.Java集合工具包位置是java.util.* Java集合主要可以划分为4个部分:List列表.Set集合.Map映射.工具类(Iterator迭代器.Enumeration枚举类.Arrays和Collections). Java集合工具包框架如下图. 说明:看上面的框架图,先抓住它的主干,即Collection和Map. Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作

  • Java中Collections.emptyList()的注意事项

    偶然发现有小伙伴错误地使用了Collections.emptyList()方法,这里记录一下.她的使用方式是: public void run() { ...... List list = buildList(param); ...... Object newNode = getNode(...); list.add(newNode); ...... } public List buildList(Object param) { if (isInValid(param)) { return Co

  • Java集合教程之Collection实例详解

    前言 集合就是一组数的集合,就像是一个容器,但是我们应该清楚的是集合中存放的都是对象的引用,而不是真正的实体.而我们常说的集合中的对象其实指的就是对象的引用. 我们可以把集合理解为一个小型数据库,用于存放数据,我们对集合的操作也就是数据的增删改查,在 Java 中有两个顶层接口 Collection 和 Map 用于定义和规范集合的相关操作.这篇文章主要说一下集合框架中的 Collection 部分. Collection 表示一组对象,这些对象可以是有序也可以是无序的,它提供了不同的子接口满足

  • Java Collections类操作集合详解

    Collections 类是 Java 提供的一个操作 Set.List 和 Map 等集合的工具类.Collections 类提供了许多操作集合的静态方法,借助这些静态方法可以实现集合元素的排序.查找替换和复制等操作.下面介绍 Collections 类中操作集合的常用方法. 1) 排序(Sort)     使用sort方法可以根据元素的自然顺序,对指定列表进行排序.列表中的所有元素都必须实现 Comparable 接口.或此列表内的所有元素都必须是使用指定比较器可相互比较的   Collec

  • Java Collections.shuffle()方法案例详解

    Java.util.Collections类下有一个静态的shuffle()方法,如下: 1)static void shuffle(List<?> list)  使用默认随机源对列表进行置换,所有置换发生的可能性都是大致相等的. 2)static void shuffle(List<?> list, Random rand) 使用指定的随机源对指定列表进行置换,所有置换发生的可能性都是大致相等的,假定随机源是公平的. 通俗一点的说,就像洗牌一样,随机打乱原来的顺序. 注意:如果给

  • Java Collections的emptyList、EMPTY_LIST详解与使用说明

    目录 Collections的emptyList.EMPTY_LIST使用 Collections.emptyList()使用注意 Collections的emptyList.EMPTY_LIST使用 今天在看大佬写的代码的时候,结果集为空的情况,他返回的不是null,而是: return Collections.EMPTY_LIST; 我们都知道返回null,很有可能造成空指针异常,可以使用emptyList或EMPTY_LIST就可以避免这个问题,除非你想捕获这个为空的信息 我们在使用emp

  • Java Comparable 和 Comparator 的详解及区别

    Java Comparable 和 Comparator 的详解及区别 Java 中为我们提供了两种比较机制:Comparable 和 Comparator,他们之间有什么区别呢?今天来了解一下. Comparable 自然排序 Comparable 在 java.lang 包下,是一个接口,内部只有一个方法 compareTo(): public interface Comparable<T> { public int compareTo(T o); } Comparable 可以让实现它的

  • java LRU(Least Recently Used )详解及实例代码

    java LRU(Least Recently Used )详解 LRU是Least Recently Used 的缩写,翻译过来就是"最近最少使用",LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉,比如我们缓存10000条数据,当数据小于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最大缓存10000条,那怎么确定删除哪条过期数据呢,采用LRU算法实现的话就是将最老的数据

  • java 中Comparable与Comparator详解与比较

    java 中Comparable与Comparator详解 今天查看TreeMap的源码,发现其键必须是实现Comparable或者Comparator的接口时产生了一些兴趣,比如在TreeMap中的put方法分别对Comparable和Comparator接口分别进行处理.那么疑问就来了,Comparable和Comparator接口的区别是什么,Java中为什么会存在两个类似的接口?   Comparable和Comparator接口都是用来比较大小的,首先来看一下Comparable的定义

  • Java的SPI机制实例详解

    Java的SPI机制实例详解 SPI的全名为Service Provider Interface.普通开发人员可能不熟悉,因为这个是针对厂商或者插件的.在java.util.ServiceLoader的文档里有比较详细的介绍.究其思想,其实是和"Callback"差不多."Callback"的思想是在我们调用API的时候,我们可以自己写一段逻辑代码,传入到API里面,API内部在合适的时候会调用它,从而实现某种程度的"定制". 典型的是Colle

  • Java Map的排序实例详解

     Java Map的排序实例详解 要对Map中的key-value键值对进行排序,可以使用Collections类提供的sort方法.该方法允许用户使用自定义的排序方法,可以按键进行排序,或者按值进行排序. 具体代码如下: 1.产生需要的数据 Map<String, Integer> map_Data = new HashMap<String, Integer>(); map_Data.put("A", 98); map_Data.put("B&quo

  • 基于java中集合的概念(详解)

    1.集合是储存对象的,长度可变,可以封装不同的对象 2.迭代器: 其实就是取出元素的方式(只能判断,取出,移除,无法增加) 就是把取出方式定义在集合内部,这样取出方式就可以直接访问集合内部的元素,那么取出方式就被定义成了内部类. 二每一个容器的数据结构不同,所以取出的动作细节也不一样.但是都有共性内容判断和取出,那么可以将共性提取,这些内部类都符合一个规则Iterator Iterator it = list.iterator(); while(it.hasNext()){ System.out

  • java集合中的list详解

    1.List接口 该接口定义的元素是有序的且可重复的.相当于数学里面的数列,有序可重复 booleanaddAll(intindex,Collection<?extendsE>c);将指定集合中所有元素,插入至本集合第index个元素之后defaultvoidreplaceAll(UnaryOperatoroperator);替换集合中每一个元素值defaultvoidsort(Comparator<?superE>c);给集合中的元素进行排序Eget(intindex);获取集合

随机推荐