Sorting Linkedhashmap

Sorting LinkedHashMap

This is now quite a bit easier with Java 8 streams: you don't need the intermediate map to sort:

map.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.forEach(entry -> ... );

Sorting LinkedHashMap by value

How can you sort a LinkedHashMap using the value?

LinkedHashMap is not sorted, it is ordered by order of insertion.

If your goal is to reorder the Map, you might do something like

static <K, V> void orderByValue(
LinkedHashMap<K, V> m, final Comparator<? super V> c) {
List<Map.Entry<K, V>> entries = new ArrayList<>(m.entrySet());

Collections.sort(entries, new Comparator<Map.Entry<K, V>>() {
@Override
public int compare(Map.Entry<K, V> lhs, Map.Entry<K, V> rhs) {
return c.compare(lhs.getValue(), rhs.getValue());
}
});

m.clear();
for(Map.Entry<K, V> e : entries) {
m.put(e.getKey(), e.getValue());
}
}

We put all the entries in a List, sort the List, then put the entries back in the Map in the new order.

Here's a Java 8 translation for those inclined:

static <K, V> void orderByValue(
LinkedHashMap<K, V> m, Comparator<? super V> c) {
List<Map.Entry<K, V>> entries = new ArrayList<>(m.entrySet());
m.clear();
entries.stream()
.sorted(Comparator.comparing(Map.Entry::getValue, c))
.forEachOrdered(e -> m.put(e.getKey(), e.getValue()));
}

(Which, out of curiosity, can be condensed to, although it is less efficient):

static <K, V> void orderByValue(
LinkedHashMap<K, V> m, Comparator<? super V> c) {
new ArrayList<>(m.keySet()).stream()
.sorted(Comparator.comparing(m::get, c))
.forEachOrdered(k -> m.put(k, m.remove(k)));
}

Is there a way to insert entries into a LinkedHashMap so that they are inserted in order based on their value?

No. See above. LinkedHashMap is not sorted.

If your goal is to keep the Map sorted, you need to use a TreeMap; however there are problems with doing so. Entries in the Map need to have unique values. See here and here.

Sorting LinkedHashMap by key java

A LinkedHashMaP is ordered based on the insertion order. If you want that the natural order of a LinkedHashMap reflects a sort criteria of some objects, then you first have to establish that order on these objects, before then adding the objects in that order to a fresh LinkedHashMap instance.

In other words: you can't change the order on an existing LinkedHashMap - because the order was fixed when you added the elements to that map initially! Or to be precise: you could only do that by extending the LinkedHashMap class and changing its behavior to break its contract. But that doesn't make sense. You are simply using the wrong data structure to implement your requirement.

If you want a Map that re-orders based on a sorting criteria, you should be looking into a TreeMap for example!

Long story short: you have to differentiate between "order based on insertion order" and "order as result of sorting criteria". You want the later, and LinkedHashMap is the wrong kind of map for that.

Sorting a LinkedHashMap in Java

I think your code some should works. i write code like you and it works, here is my code

public static void main(String[] args) {
Map<Integer, Float> unsortFloatMap = new HashMap<Integer, Float>();
unsortFloatMap.put(1985, 0.54660827f);
unsortFloatMap.put(2002, 0.45290402f);
unsortFloatMap.put(1993, 0.40605184f);
unsortFloatMap.put(2015, 0.3591997f);

unsortFloatMap.put(1975, 0.0f);
unsortFloatMap.put(1997, 0.031234723f);
unsortFloatMap.put(2004, 0.046852008f);
unsortFloatMap.put(2005, 0.1093216f);
unsortFloatMap.put(2003, 0.29673007f);
unsortFloatMap.put(1998, 0.29673007f);
unsortFloatMap.put(2007, 0.31234753f);
unsortFloatMap.put(1995, 0.73401666f);

System.out.println("Unsort Float Map......");
printMap(unsortFloatMap);

System.out.println("Sorted Float Map......");
Map<Integer, Float> sortedFloatMap = sortByFloatValue(unsortFloatMap);
printMap(sortedFloatMap);
}

// pretty print a map
public static <K, V> void printMap(Map<K, V> map) {
for (Map.Entry<K, V> entry : map.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
}
}

private static Map<Integer, Float> sortByFloatValue(Map<Integer, Float> unsortMap) {
List<Map.Entry<Integer, Float>> list = new LinkedList<Map.Entry<Integer, Float>>(unsortMap.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Integer, Float>>() {
public int compare(Map.Entry<Integer, Float> o1, Map.Entry<Integer, Float> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
});

/// Loop the sorted list and put it into a new insertion order Map
/// LinkedHashMap
Map<Integer, Float> sortedMap = new LinkedHashMap<Integer, Float>();
for (Map.Entry<Integer, Float> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}

return sortedMap;
}

Output is:

Unsort Float Map......
Key : 2002 Value : 0.45290402
Key : 2003 Value : 0.29673007
Key : 1985 Value : 0.54660827
Key : 1975 Value : 0.0
Key : 2007 Value : 0.31234753
Key : 2004 Value : 0.046852008
Key : 2005 Value : 0.1093216
Key : 1995 Value : 0.73401666
Key : 1993 Value : 0.40605184
Key : 1998 Value : 0.29673007
Key : 2015 Value : 0.3591997
Key : 1997 Value : 0.031234723
Sorted Float Map......
Key : 1975 Value : 0.0
Key : 1997 Value : 0.031234723
Key : 2004 Value : 0.046852008
Key : 2005 Value : 0.1093216
Key : 2003 Value : 0.29673007
Key : 1998 Value : 0.29673007
Key : 2007 Value : 0.31234753
Key : 2015 Value : 0.3591997
Key : 1993 Value : 0.40605184

Sorting LinkedHashMapString, ArrayListString by counting the occurrences in ArrayListString problem

The following solution is based on using Stream API

  1. Count the frequencies of elements from miss in each list value of maps and collect the frequency into some object (e.g. a list)
  2. Sort the new object by the frequency in the reverse order and then by the key of initial map (note: the key may need to be converted into int to provide the expected output: 1, 4, 11; comparing the keys as String returns the order 1, 11, 4)
  3. Build the resulting map using Collectors.toMap with LinkedHashMap::new supplier
List<String> miss = List.of("3", "7");
Map<String, List<String>> maps = Map.of(
"1", List.of("0", "3", "6"),
"4", List.of("2", "3", "4"),
"6", List.of("0", "3", "7"),
"11", List.of("1", "3", "6"),
"17", List.of("2", "6", "11")
);

Map<String, List<String>> sorted = maps.entrySet()
.stream()
.map(e -> Arrays.asList(e,
e.getValue().stream()
.mapToInt(i -> (int) miss.stream().filter(i::equals).count())
.sum()
))
.sorted(Comparator
.<List>comparingInt(ee -> (int) ee.get(1)).reversed()
.thenComparingInt(ee -> Integer.parseInt(((Map.Entry<String, List<String>>) ee.get(0)).getKey()))
)
.map(ee -> (Map.Entry<String, List<String>>) ee.get(0))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(v1, v2) -> v1,
LinkedHashMap::new
));

System.out.println(sorted);

Output:

{6=[0, 3, 7], 1=[0, 3, 6], 4=[2, 3, 4], 11=[1, 3, 6], 17=[2, 6, 11]}

Sort LinkedHashMap with LinkedListInteger as key

The simple fix: You said that you wanted sorting by the first (0th) element of the list. So specify that:

    hm.entrySet()
.stream()
.sorted(Comparator.comparing(me -> me.getKey().get(0)))
.forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));

With this sorting let’s try writing out the sorted map afterwards, for example:

    sortedMap.forEach((k, v) -> System.out.println("" + k + " -> " + Arrays.toString(v)));
[0, 41] -> [10.3, 50.05, 9.9]
[10, 7] -> [0.14, 1.2, 85.01]
[210, 3] -> [17.0, 4.0, 2.1]

If you didn’t want to create a new map, you must remove each key before inserting it again for the order to be changed:

    hm.entrySet()
.stream()
.sorted(Comparator.comparing(me -> me.getKey().get(0)))
.forEachOrdered(x -> {
hm.remove(x.getKey());
hm.put(x.getKey(), x.getValue());
});

hm.forEach((k, v) -> System.out.println("" + k + " -> " + Arrays.toString(v)));

Now the output is the same as above.

How to sort a LinkedHashMap by value in decreasing order in java stream?

To sort in reverse order, pass Comparator.reverseOrder() as parameter to comparingByValue.

To get a LinkedHashMap, you must specifically request one with the 4-argument toMap(). If you don't specify what kind of a map you want, you will get whatever the default is, which currently happens to be a HashMap. Since HashMap doesn't preserve the order of elements, it will definitely not do for you.

myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(x,y)-> {throw new AssertionError();},
LinkedHashMap::new
));

With static imports, it becomes a bit more pleasant:

myMap.entrySet().stream()
.sorted(comparingByValue(reverseOrder()))
.collect(toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(x,y)-> {throw new AssertionError();},
LinkedHashMap::new
));

Why LinkedHashMap can't sort HashMap while TreeMap can?

LinkedHashMap maintains the insertion order. This means that if you pass to the constructor a sorted Map, or put the keys in the LinkedHashMap in sorted order, it will remain sorted.

However, you pass a HashMap to the LinkedHashMap constructor, and it's not sorted (since HashMap has no ordering). Therefore the resulting LinkedHashMap is also not ordered.

On the other hand, TreeMap keeps the keys sorted, so the order in which you put the keys in the TreeMap (which in your example is determined by the order the keys are encountered while iterating over the source HashMap) doesn't matter - the resulting Map will always be sorted.



Related Topics



Leave a reply



Submit