Reputation: 3194
I have a TreeMap<Integer, Integer>
instance and I want to reassign the key value mappings in that way that the lowest key is assigned to the lowest value and the highest key to the highest key.
Here is how I do it without streams:
TreeMap<Integer, Integer> map = new TreeMap<>();
map.put(1, 6);
map.put(2, 9);
map.put(4, 2);
map.put(3, 1);
map.put(8, 10);
map.put(5, 10);
ArrayList<Integer> valueList = new ArrayList<Integer>(map.values());
Collections.sort(valueList);
int i = 0;
for (Map.Entry entry : map.entrySet()) {
entry.setValue(valueList.get(i++));
}
System.out.println(map);
output:
{1=1, 2=2, 3=6, 4=9, 5=10, 8=10}
Any hints how to perform such a task utilizing java-8 Stream API are welcome.
Thx
Upvotes: 4
Views: 595
Reputation: 298389
Your approach is not bad. You can shorten it to
PriorityQueue<Integer> q = new PriorityQueue<>(map.values());
map.entrySet().forEach(e -> e.setValue(q.remove()));
I don't think that this task is a good candidate for the Stream API.
Upvotes: 4
Reputation: 44456
I have found out a solution that is fairly easy to read and use:
Iterator<Integer> keyIterator = map.keySet().iterator();
TreeMap<Integer, Integer> newMap = map.values().stream()
.sorted()
.map(value -> new SimpleEntry<>(keyIterator.next(), value))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (l, r) -> l, TreeMap::new));
.. or shorter thanks to @HadiJ:
map.values().stream()
.sorted()
.collect(Collectors.toMap(k -> keyIterator.next(), Function.identity(), (l, r) -> l, TreeMap::new));
... but it has a significant drawback:
I cannot guarantee this will work in parallel since it depends on the result of keyIterator.next()
which is also not checked. Read more at the section Stateless Behaviors. I'd rather not use java-stream in this way.
If I were you, I'd use the advantage of the beauty of iterators:
Iterator<Integer> values = valueList.iterator();
Iterator<Integer> keys = map.keySet().iterator();
TreeMap<Integer, Integer> newMap = new TreeMap<>(); // create a new Map
while (values.hasNext() && keys.hasNext()) { // iterate simultaneously
newMap.put(keys.next(), values.next()); // put the key-value
}
Upvotes: 5