另一个对象的视图根本不包含自己的数据。它的所有操作都是根据对另一个对象的操作来实现的。
例如,的视图可能具有如下所示的实现:keySet()
Map
class KeySet implements Set<K> {
private final Map<K, V> map;
public boolean contains(Object o) {
return map.containsKey(o);
}
...
}
特别是,每当您修改视图的后备对象时 -- 这里,后退 -- 视图都会反映相同的更改。例如,如果您调用 ,则无需执行任何其他操作即可返回。Map
keySet()
map.remove(key)
keySet.contains(key)
false
或者,提供该数组的视图。Arrays.asList(array)
List
String[] strings = {"a", "b", "c"};
List<String> list = Arrays.asList(strings);
System.out.println(list.get(0)); // "a"
strings[0] = "d";
System.out.println(list.get(0)); // "d"
list.set(0, "e");
System.out.println(strings[0]); // "e"
视图只是查看原始支持对象中数据的另一种方式 - 允许您使用API访问普通数组; 允许您访问的键,就好像它是一个完全普通的键 - 所有这些都不需要复制数据或创建另一个数据结构。Arrays.asList
List
Map.keySet()
Map
Set
通常,使用视图而不是制作副本的优点是效率。例如,如果你有一个数组,并且需要将其获取到一个采用 的方法,则不会创建数据的一个新的完整副本 - 视图只需要恒定的额外内存,并且只需通过访问原始数组来实现所有方法。List
ArrayList
Arrays.asList
List
此上下文中的视图是由另一个集合(或数组)支持的集合,该集合本身使用恒定数量的内存(即内存不依赖于支持集合的大小)。应用于视图的操作将委派给后备集合(或数组)。当然,可以将此定义扩展到集合之外,但您的问题似乎与它们特别相关。
例如,Arrays.asList()
返回“指定数组的列表视图”。它不会将元素复制到新列表中,而是创建一个包含对数组的引用并基于该列表进行操作的列表。
另一个例子是 Collections.unmodifiableList(
),它返回“指定列表的不可修改视图”。换句话说,它返回一个列表,其中包含对指定列表的引用,所有操作都委托给该列表。在这种情况下,返回的列表不允许您以任何方式修改它,因此,当调用此类方法时,它不会委派负责更改列表的方法,而是引发异常。