什么是集合的视图?

在使用Guava集合并阅读其文档时,我一直在阅读术语视图几次。

我已经在这个背景下寻找一个视图的解释,以及它是否是在番石榴之外使用的术语。 它经常在这里使用。 Guava的这种类型有其名称的视图

我的猜测是,集合的视图是另一个具有相同数据但结构不同的集合; 例如,当我将java.util.HashSet的条目添加到java.util.LinkedHashSet ,后者将是前者的视图。 那是对的吗?

有人可以给我一个链接到一个公认的视图定义,如果有的话?

谢谢。

另一个对象的视图根本不包含自己的数据。 它的所有操作都是根据对另一个对象的操作实现的。

例如, MapkeySet()视图可能具有如下所示的实现:

 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。