15

I need to call an external API with an ArrayList of HashMaps holding several predefined key-value pairs each. An example:

ArrayList<HashMap<String, String>> arrayListHashMap = new ArrayList<HashMap<String, String>>();

    {
        HashMap hashMap = new HashMap<String, String>();
        hashMap.put("key", "A key");
        hashMap.put("value", "B value");
        arrayListHashMap.add(hashMap);
    }

    {
        HashMap hashMap = new HashMap<String, String>();
        hashMap.put("key", "B key");
        hashMap.put("value", "A value");
        arrayListHashMap.add(hashMap);
    }

Now I need to sort this construct on the contents of the "value" key. This sort would result in the "key=B key/value=A value" entry as the first one in the arrayListHashMap.

Any help is highly appreciated.

HJW

Harald Wilhelm
  • 6,656
  • 11
  • 67
  • 85

3 Answers3

41

You need to implement a Comparator<HashMap<String, String>> or more generally Comparator<Map<String, String>> which just extracts the value assocated with the value key, then use Collections.sort. Sample code (with generalization for whatever key you want to sort on):

class MapComparator implements Comparator<Map<String, String>>
{
    private final String key;

    public MapComparator(String key)
    {
        this.key = key;
    }

    public int compare(Map<String, String> first,
                       Map<String, String> second)
    {
        // TODO: Null checking, both for maps and values
        String firstValue = first.get(key);
        String secondValue = second.get(key);
        return firstValue.compareTo(secondValue);
    }
}

...
Collections.sort(arrayListHashMap, new MapComparator("value"));
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thank you very much for your fast answer. – Harald Wilhelm Mar 20 '11 at 16:49
  • Hello, What if I want to sort on some custom criteria? Like I have one value say TEST and I wish to sort a list such a way that all the value which is TEST comes first and then all other. So basically if i have list of size let say 10 and in that if it contains TEST value 2 times at position 5 & 8 then I want both of them on top. And other values will be after that..Can you please tell me how to do so.. – Scorpion Nov 07 '12 at 07:38
  • @Scorpion: Then you write a comparator which checks for TEST and always treats that as earlier than any other value. Which bit of that are you finding difficult? (This would probably be best as a new question...) – Jon Skeet Nov 07 '12 at 07:46
  • 1
    @JonSkeet Hi, I'm stuck in similar situation and I'm doing whatever you have suggested but still I'm getting "The method sort(List, Comparator super T>) in the type Collections is not applicable for the arguments (ArrayList, MapComparator)" Any idea how to resolve this? – shubham gupta Dec 17 '15 at 09:27
  • @shubhamgupta: Without seeing the exact code, it's hard to know. I suggest you ask a new question with a short but complete example demonstrating the problem. – Jon Skeet Dec 17 '15 at 09:50
1

You can use the below solution to achieve it:

arrayListHashMap.sort(Comparator.comparing(m -> m.get("value"), Comparator.nullsLast(Comparator.naturalOrder())));
Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
Bala
  • 11
  • 1
0

(This is not an answer to the asked question - Jon did this already -, but the comment field is too small for this.)

Your data structure looks like you misunderstood the key-value structure of maps (and Hash maps in your example).

A Map can contain any number of keys, and for each key also a value. A pair of key and value is given by a Map.Entry (which can be obtained by the entrySet() method of the map). If you then want to sort by key, simply use a SortedMap (like TreeMap) instead of the usual HashMap.

You are emulating the individual entries by a HashMap each, then putting them all in a ArrayList ... :-/

Here what I would have done in your example:

Map<String, String> map = new TreeMap<String, String>();
map.put("B key", "B value");
map.put("A key", "B value");

System.out.println(map); // already sorted
Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
  • 1
    Thanks for your answer. I need to feed the external API - the idea is not mine. What I do understand is that they simulate something like a database query result. The ArrayList is the query result, every HashMap is a record and every entry is a fieldname and it's value. "key" would be one field and "value" another. Seems that I should've used different names for the two entries in the example. Just take "field1" and "field2" instead of "key" and "value". Sorry for the confusion. – Harald Wilhelm Mar 20 '11 at 16:47
  • The external API should in fact be using a list of javabeans. – BalusC Mar 20 '11 at 16:49