使用Collections

使用Collections

廖雪峰

资深软件开发工程师,业余马拉松选手。

Collections是JDK提供的工具类,同样位于java.util包中。它提供了一系列静态方法,能更方便地操作各种集合。

注意

Collections结尾多了一个s,不是Collection!

我们一般看方法名和参数就可以确认Collections提供的该方法的功能。例如,对于以下静态方法:

public static boolean addAll(Collection c, T... elements) { ... }

addAll()方法可以给一个Collection类型的集合添加若干元素。因为方法签名是Collection,所以我们可以传入List,Set等各种集合类型。

创建空集合

对于旧版的JDK,可以使用Collections提供的一系列方法来创建空集合:

创建空List:List emptyList()

创建空Map:Map emptyMap()

创建空Set:Set emptySet()

要注意到返回的空集合是不可变集合,无法向其中添加或删除元素。

新版的JDK≥9可以直接使用List.of()、Map.of()、Set.of()来创建空集合。

创建单元素集合

对于旧版的JDK,Collections提供了一系列方法来创建一个单元素集合:

创建一个元素的List:List singletonList(T o)

创建一个元素的Map:Map singletonMap(K key, V value)

创建一个元素的Set:Set singleton(T o)

要注意到返回的单元素集合也是不可变集合,无法向其中添加或删除元素。

新版的JDK≥9可以直接使用List.of(T...)、Map.of(T...)、Set.of(T...)来创建任意个元素的集合。

排序

Collections可以对List进行排序。因为排序会直接修改List元素的位置,因此必须传入可变List:

import java.util.*;

public class Main {

public static void main(String[] args) {

List list = new ArrayList<>();

list.add("apple");

list.add("pear");

list.add("orange");

// 排序前:

System.out.println(list);

Collections.sort(list);

// 排序后:

System.out.println(list);

}

}

洗牌

Collections提供了洗牌算法,即传入一个有序的List,可以随机打乱List内部元素的顺序,效果相当于让计算机洗牌:

import java.util.*;

public class Main {

public static void main(String[] args) {

List list = new ArrayList<>();

for (int i=0; i<10; i++) {

list.add(i);

}

// 洗牌前:

System.out.println(list);

// 洗牌:

Collections.shuffle(list);

// 洗牌后:

System.out.println(list);

}

}

不可变集合

Collections还提供了一组方法把可变集合封装成不可变集合:

封装成不可变List:List unmodifiableList(List list)

封装成不可变Set:Set unmodifiableSet(Set set)

封装成不可变Map:Map unmodifiableMap(Map m)

这种封装实际上是通过创建一个代理对象,拦截掉所有修改方法实现的。我们来看看效果:

import java.util.*;

public class Main {

public static void main(String[] args) {

List mutable = new ArrayList<>();

mutable.add("apple");

mutable.add("pear");

// 变为不可变集合:

List immutable = Collections.unmodifiableList(mutable);

immutable.add("orange"); // UnsupportedOperationException!

}

}

然而,继续对原始的可变List进行增删是可以的,并且,会直接影响到封装后的“不可变”List:

import java.util.*;

public class Main {

public static void main(String[] args) {

List mutable = new ArrayList<>();

mutable.add("apple");

mutable.add("pear");

// 变为不可变集合:

List immutable = Collections.unmodifiableList(mutable);

mutable.add("orange");

System.out.println(immutable);

}

}

因此,如果我们希望把一个可变List封装成不可变List,那么,返回不可变List后,最好立刻扔掉可变List的引用,这样可以保证后续操作不会意外改变原始对象,从而造成“不可变”List变化了:

import java.util.*;

public class Main {

public static void main(String[] args) {

List mutable = new ArrayList<>();

mutable.add("apple");

mutable.add("pear");

// 变为不可变集合:

List immutable = Collections.unmodifiableList(mutable);

// 立刻扔掉mutable的引用:

mutable = null;

System.out.println(immutable);

}

}

线程安全集合

Collections还提供了一组方法,可以把线程不安全的集合变为线程安全的集合:

变为线程安全的List:List synchronizedList(List list)

变为线程安全的Set:Set synchronizedSet(Set s)

变为线程安全的Map:Map synchronizedMap(Map m)

多线程的概念我们会在后面讲。因为从Java 5开始,引入了更高效的并发集合类,所以上述这几个同步方法已经没有什么用了。

小结

Collections类提供了一组工具方法来方便使用集合类:

创建空集合;

创建单元素集合;

创建不可变集合;

排序/洗牌等操作。

🎈 相关推荐

揭秘!52岁田慧泰国定居真相,单身豪宅生活背后的故事
为什么黑人的丁丁那么长?原因你可能想象不到
约彩365安卓老版本

为什么黑人的丁丁那么长?原因你可能想象不到

📅 06-30 👀 2552
新手如何从零开始学炒股? 学炒股并不难,真正难的是静下心来学。很多朋友刚看懂了K线图,就开始实盘操作,结果不尽人意。那新手小白学炒股具体该如何操作...