【Java】Java之Collections.emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方

it2025-05-26  16

1.概述

2.好处

如果你想 new 一个空的 List ,而这个 List 以后也不会再添加元素,那么就用 Collections.emptyList() 好了。new ArrayList() 或者 new LinkedList() 在创建的时候有会有初始大小,多少会占用一内存。 每次使用都new 一个空的list集合,浪费就积少成多,浪费就严重啦,就不好啦为了编码的方便。 比如说一个方法返回类型是List,当没有任何结果的时候,返回null,有结果的时候,返回list集合列表。 那样的话,调用这个方法的地方,就需要进行null判断。使用emptyList这样的方法,可以方便方法调用者。返回的就不会是null,省去重复代码。

2.1 不占用内存

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 freeMemoryNew=Runtime.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: 0

我们可以看出new ArrayList执行一万次会消耗1430376KB内存,而Collections.emptyList不会消耗内存。

那有人会说emptyList不也是new EmptyList()吗?

其实我们再仔细看下源码就发现emptyList是一个static变量,只会初始化一次,所以后续使用不会再初始化对象。此时我们可以得出结论,emptyList不占用内存,但是无法执行add等方法,new ArrayList()占用内存,但是会初始化对象数组,可以执行add等方法。

3.注意

这个空的集合是不能调用.add(),添加元素的。因为直接报异常。因为源码就是这么写的:直接抛异常。

Collections里面没这么写,但是EmptyList继承了AbstractList这个抽象类,里面简单实现了部分集合框架的方法。

这里面的add方法最后调用的方法体,就是直接抛异常。

throw new UnsupportedOperationException();

这么解释add报异常就对啦。

4.源码

下面简单看下这个源码:

/** * Collections 类里面的方法如下,一步步往下看就是啦 */ public static final <T> List<T> emptyList() { return (List<T>) EMPTY_LIST; } //。。。。。 /** * Collections 类里面的方法如下,一步步往下看就是啦 */ public static final List EMPTY_LIST = new EmptyList<>(); //。。。。。 /** * Collections里面的一个静态内部类 */ 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; } }

除了这个emptyList,之外,还有类似的,emptyMap,emptySet等等。具体看下图,都是一个套路。

5.案例

参考:https://blog.csdn.net/m0_46309515/article/details/107161340

最新回复(0)