0

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!

3 Answers 3

1

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);
Sign up to request clarification or add additional context in comments.

Comments

1

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

1 Comment

you are right sortedMap is actually a LinkedHashMap. My bad that I mentioned hashmap in title. Thank you for your help.
0

This can be implemented in different ways:

  1. Convert 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);
  1. Use 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);
  1. Similarly to previous implementation, current map may be modified using 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.

1 Comment

@AlexRundenko map and list are always going to be of the same size in this scenario. I appreciate your help for these examples that are indeed feasible for this task. I am new to streams so trying to get an understanding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.