网站建设哪里接活,开发商违约延期交房可以退房吗,如何给网站引流,住房城乡建设门户网站前言
Java中ArrayList或许是我们平时开发最常用的一个集合类了#xff0c;其次是HashMap#xff0c;基本上满足了业务开发的绝大多数场景。今天要说的就是Collections.emptyList()和new ArrayList()的区别以及注意事项。
先来一段代码 运行main方法#xff0c;会有如下输出…前言
Java中ArrayList或许是我们平时开发最常用的一个集合类了其次是HashMap基本上满足了业务开发的绝大多数场景。今天要说的就是Collections.emptyList()和new ArrayList()的区别以及注意事项。
先来一段代码 运行main方法会有如下输出 很显然Collections.emptyList()会抛出“java.lang.UnsupportedOperationException”的异常。
使用及区别
日常开发中我们经常会写一个方法返回一个集合。当这个方法返回的数据为空时候通常我们会返回一个Collections.emptyList()而不是null。这样方法调用者就不用担心集合是否null了。比如这样的 突然有一天有一个同事调用了你的这个方法然后再加入自己的数据 就会可能出现如下几种情况
自测时候被发现幸亏本大神自测发现不然测试那帮家伙肯定发现不了被测试发现那是因为没有数据好了好了我兼容一下好了代码上线了不断的抛出异常不断的报警大多数用户访问的页面出现系统异常。
很不幸我们真的成功的走到了第三步然后被用户反应出来了(因为只有部分用户在没有数据的情况下会产生这个bug)。。。 说了这么多那既然Collections.emptyList()有问题我就直接用new ArrayList()没问题了吧
是的没有问题但是总感觉low了点
所以搞清楚二者的区别以及适用场景才是一个爱学习的程序员要做的事情。
先看Collections.emptyList()方法的源码 返回一个不可变的空集合那如何是不可变的呢 原来是EmptyList类没有实现add()和remove()方法。
那使用这个方法的意义是什么或者说JDK为什么要提供这个方法呢
大家肯定看到了EMPTY_LIST这个类常量 它在Collections类里面属于静态常量静态常量什么概念在JVM虚拟机加载完毕时候就已经存在了当我们调用这个方法的时候不需要再去创建一个新的List对象了减少了内存开销。所以当你的方法调用频率很高并且可能会返回空集合时候使用Collections.emptyList()会提高你的代码性能降低内存开销。
总结
Collections.emptyList()返回了一个不可变的空集合不支持集合数据修改操作多次调用不会额外增加内存消耗new ArrayList()每次都会创建一个对象需要内存开销Collections.emptyList()使得调用者不需要去判断返回是否为null但是需要注意这个集合不可变EMPTY_LIST和emptyList()的唯一区别就是EMPTY_LIST没有支持泛型需要强转一下emptySet()、emptyMap()和emptyList()是一个道理Java 9中的List.of()简化了emptyList()的使用。 背景
项目中有时候会使用Collections.emptyList返回一个空列表但是emptyList在执行addremove等方法时会直接抛出UnsupportedOperationException异常我们可以看下源码
public class Collections {public static final List EMPTY_LIST new EmptyList();public static final T ListT emptyList() {return (ListT) EMPTY_LIST;}private static class EmptyListEextends AbstractListEimplements RandomAccess, Serializable {public int size() {return 0;}public boolean isEmpty() {return true;}public boolean contains(Object obj) {return false;}public E get(int index) {throw new IndexOutOfBoundsException(Index: index);}}
}public abstract class AbstractListE extends AbstractCollectionE implements ListE {public boolean add(E e) {add(size(), e);return true;}public void add(int index, E element) {throw new UnsupportedOperationException();}
}我们可以发现emptyList最后执行的是AbstractList里面的add方法所以会直接抛出异常。为了避免报错有同事提议将emptyList都用new ArrayList()代替此时决定看下emptyList的优势
代码
通过百度知道emptyList不需要占用内存而ArrayList每次new都会在堆中开辟内存空间存放对象我们先通过代码验证一下
public class ListTest {private static final int printCount 10000;public static void main(String[] args) {long freeMemory Runtime.getRuntime().freeMemory();System.out.println(freeMemory: freeMemory);for (int i 0; i printCount; i) {List newList new ArrayList();}long freeMemoryNewRuntime.getRuntime().freeMemory();System.out.println(freeMemory use: (freeMemory-freeMemoryNew));for(int i 0;i printCount; i){List emptyList Collections.emptyList();}long freeMemoryEmpty Runtime.getRuntime().freeMemory();System.out.println(freeMemory use: (freeMemoryNew-freeMemoryEmpty));}
}此时我们看一下执行结果
Connected to the target VM, address: 127.0.0.1:63534, transport: socket
Disconnected from the target VM, address: 127.0.0.1:63534, transport: socket
freeMemory: 253398816
freeMemory use: 1430376
freeMemory use: 0Process finished with exit code 0我们可以看出new ArrayList执行一万次会消耗1430376KB内存而Collections.emptyList不会消耗内存那有人会说emptyList不也是new EmptyList()吗其实我们再仔细看下上面的源码就发现emptyList是一个static变量只会初始化一次所以后续使用不会再初始化对象。此时我们可以得出结论emptyList不占用内存但是无法执行add等方法new ArrayList()占用内存但是会初始化对象数组可以执行add等方法。 Java之Collections.emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方
先说明一下好处有哪些 1如果你想 new 一个空的 List 而这个 List 以后也不会再添加元素那么就用 Collections.emptyList() 好了。 new ArrayList() 或者 new LinkedList() 在创建的时候有会有初始大小多少会占用一内存。 每次使用都new 一个空的list集合浪费就积少成多浪费就严重啦就不好啦 2为了编码的方便。 比如说一个方法返回类型是List当没有任何结果的时候返回null,有结果的时候返回list集合列表。 那样的话调用这个方法的地方就需要进行null判断。使用emptyList这样的方法可以方便方法调用者。返回的就不会是null省去重复代码。
注意的地方 这个空的集合是不能调用.add添加元素的。因为直接报异常。因为源码就是这么写的直接抛异常。
哦Collections里面没这么写但是EmptyList继承了AbstractList这个抽象类里面简单实现了部分集合框架的方法。 这里面的add方法最后调用的方法体就是直接抛异常。 throw new UnsupportedOperationException(); 这么解释add报异常就对啦。
下面简单看下这个源码 /** * Collections 类里面的方法如下,一步步往下看就是啦 */ public static final T ListT emptyList() { return (ListT) EMPTY_LIST; }
//。。。。。 /** * Collections 类里面的方法如下,一步步往下看就是啦 */ public static final List EMPTY_LIST new EmptyList();
//。。。。。 /** * Collections里面的一个静态内部类 */ private static class EmptyListE extends AbstractListE implements RandomAccess, Serializable { private static final long serialVersionUID 8842843931221139166L; public IteratorE iterator() { return emptyIterator(); } public ListIteratorE 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; } } 除了这个emptyList之外还有类似的emptyMapemptySet等等。具体看下图都是一个套路。