为什么 LinkedHashMap keyset() return LinkedHashSet 与 Set 不同?
Why doesn't LinkedHashMap keyset() return LinkedHashSet vs Set?
我已阅读 java 文档以及此 post 中,LinkedHashMaps 的 keyset()
维持秩序。
Is the order guaranteed for the return of keys and values from a LinkedHashMap object?
我的问题是,如果它保证顺序那么为什么 LinkedHashMap
return 的源代码不是 Set
类型的对象来保证顺序 LinkedHashSet
?
我可能想到的一个原因是 LinkedHashSet 使用一个会增加内存分配的映射(取决于 AbstractSet 的实现方式)。是否也是因为它未来证明了键集的实现?
就像这个 post 中的回答所说:Is it better to use List or Collection?
Returning a List is in line with programming to the Highest Suitable
Interface.
Returning a Collection would cause ambiguity to the user, as a
returned collection could be either: Set, List or Queue.
那么,不看keyset()
的文档,这不是模棱两可吗?
keyset()
源代码:
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
private final class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
}
它 returns 一个 Set
由 Map
接口定义。 Set
只是不包含重复元素的集合。另一方面,List
是有序集合(也称为序列)。 List
接口没有指定元素是唯一的。
不过,LinkedHashMap
实现实际上 returns 底层 keySet 是一个 LinkedKeySet
,而 LinkedKeySet
的 forEach()
方法是 order-保留,即:
//from the source code for the LinkedHashMap:
public Set<K> keySet() {
Set<K> ks;
return (ks = keySet) == null ? (keySet = new LinkedKeySet()) : ks;
}
因此,在这种情况下,元素既是唯一的又是有序的。
"why doesn't the source code of LinkedHashMap
return an Object
of type Set
that guarantees order like LinkedHashSet
?"
因为 LinkedHashSet
是一个具体的 class,它自己的实现维护自己的数据,并且 keyset()
方法必须 return Map
,所以它不能只将关键数据复制到LinkedHashSet
。请参阅 javadoc:
Returns a Set
view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
if it guarantees order then why doesn't the source code of LinkedHashMap return an Object of type Set that guarantees order like LinkedHashSet?
声明的键集类型取自Map.keySet()
声明的类型。 LinkedHashMap
在协变 [=54=] 类型被添加到 Java 语言之前被添加到标准库中。那时,除了使用类型 Set
.
别无选择
在任何情况下,仅因为键集必须与底层映射具有相同的顺序并不意味着它必须是 LinkedHashSet
,事实上它不能,因为它不能支持元素添加。它的 class 是 class LinkedHashMap
的私有嵌套 class。在 class 和 Set
之间没有 public 类型比 Set
作为 return 类型更有用。
的确,我认为定义一个并不容易。将它与任何其他集合区分开来的基本特征是什么?您不能只说 "iteration order" 而不指定 什么 迭代顺序实例,并且该顺序取决于从中获取集合的 LinkedHashMap
实例。换句话说,迭代顺序是实例特征,而不是 class 特征。因此,表达作为 LinkedHashMap
键集性质的声明类型几乎不会提供任何超出 Set
提供的实际用途的信息。
无论如何,我认为您引用的关于 returning a List
vs a Collection
的摘录非常有说服力。事实上,关于对象的特定 class 的歧义本身并不是问题。在 Collection
与 List
示例中,如果类型 Collection
很好地捕获了方法的 return 类型要求,那么没有特别的原因表明一个 List
是必需的,那么 Collection
是一个很好的选择 return 类型。如果 Set
也可以满足要求,那就特别好,因为这样 API 就不会在两个同样好的备选方案之间做出本质上任意的选择。
有一种观点认为,方法的参数类型应尽可能通用,return 类型应尽可能具体。我认为这个想法有很多优点,但它更像是一个指南而不是规则,并且对于 "as specific as possible" 的具体程度有很大的解释空间。
我已阅读 java 文档以及此 post 中,LinkedHashMaps 的 keyset()
维持秩序。
Is the order guaranteed for the return of keys and values from a LinkedHashMap object?
我的问题是,如果它保证顺序那么为什么 LinkedHashMap
return 的源代码不是 Set
类型的对象来保证顺序 LinkedHashSet
?
我可能想到的一个原因是 LinkedHashSet 使用一个会增加内存分配的映射(取决于 AbstractSet 的实现方式)。是否也是因为它未来证明了键集的实现?
就像这个 post 中的回答所说:Is it better to use List or Collection?
Returning a List is in line with programming to the Highest Suitable Interface.
Returning a Collection would cause ambiguity to the user, as a returned collection could be either: Set, List or Queue.
那么,不看keyset()
的文档,这不是模棱两可吗?
keyset()
源代码:
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
private final class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
}
它 returns 一个 Set
由 Map
接口定义。 Set
只是不包含重复元素的集合。另一方面,List
是有序集合(也称为序列)。 List
接口没有指定元素是唯一的。
不过,LinkedHashMap
实现实际上 returns 底层 keySet 是一个 LinkedKeySet
,而 LinkedKeySet
的 forEach()
方法是 order-保留,即:
//from the source code for the LinkedHashMap:
public Set<K> keySet() {
Set<K> ks;
return (ks = keySet) == null ? (keySet = new LinkedKeySet()) : ks;
}
因此,在这种情况下,元素既是唯一的又是有序的。
"why doesn't the source code of LinkedHashMap
return an Object
of type Set
that guarantees order like LinkedHashSet
?"
因为 LinkedHashSet
是一个具体的 class,它自己的实现维护自己的数据,并且 keyset()
方法必须 return Map
,所以它不能只将关键数据复制到LinkedHashSet
。请参阅 javadoc:
Returns a
Set
view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
if it guarantees order then why doesn't the source code of LinkedHashMap return an Object of type Set that guarantees order like LinkedHashSet?
声明的键集类型取自Map.keySet()
声明的类型。 LinkedHashMap
在协变 [=54=] 类型被添加到 Java 语言之前被添加到标准库中。那时,除了使用类型 Set
.
在任何情况下,仅因为键集必须与底层映射具有相同的顺序并不意味着它必须是 LinkedHashSet
,事实上它不能,因为它不能支持元素添加。它的 class 是 class LinkedHashMap
的私有嵌套 class。在 class 和 Set
之间没有 public 类型比 Set
作为 return 类型更有用。
的确,我认为定义一个并不容易。将它与任何其他集合区分开来的基本特征是什么?您不能只说 "iteration order" 而不指定 什么 迭代顺序实例,并且该顺序取决于从中获取集合的 LinkedHashMap
实例。换句话说,迭代顺序是实例特征,而不是 class 特征。因此,表达作为 LinkedHashMap
键集性质的声明类型几乎不会提供任何超出 Set
提供的实际用途的信息。
无论如何,我认为您引用的关于 returning a List
vs a Collection
的摘录非常有说服力。事实上,关于对象的特定 class 的歧义本身并不是问题。在 Collection
与 List
示例中,如果类型 Collection
很好地捕获了方法的 return 类型要求,那么没有特别的原因表明一个 List
是必需的,那么 Collection
是一个很好的选择 return 类型。如果 Set
也可以满足要求,那就特别好,因为这样 API 就不会在两个同样好的备选方案之间做出本质上任意的选择。
有一种观点认为,方法的参数类型应尽可能通用,return 类型应尽可能具体。我认为这个想法有很多优点,但它更像是一个指南而不是规则,并且对于 "as specific as possible" 的具体程度有很大的解释空间。