java集合工具类Collections中的“坑”
2016-12-19 17:19
127 查看
java集合工具类Collections包括以下几个方法:
在实际使用时发现通过以上方法创建的集合无法进行添加或删除操作。为什么返回的都是List/Set/Map,原生List/Set/Map和工具类创建的实例就不同呢?通过进入java源码查看后发现两者的确有很大的不同。
其次,既然是不可变的,那么
EMPTY_LIST常量定义的时候就初始化为
(以上源码版本为:jdk1.8.0_66)
一目了然,EmptyList是一个继承了AbstractList的静态内部类,但是它并没有覆写AbstractList类的
至此,也就明白了
另外
EMPTY_ELEMENTDATA源码如下所示:
(以上源码版本为:jdk1.8.0_66)
同样在
如有错误请批评指出!
2.Collections.emptyList() vs. new instance
public static final <T> List<T> emptyList()
public static final <T> Set<T> emptySet()
public static final <K,V> Map<K,V> emptyMap()
在实际使用时发现通过以上方法创建的集合无法进行添加或删除操作。为什么返回的都是List/Set/Map,原生List/Set/Map和工具类创建的实例就不同呢?通过进入java源码查看后发现两者的确有很大的不同。
1.查找原因
首先通过方法定义就可以看到这些方法都是final的,因此他们是不可变(immutable)的。这就解释了为什么创建的集合无法进行add()等操作。java API的解释:Returns an empty list (immutable).即返回一个不可变的空list。
其次,既然是不可变的,那么
Collections.emptyList()和
new ArrayList()有什么区别呢?通过查阅Collections源码可以发现两者其实有很大区别。
emptyList()的源码如下:
public static final <T> List<T> emptyList() { return (List<T>) EMPTY_LIST; }
emptyList()方法调用了EMPTY_LIST常量,EMPTY_LIST的定义如下:
@SuppressWarnings("rawtypes") public static final List EMPTY_LIST = new EmptyList<>();
EMPTY_LIST常量定义的时候就初始化为
EmptyList<>(),那么
EmptyList<>()又做了哪些事?其源码如下:
private static class EmptyList<E> extends AbstractList<E> implements RandomAccess, Serializable { private static final long serialV 4000 ersionUID = 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; } @Override public boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); return false; } @Override public void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); } @Override public void sort(Comparator<? super E> c) { } // Override default methods in Collection @Override public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); } @Override public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); } // Preserves singleton property private Object readResolve() { return EMPTY_LIST; } }
(以上源码版本为:jdk1.8.0_66)
一目了然,EmptyList是一个继承了AbstractList的静态内部类,但是它并没有覆写AbstractList类的
add()以及
get()等方法。同时
EMPTY_LIST是final修饰的,这就注定了EmptyList也不能有
add()等操作。
至此,也就明白了
Collections.emptyList()和
new ArrayList<T>()生成的
list是不同的。那么问题来了,既然已经有
List等类,为什么工具类
Collections中还要再定义一个内部类去实现空集合?难道不是多此一举吗?当然不是。那么在使用时两者之间如何选择呢?
2.Collections.emptyList() VS new ArrayList()
2.1相同点
他们都是AbstractList的子类,都可以序列化(Serializable)。
2.2区别
Collections.emptyList()返回一个不可变list,而
new ArrayList<T>()返回的list是可变的。如果确实需要返回一个不可变的空list最好使用
Collections.emptyList();
Collections.emptyList()多次调用只返回同一个list实例,而
new ArrayList<T>()每次调用都会返回新的实例。如果程序中需要多次创建不可变的空list那么最好通过
Collections.emptyList()来实现,因为它占用的资源比
new ArrayList<T>()要少;
另外
ArrayList的带参构造函数
ArrayList(int initialCapacity)传入参数0,即返回
new ArrayList<>(0),以此来代替
new ArrayList<>()也可以创建一个不可变的集合对象。因为
new ArrayList<>(0)返回的是一个不可变的空数组。如下源码所示:
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA;//EMPTY_ELEMENTDATA为一个不可变空数组 } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
EMPTY_ELEMENTDATA源码如下所示:
private static final Object[] EMPTY_ELEMENTDATA = {};
(以上源码版本为:jdk1.8.0_66)
同样在
emptySet()及
emptyMap()等类似的方法也会有类似的现象,就不再一一列举。
3.总结
当我们带着问题深入源码的时候总能发现意想不到的事。既然JDK有Collections.emptyList()这样的实现,必定有其特殊的用意。因此我们要时常去思考问题的本质,去打破砂锅问到底这样才能弄清楚问题的真相。
如有错误请批评指出!
参考文献
1.Collections.emptyList2.Collections.emptyList() vs. new instance
相关文章推荐
- Java类集 _集合工具类:Collections
- Java笔记(二十四)……集合工具类Collections&Arrays
- Java基础---泛型、集合框架工具类:collections和Arrays
- java第八章集合中的Collections操作集合的工具类
- Java从零开始学二十四(集合工具类Collections)
- Java基础17:集合工具类Collections;高级for循环;静态导入;可变参数
- 黑马程序员—java基础学习--Map集合、Collections,Arrays工具类
- 线程高级应用-心得8-java5线程并发库中同步集合Collections工具类的应用及案例分析
- 黑马程序员——Java基础--集合框架工具类:Collections、Arrays、其他对象
- 黑马程序员-JAVA基础-Java 集合之Collections 工具类
- java基础入门----Collections1 集合框架工具类
- 黑马程序员 java 基础 毕向东 面向对象 集合框架 工具类 Collections and Arrays
- Java 集合工具类 Collections
- 线程高级应用-心得8-java5线程并发库中同步集合Collections工具类的应用及案例分析
- 黑马程序员_Java第17天知识总结_集合框架的工具类_Collections_Arrays_将数组变成list集合_集合变数组_高级for循环_可变参数
- Java类集 _集合工具类:Collections
- [Google Guava] 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具
- Java 集合工具类Collections
- 黑马程序员——Java基础---泛型、集合框架工具类:collections和Arrays
- JAVA学习--Collections集合工具类使用