Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does an ArrayList created from the keySet() of LinkedHashMap preserves the order of insertion?

I get data something like

{"Employee 1 of ABC", "ABCX"}, {"Employee 2 of ABC", "ABCY"}, {"Employee 3 of ABC", "ABCZ"}

from database through a RefCursor.

I have a case where I need to preserve the order in which data is read from the database. Since my data is kind of 'key-value' ,I thought of using a implementation of Map which is ordered. Hence chose 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);
            }
}

I have to pass the keys to the client, in the same order in which it was retrieved from the database (Cursor).

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

keySet() - The documentation says "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"

What I expect is that Since ArrayList is also an ordered collection, I should get the keys in the same way in which it was retrieved/inserted into the Map.

When I do a sample test program, I am getting as expected.

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);   
    }
}

output: [Employee 1 of ABC, Employee 2 of ABC, Employee 3 of ABC]

However my question is , if this is guaranteed output or is it that I am getting just randomly, and it might vary(?),

  • update 09/14/2019

I am separating the answer from the question to avoid any confusion.

like image 869
spiderman Avatar asked Sep 29 '15 19:09

spiderman


2 Answers

It is guaranteed.

Even though the Set interface in itself doesn't guarantee any order (well, LinkedHashSet does), the fact that the Map implementation itself guarantees insertion ordering pretty much guarantees that you will get the keys in this order as well. The interface returned by .keySet() just happens to be a Set since, well, keys in a Map are guaranteed to be unique.

If it weren't, consider what would happen in this situation:

// 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);
}

If these two codes had two different behaviors, uh...

like image 54
fge Avatar answered Nov 14 '22 21:11

fge


Yes, it is guaranteed.

In the Oracle JDK, the class LinkedHashMap reimplements the method newKeyIterator() which returns an instance of a class inheriting LinkedHashIterator. That one is ordered.

like image 28
nrainer Avatar answered Nov 14 '22 21:11

nrainer