什么是集合的视图?
在使用Guava集合并阅读其文档时,我一直在阅读术语视图几次。
我已经在这个背景下寻找一个视图的解释,以及它是否是在番石榴之外使用的术语。 它经常在这里使用。 Guava的这种类型有其名称的视图 。
我的猜测是,集合的视图是另一个具有相同数据但结构不同的集合; 例如,当我将java.util.HashSet
的条目添加到java.util.LinkedHashSet
,后者将是前者的视图。 那是对的吗?
有人可以给我一个链接到一个公认的视图定义,如果有的话?
谢谢。
另一个对象的视图根本不包含自己的数据。 它的所有操作都是根据对另一个对象的操作实现的。
例如, Map
的keySet()
视图可能具有如下所示的实现:
class KeySet implements Set { private final Map 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 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"
视图只是查看原始后备对象中数据的另一种方式 – Arrays.asList
允许您使用List
API访问普通数组; Map.keySet()
允许您访问Map
的键,就好像它是一个完全普通的Set
– 所有这些都没有复制数据或创建另一个数据结构。
通常,使用视图而不是制作副本的优点是效率。 例如,如果你有一个数组并且你需要将它带到一个接受List
的方法,那么你就不是在创建一个新的ArrayList
和一个数据的整个副本Arrays.asList
视图只需要不变的额外内存,并通过访问原始数组实现所有List
方法。
此上下文中的视图是由另一个集合(或数组)支持的集合,该集合本身使用常量内存(即内存不依赖于后备集合的大小)。 应用于视图的操作将委派给后备集合(或数组)。 当然,有可能将此定义扩展到仅仅集合之外,但您的问题似乎与它们有关。
例如, Arrays.asList()
返回“指定数组的列表视图”。 它不会将元素复制到新列表,而是创建一个包含对数组的引用的列表,并根据该列表进行操作。
另一个例子是Collections.unmodifiableList()
,它返回“指定列表的不可修改的视图”。 换句话说,它返回一个列表,其中包含对委派所有操作的指定列表的引用。 在这种情况下,返回的列表不允许您以任何方式修改它,因此它不是委托负责变更列表的方法,而是在调用此类方法时抛出exception。