用 Collections.unmodifiableList()
方法
想象你有一个装满水果的篮子,这个篮子代表一个 List
。你想要确保没有人可以拿走或添加水果到篮子里。你可以使用 Collections.unmodifiableList()
方法,它就像给篮子加了一把锁,使得篮子看起来是开着的,但实际上无法被修改。
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
public class FruitBasket {
public static void main(String[] args) {
// 创建一个装满水果的篮子(ArrayList)
List<String> fruits = new ArrayList<>();
fruits.add("苹果");
fruits.add("香蕉");
fruits.add("橙子");
// 将篮子上锁,变成不可修改的篮子
List<String> unmodifiableFruits = Collections.unmodifiableList(fruits);
// 尝试修改不可修改的篮子
// unmodifiableFruits.add("新水果"); // 这行代码会抛出异常
// unmodifiableFruits.remove("香蕉"); // 这行代码也会抛出异常
// 你可以查看篮子中的水果,但不能改变它们
System.out.println("不可修改的篮子中的水果:");
for (String fruit : unmodifiableFruits) {
System.out.println(fruit);
}
}
}
在这个故事中,unmodifiableFruits
就像是一个只读的篮子,你可以查看里面的水果,但不能添加或移除它们。
用 Collections.unmodifiableSet()
或 Collections.unmodifiableMap()
方法
如果你有一个装满糖果的盒子,这个盒子代表一个 Set
,你想要确保没有人可以拿走或添加糖果。你可以使用 Collections.unmodifiableSet()
方法。
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class CandyBox {
public static void main(String[] args) {
// 创建一个装满糖果的盒子(HashSet)
Set<String> candies = new HashSet<>();
candies.add("巧克力");
candies.add("软糖");
candies.add("棒棒糖");
// 将盒子上锁,变成不可修改的盒子
Set<String> unmodifiableCandies = Collections.unmodifiableSet(candies);
// 尝试修改不可修改的盒子
// unmodifiableCandies.add("新糖果"); // 这行代码会抛出异常
// unmodifiableCandies.remove("软糖"); // 这行代码也会抛出异常
// 你可以查看盒子中的糖果,但不能改变它们
System.out.println("不可修改的盒子中的糖果:");
for (String candy : unmodifiableCandies) {
System.out.println(candy);
}
}
}
如果你有一个装满钥匙的盒子,这个盒子代表一个 Map
,你想要确保没有人可以拿走或添加钥匙。你可以使用 Collections.unmodifiableMap()
方法。
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class KeyBox {
public static void main(String[] args) {
// 创建一个装满钥匙的盒子(HashMap)
Map<String, String> keys = new HashMap<>();
keys.put("家门", "钥匙A");
keys.put("车门", "钥匙B");
keys.put("抽屉", "钥匙C");
// 将盒子上锁,变成不可修改的盒子
Map<String, String> unmodifiableKeys = Collections.unmodifiableMap(keys);
// 尝试修改不可修改的盒子
// unmodifiableKeys.put("新钥匙", "钥匙D"); // 这行代码会抛出异常
// unmodifiableKeys.remove("车门"); // 这行代码也会抛出异常
// 你可以查看盒子中的钥匙,但不能改变它们
System.out.println("不可修改的盒子中的钥匙:");
for (Map.Entry<String, String> entry : unmodifiableKeys.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
}
}
用 Collections.emptySet()
, Collections.emptyMap()
, Collections.emptyList()
想象你有一个空的篮子,这个篮子代表一个空的 Set
,你想要确保没有人可以拿走或添加水果到篮子里。你可以使用 Collections.emptySet()
方法。
import java.util.Collections;
import java.util.Set;
public class EmptyFruitBasket {
public static void main(String[] args) {
// 创建一个空的篮子
Set<String> emptyFruits = Collections.emptySet();
// 尝试修改空篮子
// emptyFruits.add("苹果"); // 这行代码会抛出异常
// emptyFruits.remove("香蕉"); // 这行代码也会抛出异常
// 你可以查看篮子是否为空,但不能改变它
System.out.println("空篮子是否为空:" + emptyFruits.isEmpty());
}
}
使用 Collections.singleton()
想象你有一个装满巧克力的盒子,这个盒子代表一个 Set
,你想要确保这个盒子只有一块巧克力。你可以使用 Collections.singleton()
方法。
import java.util.Collections;
import java.util.Set;
public class ChocolateBox {
public static void main(String[] args) {
// 创建一个只有一块巧克力的盒子
Set<String> chocolate = Collections.singleton("巧克力");
// 尝试修改盒子
// chocolate.add("新巧克力"); // 这行代码会抛出异常
// chocolate.remove("巧克力"); // 这行代码也会抛出异常
// 你可以查看盒子中的巧克力,但不能改变它们
System.out.println("只有一块巧克力的盒子中的巧克力:");
for (String candy : chocolate) {
System.out.println(candy);
}
}
}
使用 Collections.nCopies()
想象你有一个装满相同玩具的箱子,这个箱子代表一个 List
,你想要确保这个箱子只有一件玩具。你可以使用 Collections.nCopies()
方法。
import java.util.Collections;
import java.util.List;
public class ToyBox {
public static void main(String[] args) {
// 创建一个只有一件玩具的箱子
List<String> toys = Collections.nCopies(1, "玩具车");
// 尝试修改箱子
// toys.add("新玩具"); // 这行代码会抛出异常
// toys.remove("玩具车"); // 这行代码也会抛出异常
// 你可以查看箱子中的玩具,但不能改变它们
System.out.println("只有一件玩具的箱子中的玩具:");
for (String toy : toys) {
System.out.println(toy);
}
}
}
使用 自定义一个不可变集合
自定义不可变集合意味着你需要创建一个类,这个类将包含一个集合,并且不允许外部代码修改这个集合。为了实现这一点,你需要确保集合的引用是私有的,并且不提供任何修改集合的方法。
下面是一个简单的例子,展示了如何创建一个不可变的 List
:
import java.util.ArrayList;
import java.util.List;
public final class ImmutableListExample {
private final List<String> list;
public ImmutableListExample(List<String> list) {
// 创建一个不可变的列表,这里使用了Collections.unmodifiableList()来确保列表不可修改
this.list = Collections.unmodifiableList(new ArrayList<>(list));
}
// 提供一个方法来获取列表的副本,但不提供修改列表的方法
public List<String> getList() {
return new ArrayList<>(list);
}
// 主方法,用于演示
public static void main(String[] args) {
List<String> originalList = new ArrayList<>();
originalList.add("苹果");
originalList.add("香蕉");
originalList.add("橙子");
ImmutableListExample immutableListExample = new ImmutableListExample(originalList);
// 尝试修改列表
// immutableListExample.getList().add("新水果"); // 这行代码会抛出异常
// 你可以查看列表中的水果,但不能改变它们
System.out.println("不可修改的列表中的水果:");
for (String fruit : immutableListExample.getList()) {
System.out.println(fruit);
}
}
}
在这个例子中,ImmutableListExample
类有一个私有的 List<String>
类型的成员变量 list
。在构造函数中,我们使用 Collections.unmodifiableList()
方法来创建一个不可修改的列表,并将其赋值给 list
。这样,外部代码就无法直接修改这个列表了。
我们还提供了一个 getList()
方法,它返回一个列表的副本。这样,外部代码可以读取列表中的元素,但不能修改原始列表。
请注意,虽然我们创建了一个不可修改的列表,但这个列表的元素本身(在这个例子中是字符串)是可以被修改的,因为它们是可变的。如果你想要确保列表中的元素也是不可修改的,你需要确保这些元素本身也是不可变的。
通过这种方式,你可以创建一个自定义的不可变集合,它封装了内部的集合,并且提供了只读的访问方式。