我已经阅读过java文档,并且在这篇文章中也看过LinkedHashMaps' keyset()
维持秩序。
Is the order guaranteed for the return of keys and values from a LinkedHashMap object?
我的问题是,如果它保证了订单,那么为什么LinkedHashMap
的源代码不会返回类型为Set
的对象,以保证LinkedHashSet
之类的顺序?
我可以想到的一个原因是LinkedHashSet使用了一个可以增加内存分配的映射(取决于AbstractSet的实现方式)。是不是因为它的未来证明了keyset的实现?
就像这篇文章中的答案一样:Is it better to use List or Collection?
返回列表符合最高适合的编程 接口
返回集合会导致用户不明确,因为a 返回的集合可以是:Set,List或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();
}
}
答案 0 :(得分:5)
“为什么LinkedHashMap
的源代码不会返回Object
Set
类LinkedHashSet
来保证LinkedHashSet
之类的订单?” < / p>
因为Map
是一个具体类,它自己的实现维护自己的数据,keyset()
方法必须返回LinkedHashSet
的视图,所以它不能只复制关键数据到Set
。见javadoc:
返回此地图中包含的键的{{1}}视图。 集由地图支持,因此对地图的更改会反映在集合中,反之亦然。
答案 1 :(得分:2)
它返回<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css" rel="stylesheet"/>
<div class="row">
<div class="featuresanimate">
<div id="features" class="section scrollspy">
<div class="container">
<h2 style="text-decoration:underline;text-align:center;font-weight:bold;font-family:Comic Sans MS">Features</h2>
<div class="features">
<div class="col s6">
<img src="http://placehold.it/100x100" height="100" width="100">
<div class="feature-set">
<h3>One</h3>
<ul>
<li>profile</li>
<li>profile</li>
<li>profile</li>
<li>profile</li>
</ul>
</div>
</div>
<div class="col s6">
<img src="http://placehold.it/100x100" height="100" width="100">
<div class="feature-set">
<h3>Two</h3>
<ul>
<li>profile</li>
<li>profile</li>
<li>profile</li>
<li>profile</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
接口定义的...
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<div class="grid_12 exhibition-views">
<div class="navigation">
<div class="previous">
<?php
_e("[:en]".previous_image_link(0,'Previous')."[:de]".previous_image_link(0,'Zurück')."[:]");
?>
</div>
<div class="next">
<?php
_e("[:en]".next_image_link(0,'Next')."[:de]".next_image_link(0,'Weiter')."[:]");
?>
</div>
</div>
<?php echo wp_get_attachment_image( $post->ID, 'large' ); ?>
<!-- <div class="caption">< ?php if ( !empty($post->post_excerpt) ) the_excerpt(); ? ></div> -->
</div>
<?php endwhile; ?>
...
。 Set
只是一个不包含重复元素的集合。另一方面,Map
是有序集合(也称为序列)。 Set
接口未指定元素是唯一的。
但是,List
实现实际上返回了List
的基础keySet,LinkedHashMap
的{{1}}方法是保持顺序的,即:
LinkedKeySet
因此,在这种情况下,元素既是唯一的又是有序的。
答案 2 :(得分:1)
如果它保证顺序那么为什么LinkedHashMap的源代码不返回类型为Set的Object,它保证了LinkedHashSet这样的顺序?
密钥集的声明类型是从Map.keySet()
声明的那个中提取的。在将协变返回类型添加到Java语言之前,LinkedHashMap
已添加到标准库中。那时,除了使用类型Set
之外别无选择。
无论如何,仅仅因为键集必须与底层映射具有相同的顺序并不意味着它必须是LinkedHashSet
,实际上它不能,因为它不能支持元素添加。它的类是类LinkedHashMap
的私有嵌套类。该类与Set
之间没有公共类型作为返回类型比Set
更有用。
实际上,我认为定义一个并不容易。将它与任何其他集合区分开来的基本特征是什么?您不能仅仅指定“迭代顺序”而不指定迭代顺序实例将具有哪些,并且该顺序取决于从中获取集合的LinkedHashMap
实例。换句话说,迭代顺序是实例特征,而不是类特征。因此,表示作为LinkedHashMap
的关键集的性质的声明类型几乎不会提供除Set
之外的任何实际用途的信息。
无论如何,我没有找到你引用的关于返回List
与Collection
的摘录非常有说服力的摘录。事实是,关于对象特定类的模糊性本身并不是问题。在Collection
与List
示例中,如果类型Collection
很好地捕获了方法的返回类型要求,那么{{1}的特征特征没有特别的原因需要,然后List
是返回类型的一个很好的选择。如果Collection
也能满足要求,那就特别好了,因为API并没有在两个同样好的选择之间做出基本上任意的选择。
有一种思想流派认为方法应该在其参数类型中尽可能通用,并且在返回类型中尽可能具体。我认为这个想法有很多优点,但它更多的是指导而不是规则,并且对于具体的“尽可能具体”具有相当大的解释空间。