是否可以保证从LinkedHashMap对象返回键和值的顺序?


162

我知道LinkedHashMap有一个可预测的迭代顺序(插入顺序)。是否Set通过返回LinkedHashMap.keySet()Collection返回的LinkedHashMap.values()也维持这种秩序?


1
由于所有答案都解决了values()以及的问题keySet(),因此我将问题扩展为包括该问题。这意味着可以关闭更多问题作为重复项。
邓肯·琼斯

Answers:


226

Map界面提供了三个 集合视图,这些视图允许将地图的内容视为一组键,值的集合或一组键-值映射。该订单的地图被定义为其中在地图上的集合视图迭代返回元素的顺序。某些地图实现(例如TreeMap 类)会对其顺序做出具体保证;其他人,例如 HashMap上课者,则不会。

- 地图

此链表定义了迭代顺序,通常是将键插入映射的顺序insert-order)。

- LinkedHashMap的

所以,是的,keySet()values(),和entrySet()顺序(三组收集的意见中提到)返回值的内部链接列表的用途。是的,JavaDoc支持MapLinkedHashMap保证它。

毕竟,这就是本课的重点。


8
使用LinkedHashMap比使用HashMap更快地完成地图上的迭代。
蒂埃里

2
values()返回一个集合。不是列表。如何保持秩序?
Dejell 2014年

7
@Dejel Collection只是values()返回的基类。它返回的Collection的实现仍由LinkedHashMap。在LinkedHashMap这种情况下,它将返回一个LinkedValues实例,即LinkedHashMap.java中的私有类。
Powerlord 2014年

2
在我的情况下,LinkedHashMap的键集不是按映射中表示的顺序。对此感到非常困惑。
Amalgovinus

2
感谢您链接到文档(来自Map),该文档明确将地图的顺序与地图集合视图上的迭代器联系在一起(并弄清楚这些集合视图是什么)。那是我所缺少的。
LarsH


6

不要混淆LinkedHashMap.keySet()LinkedHashMap.entrySet()返回Set,因此它不保证订购!

Set是一个接口HashSetTreeSet等众生它的实现。接口的HashSet实现Set不能保证排序。但是TreeSet可以。也LinkedHashSet可以。

因此,取决于如何Set实现LinkedHashMap才能知道返回的Set引用是否可以保证排序。我查看了的源代码LinkedHashMap,它看起来像这样:

private final class KeySet extends AbstractSet<K> {...}
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {...}

因此,LinkedHashMap / HashMap具有自己的Setie 实现KeySet。因此,请勿将此与混淆HashSet

同样,通过将元素插入存储桶的方式来保持顺序。看一下的addEntry(..)方法LinkedHashMap并将其与之比较,以HashMap突出显示HashMap和之间的主要区别LinkedHashMap


4
尽管此答案肯定会提供有用的信息,但并不能真正回答问题。基本上是说它们可以具有可预测的迭代顺序。
Tuupertunut

5

您可以这样假设。Javadoc说“可预测的迭代顺序”,并且Map 唯一可用的迭代器 keySet(),entrySet()和values()的迭代器。

因此,在没有任何进一步限定的情况下,显然打算将其应用于所有这些迭代器。


0

AFAIK没有记录,因此您不能“正式”假设如此。但是,当前的实施方式不太可能会改变。

如果您想确保顺序,则可能要遍历整个地图,然后将其插入具有所选顺序功能的排序集中,尽管您自然会支付性能费用。


您是说entrySet()通过keySet()保证顺序吗?
user256239 2010年

1
@kknight:我不确定。javadoc指出:“此链表定义了迭代顺序,通常是将键插入映射的顺序(插入顺序)。” 但是,JDK的JavaDocs通常非常模棱两可。
乌里(Uri)2010年

5
如果甚至entrySet()也不能保证迭代顺序,那么LinkedHashMap和HashMap有什么区别?我们如何在LinkedHashMap实例中利用可预测的迭代顺序?
user256239 2010年

1
它肯定是有记录的。答案是完全错误的。
罗恩侯爵,

-3

查看接口,它返回一个普通Set而不是一个SortedSet。因此,没有任何保证。

在通过查看实现来假定隐式保证之前(总是一个坏主意),还要查看所有其他Java实现中的实现:)

例如,您最好在构造函数中使用keySet创建一个TreeSet。


3
仔细阅读文档,确实可以保证。正如某人已经写过的,这就是本课的重点。
glglgl

-4

我认为您不能假定keySet()和values()的顺序。

我可以轻松地编写LinkedHashMap的实现,只要我坚持Map中定义和在HashMap中覆盖的这两个方法的协定,该实现将返回无序的keySet()和values()。


6
LinkedHashMap该类的全部目的是在迭代地图时保留元素的顺序,并且对此行为进行了详细说明。如果编写子类而不遵守基类规范,那么您所做的事情就非常错误。
zakinster 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.