1

In a graph i associate a node to a quantity : quantities could be redundant and nodes can't, so in order to sort according to ascending quantities i put nodes as keys and quantities as values of a LinkedHashMap and sort it as follows :

 LinkedHashMap<Node, Integer> orderedResult = mapNameToSize.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));

But my question is how to get the keys sorted accordingly into a ArrayList?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • To get the keys into an ArrayList: `new ArrayList<>(orderedResult.keySet())` – Andreas May 05 '21 at 22:21
  • i'm afraid keySet won't return the right associated order – Patrick Schulz May 05 '21 at 22:22
  • It returns the keys in the order define by the [`LinkedHashMap`](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html), i.e. in insertion order, which in this case means in value order. – Andreas May 05 '21 at 22:23
  • I don't want the initial insertion order but the order resulting from my sorting code (see above the code) – Patrick Schulz May 05 '21 at 22:26
  • 1
    Yes, the insertion order for the entries in the `orderedResult` map, which is the value order, since you sorted by value before inserting into that map. Do you actually understand what that code is doing, because I already said this?!? – Andreas May 05 '21 at 22:33
  • 1
    How about `results.entrySet().sorted(comparingByValue()).map(Map.Entry::getKey).collect(toList())` – sprinter May 05 '21 at 22:34
  • @sprinter Why would you sort *again*, when the keys have already been sorted by the code in the question? – Andreas May 05 '21 at 22:35
  • @Sprinter pls elaborate into an answer, thanks ! – Patrick Schulz May 05 '21 at 22:36
  • @Andreas he's not sorting again, his way, he sorts and right away add to a list (which is different from my code which returns to a Set)! – Patrick Schulz May 05 '21 at 22:38
  • 1
    I actually meant that this code could replace the current code putting into a `LinkedHashMap`. If all you want is sorted keys then that seems unnecessary. – sprinter May 05 '21 at 22:41
  • I meant, if you already spent the time to create the `orderedResult` map, where the keys are ordered as you wanted, why would you spend time sorting *again*, instead of just taking the already-ordered keys from the `orderedResult` map? I agree, that if you don't need the `orderedResult` map for anything else, then first creating the map then extracting the keys is overkill, and code by sprinter would be better. But if you already have the `orderedResult` map, then sorting again is a waste. – Andreas May 05 '21 at 22:41
  • @Andreas is correct - in your code you sort your key entries by value then collect into a map that preserves insertion order. This will guarantee the keys are in order. However if all you want is the sorted keys then there's no need for map - just create the list directly. – sprinter May 05 '21 at 22:44

2 Answers2

2

If all you want is your keys in order of value then you can replace your code with:

List<Node> sortedNodes = 
    mapNameToSize
    .entrySet()
    .stream()
    .sorted(Map.Entry.comparingByValue())
    .map(Map.Entry::getKey)
    .collect(Collectors.toList())
;
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
sprinter
  • 27,148
  • 6
  • 47
  • 78
  • Note that if mutability is required, null entries may be present, or for some other reason a result of type `ArrayList` is needed where an arbitrary `List` may not, it would be better to collect to an `ArrayList` specifically, as `Collectors.toList` does not guarantee mutability of the resulting list. `.collect(Collectors.toCollection(ArrayList::new))` – M. Justin May 17 '21 at 16:03
0

Using the ArrayList copy constructor with the LinkedHashMap's keySet will return an ArrayList with elements in the same order as the LinkedHashMap's entries:

List<Node> orderedKeys = new ArrayList<>(orderedResult.keySet())

As mentioned in another answer, you could alternatively sort the initial map's entries within a stream and collect its values into a list. This is a good solution if all you want is the values, and don't also need the LinkedHashMap.

However, if you already have an ordered LinkedHashMap and you want to get its keys in the same order as the map, it probably makes more sense to use to use the existing map's key set than to re-sort the source and stream to a list. Additionally, this will work even if there is no corresponding comparison ordering for the LinkedHashMap (e.g. it's ordered according to arbitrary insertion order, whereas the stream approach requires a well-defined comparison operation..

M. Justin
  • 14,487
  • 7
  • 91
  • 130