什么是集合的视图?

2022-09-03 00:07:26

在使用番石榴系列并阅读其文档时,我一直在阅读术语视图几次。

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

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

有人可以用一个指向视图的公认定义的链接来连接我吗?如果有的话?

谢谢。


答案 1

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

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

class KeySet implements Set<K> {
  private final Map<K, V> map;

  public boolean contains(Object o) {
    return map.containsKey(o);
  }

  ...
}

特别是,每当您修改视图的后备对象时 -- 这里,后退 -- 视图都会反映相同的更改。例如,如果您调用 ,则无需执行任何其他操作即可返回。MapkeySet()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.asListListMap.keySet()MapSet

通常,使用视图而不是制作副本的优点是效率。例如,如果你有一个数组,并且需要将其获取到一个采用 的方法,则不会创建数据的一个新的完整副本 - 视图只需要恒定的额外内存,并且只需通过访问原始数组来实现所有方法。ListArrayListArrays.asListList


答案 2

此上下文中的视图是由另一个集合(或数组)支持的集合,该集合本身使用恒定数量的内存(即内存不依赖于支持集合的大小)。应用于视图的操作将委派给后备集合(或数组)。当然,可以将此定义扩展到集合之外,但您的问题似乎与它们特别相关。

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

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