Reputation: 11
I have this code in which I am overwriting values of Map from an ArrayList.
I want to write this code using Streams and Lambda expression
List<Integer> list = new ArrayList<Integer>(arrayList);
Collections.sort(list, Collections.reverseOrder());
int i = 0;
Iterator<Entry<Integer, Integer>> itr = sortedMap.entrySet().iterator();
while(itr.hasNext()) {
Entry<Integer, Integer> pair = itr.next();
pair.setValue(list.get(i));
++i;
}
Thank You!
Upvotes: 0
Views: 415
Reputation: 298559
Doing literally the same as your original code, i.e. set the values of the existing sortedMap
in descending order, can be achieved as
Iterator<Integer> values = arrayList.stream()
.sorted(Collections.reverseOrder())
.iterator();
sortedMap.replaceAll((key,value) -> values.next());
This assumes that the list and the map have the same size, as you acknowledged in a comment, i.e. it does not check for the end of the Iterator
.
It’s important that sortedMap
truly has to be a SortedMap
or a map implementation maintaining an order in general, which excludes the HashMap
mentioned in the title of your question. Otherwise, it’s pointless to sort the values of the arrayList
…
Upvotes: 1
Reputation: 19575
This can be implemented in different ways:
keySet
of the sorted map into list and use indexes to build a map using Collectors.toMap
:List<Integer> keys = new ArrayList<>(map.keySet());
Map<Integer, Integer> res = IntStream
.range(0, list.size())
.boxed()
.collect(Collectors.toMap(i -> keys.get(i), i -> list.get(i), (a, b)-> a, TreeMap::new));
System.out.println(res);
AtomicInteger
and its getAndIncrement
when streaming by keys of the sorted map to refer the element in the list with the updates:AtomicInteger i = new AtomicInteger(0);
Map<Integer, Integer> res2 = map.keySet()
.stream()
.collect(Collectors.toMap(
k -> k,
k -> list.get(i.getAndIncrement()),
(a, b) -> a,
TreeMap::new // or LinkedHashMap::new as keys are sorted
));
System.out.println(res2);
forEach
of the map's entrySet()
:AtomicInteger j = new AtomicInteger(0);
map.entrySet().forEach(e -> e.setValue(list.get(j.getAndIncrement())));
Extra safety measures may need to be added, for instance, handling of the case when the map and the list are of different size.
These examples prove the feasibility of such task, though the task itself does not seem to be an appropriate application of Stream API.
Upvotes: 0
Reputation: 21
You could convert the map keys to a list, and then loop through both map keys and sorted list simultaneously using IntStream:
List<Integer> list = new ArrayList<>(arrayList);
Collections.sort(list, Collections.reverseOrder());
List<Integer> mapKeys = new ArrayList<>(sortedMap.keySet());
Map<Integer,Integer> overwrittenMap =
IntStream.range(0,mapKeys.size())
.boxed()
.collect(TreeMap::new,
(map,i) -> map.put(mapKeys.get(i),list.get(i)),
Map::putAll);
Upvotes: 1