2

I found strange behaviour of (iterator?) ConcurrentLinkedHashMap. Elements obtained by iterating entrySet/keySet are in strange/unexpected order if key is long. Everything is ok if key is short.

Following code:

    public static void main(String[] args) {
    ConcurrentLinkedHashMap<String, String> map =
            new ConcurrentLinkedHashMap.Builder<String, String>().maximumWeightedCapacity(1000).build();
    for (int i = 0; i < 5; i++) {
        map.put(i + "", i + "");
    }
    print(map);
    map.clear(); 
    // NOW AGAIN THE SAME, BUT WITH LONG KEY
    for (int i = 0; i < 5; i++) {
        map.put(i + "aaaaaaaaaaaaaaaaaaaaaaaaaa" +
                "aaaaaaaaaaaaaaaaaaaaaaaaaa" +
                "aaaaaaaaaaaaaaaaaaaaaaaaaa", i + "");
    }
    print(map);
}

private static void print(ConcurrentLinkedHashMap<String, String> a) {
    Iterator iterator = a.entrySet().iterator();
    while (iterator.hasNext()) {
        System.out.println(" = " + iterator.next());
    }
}

provides such output:

 = 0=0
 = 1=1
 = 2=2
 = 3=3
 = 4=4
 = 1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1
 = 4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=4
 = 2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=2
 = 3aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=3
 = 0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=0

That is quite strange. If i make key longer - result is different.

Is it a bug? How could I get correct result? (second 'print' result should be in the same order as first)

littleAlien
  • 721
  • 2
  • 8
  • 20
  • What version of guava are you using? – assylias Jun 04 '15 at 21:56
  • @assylias According to git it has never been a part of Guava, it was just [used as the base](https://github.com/ben-manes/concurrentlinkedhashmap) for `MapMaker` and `CacheBuilder`. – maaartinus Jun 04 '15 at 23:56

1 Answers1

5

Unlike java.util.LinkedHashMap, this class does not provide predictable iteration order. (Javadoc)

The documentation is rather clear on that - so no bug

Concerning the order of entries while iterating over them, ConcurrentLinkedHashMap provides ascending and descending order on retention for keys. This might not always be what you are aiming for, but at least for the given test-scenario returns an ordered output given the code below:

private static void print(ConcurrentLinkedHashMap<String, String> a)
{
    Iterator iterator = a.entrySet().iterator();
    while (iterator.hasNext())
    {
        System.out.println(" = " + iterator.next());
    }
    Iterator<String> iter = a.ascendingKeySet().iterator();
    while (iter.hasNext()) 
    {
        String key = iter.next();
        System.out.println(key + " -> " + a.get(key));
    }
}

Output:

 = 0=0
 = 1=1
 = 2=2
 = 3=3
 = 4=4
0 -> 0
1 -> 1
2 -> 2
3 -> 3
4 -> 4
 = 1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1
 = 4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=4
 = 2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=2
 = 3aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=3
 = 0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=0
0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -> 0
1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -> 1
2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -> 2
3aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -> 3
4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -> 4
Roman Vottner
  • 12,213
  • 5
  • 46
  • 63
  • Well, yes, thanks. Strage why is it called Linked* then. – littleAlien Jun 04 '15 at 22:35
  • @user_x updated my post to include some information regarding `ascendingKeySet` – Roman Vottner Jun 04 '15 at 22:51
  • @user_x The class provides the `access order = true` feature of LinkedHashMap, which is more commonly needed with multi-threading and difficult to scale. An insertion-order concurrent map is relatively trivial in comparison. – Ben Manes Jun 05 '15 at 04:02