从LinkedHashMap的keySet()创建的ArrayList是否保留了插入顺序?

时间:2015-09-29 19:51:12

标签: java linkedhashmap

我得到类似

的数据
  

{“ABC的员工1”,“ABCX”},{“ABC的员工2”,“ABCY”},   {“ABC的员工3”,“ABCZ”}

从数据库到RefCursor

我有一个案例需要保留从数据库中读取数据的顺序。 由于我的数据是一种“键值”,我想到了使用了Map的实现,它是有序的。因此选择LinkedHashMap

//defined as a static map inside a common utlity class
public class Common{
public static final LinkedHashMap<String, String> empMap = new   LinkedHashMap<String, String>();
}

//rs is the resultset
if (rs != null) {
            while (rs.next()) {
                key = rs.getString("name_text");
                value = rs.getString("id");
                Common.empMap.put(key, value);
            }
}

我必须按照从数据库(光标)检索它的顺序将密钥传递给客户端。

List<String> empList = new ArrayList<String>(Common.empMap.keySet());
  

keySet() - 文档说“返回键的Set视图   包含在这张地图中。该集由地图支持,因此更改为   地图反映在集合中,反之亦然“

我期望的是,由于ArrayList也是一个有序集合,我应该以与检索/插入Map相同的方式获取密钥。

当我做一个示例测试程序时,我得到了预期的结果。

public class LinkedMap {    
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();        
        map.put("Employee 1 of ABC", "ABCX");
        map.put("Employee 2 of ABC", "ABCY");
        map.put("Employee 3 of ABC", "ABCZ");   
        ArrayList<String> list = new ArrayList<String>(map.keySet());   
        System.out.println(list);   
    }
}
  

输出:[ABC的员工1,ABC的员工2,ABC的员工3]

然而我的问题是,如果这是保证输出,或者我是随机获得的,它可能会有所不同(?),

更新:2015年9月30日

谢谢大家,你们每个人都提供了有效的分数。

总结所有答案,

保证订单得以维持。

根据Javadocs

  

LinkedHashMap是Map的Hash表和链表实现   接口,具有可预测的迭代顺序。这个实现   与HashMap的不同之处在于它维护着一个运行的双向链表   通过它的所有条目。此链接列表定义迭代   排序,通常是插入密钥的顺序   地图(插入顺序)

ie: LinkedHashMap将按照条目放入地图的顺序进行迭代

所以LinkedHashMap#keySet()会给我一个将键插入地图的顺序,因为 LinkedHashMap#keySet().iterator()按指定顺序迭代。

深入了解iterator()的实施,我们可以看到,

LinkedHashMap实现newKeyIterator()方法,该方法返回继承LinkedHashIterator的类的实例,负责“排序”

// These Overrides alter the behavior of superclass view iterator() methods
Iterator<K> newKeyIterator()   { return new KeyIterator();   } ...  

private class KeyIterator extends LinkedHashIterator<K> {...

private abstract class LinkedHashIterator<T> implements Iterator<T> { ...

为此:ArrayList<String> list = new ArrayList<String>(map.keySet());  构造函数 ArrayList(Collection)documented,以按指定Collection的迭代器返回元素的顺序填充列表。

6 个答案:

答案 0 :(得分:4)

保证。

即使Set接口本身并不保证任何顺序(好吧,LinkedHashSet也这样做),Map实现本身保证插入排序的事实几乎可以保证您也将按此顺序获得密钥。 .keySet()返回的界面恰好是Set,因为Map中的密钥保证是唯一的。

如果不是,请考虑在这种情况下会发生什么:

// case 1
for (final Map.Entry<K, V> entry: map.entrySet()) {
    // entry.getKey(), entry.getValue()
}

// case 2
for (final K key: map.keySet()) {
    V value = map.get(key);
}

如果这两个代码有两种不同的行为,呃......

答案 1 :(得分:2)

是的,这是有保证的。

在Oracle JDK中,类LinkedHashMap重新实现方法newKeyIterator(),该方法返回继承LinkedHashIterator的类的实例。那是订购的。

答案 2 :(得分:1)

其他答案解释LinkedHashMap#keySet().iterator()按指定顺序迭代,所以让我添加:

ArrayList Javadoc说ArrayList(Collection)

  

按照集合迭代器返回的顺序构造一个包含指定集合元素的列表。

因此可以保证ArrayList项目的顺序相同。

答案 3 :(得分:1)

保证LinkedHashSet的迭代顺序与插入键的顺序相同(假设您不使用允许您通过最近访问请求排序的特殊构造函数)。您可以在its documentation

中找到

我想你可以说迭代订单保证仅适用于条目集,而不适用于其他视图,但是文档不能很好地支持(因为它们指的是 迭代顺序),实际上集合视图确实共享一个共同的迭代顺序。

就其本身而言,构造函数ArrayList(Collection) is documented按照指定的Collection迭代器返回元素的顺序填充列表。

答案 4 :(得分:1)

正如此问题Does entrySet() in a LinkedHashMap also guarantee order?中所述并在JavaDocs中注明,迭代类型操作被定义为LinkedHashMap的插入顺序。这会影响keySetentrySet

ArrayList的构造函数将以迭代器的顺序插入List

这两个条件相结合,意味着API保证了这种行为。

答案 5 :(得分:0)

谢谢大家,你们每个人都贡献了有效的积分。

要总结所有答案,

保证订单得到维护。

根据Javadocs

  

LinkedHashMap是Map的哈希表和链接列表实现   界面,具有可预测的迭代顺序。这个实现   与HashMap的不同之处在于,它维护正在运行的双向链接列表   通过其所有条目。此链表定义了迭代   排序,通常是将密钥插入的顺序   地图(插入顺序)

ie: LinkedHashMap将按照将条目放入地图的顺序进行迭代

因此LinkedHashMap#keySet()将为我提供将键插入地图的顺序,因为 LinkedHashMap#keySet().iterator()按指定顺序进行迭代。

深入研究iterator()的实现,

LinkedHashMap实现了newKeyIterator()方法,该方法返回继承LinkedHashIterator的类的实例,并照顾“顺序”

// These Overrides alter the behavior of superclass view iterator() methods
Iterator<K> newKeyIterator()   { return new KeyIterator();   } ...  

private class KeyIterator extends LinkedHashIterator<K> {...

private abstract class LinkedHashIterator<T> implements Iterator<T> { ...

为此:ArrayList<String> list = new ArrayList<String>(map.keySet());  构造函数 ArrayList(Collection)documented,以按指定Collection的迭代器返回元素的顺序填充列表。