16

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

我一直在寻找关于在这种情况下视图是什么以及它是否是在番石榴之外使用的术语的解释。它在这里经常使用。这种来自 Guava 的类型在其名称中具有视图。

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

有人可以给我一个链接到公认的view定义(如果有的话)吗?

谢谢。

4

2 回答 2

25

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

例如,a 的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), thenkeySet.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"

视图只是查看原始支持对象中数据的另一种方式——Arrays.asList允许您使用ListAPI 访问普通数组;Map.keySet()让您可以像访问Map一个完全普通的 a 一样访问它的键Set——所有这些都无需复制数据或创建另一个数据结构。

通常,使用视图而不是复制的优点是效率。例如,如果您有一个数组,并且您需要将它获取到一个采用 a 的方法List,那么您并没有创建一个新ArrayList的和完整的数据副本——Arrays.asList视图只占用恒定的额外内存,并且只是实现了所有List通过访问原始数组的方法。

于 2013-09-19T18:43:23.703 回答
7

在这种情况下,视图是由另一个集合(或数组)支持的集合,该集合本身使用恒定数量的内存(即内存不依赖于支持集合的大小)。应用于视图的操作被委托给支持集合(或数组)。当然,可以将此定义扩展到集合之外,但您的问题似乎专门针对它们。

例如,Arrays.asList()返回“指定数组的列表视图”。它不会将元素复制到新列表,而是创建一个包含对数组的引用并基于此进行操作的列表。

另一个示例是Collections.unmodifiableList()返回“指定列表的不可修改视图”。换句话说,它返回一个列表,其中包含对指定列表的引用,所有操作都委托给该列表。在这种情况下,返回的列表不允许您以任何方式对其进行修改,因此不是委派负责改变列表的方法,而是在调用此类方法时引发异常。

于 2013-09-19T18:42:15.107 回答