2

So I have a Map<String, Map<String, Integer>> and I want to convert it to a Map<Integer, Map<String, Integer>> where the String key is replaced with its index in the map(0,1,2,.....). I know that indices are not accurate in maps but that does not matter in my case. I tried using AtomicInteger as an index that is incremented after each operation on the stream but I could not solve the problem....

Csa77
  • 649
  • 13
  • 19
  • ...and can you paste here what you have so far? – x80486 May 12 '18 at 13:24
  • Possible duplicate of [Java 8 list to map with stream](https://stackoverflow.com/questions/32859038/java-8-list-to-map-with-stream) – sn42 May 12 '18 at 13:35

4 Answers4

6

As pointed by Michael a Map where the keys are only Integer following each other can be reduced as a List<Map<String, Integer>>, but if you really your specific structure :

  1. you can use AtomicInteger :

    AtomicInteger a = new AtomicInteger(0);
    before.forEach((key, value) -> after.put(a.getAndIncrement(), value));
    

    => Working example here


  1. Or, is after is empty at start

    before.values().forEach(value -> after.put(after.size(), value));
    

    => Working example here

azro
  • 53,056
  • 7
  • 34
  • 70
4

A map with contiguous integer keys is conceptually no different from a list, so really what you want is a List<Map<String, Integer>>.

You can achieve this like so:

List<Map<String, Integer>> after = before.values().stream().collect(Collectors.toList());
Michael
  • 41,989
  • 11
  • 82
  • 128
  • 1
    Thank you! This method works, but in fact I do need to get a Map<> as a result..... – Csa77 May 12 '18 at 13:38
  • 2
    Or just `new ArrayList<>(before.values())`… – Holger May 12 '18 at 14:00
  • @Holger It's one of *those questions* that unnecessarily restricts itself to "Using Java 8 streams..." – Michael May 12 '18 at 14:03
  • Right; since the Collection API is older than Stackoverflow, there never was a similar bunch of “How can I solve this using the Collection API?” questions. I think, it’s worth showing all alternatives to help developers to become aware of how many things could be solved easily, even without the Stream API… Btw, the accepted answer doesn’t use the Stream API either… – Holger May 12 '18 at 14:09
  • @Holger StackOverflow is no place for pragmatism! – Michael May 12 '18 at 14:12
  • I think, Stackoverflow works well for answerers who don’t stick to the questions wording. As said, the accepted answer doesn’t use the Stream API (though the OP might not be aware of the difference). But even if a more general answer doesn’t satisfy the OP, all you lose is the 15 points for the green checkmark, whereas addressing a bigger scope may earn you the 10 points of an upvote more than once. – Holger May 12 '18 at 14:25
  • @Holger Except this is literally home of the pedant. :) – Michael May 12 '18 at 15:21
2

Since you explicitly require a Map<Integer, Map<String, Integer>>, you could do it in two steps.

first, collect the values of the map to a list:

List<Map<String, Integer>> temporaryResult = new ArrayList<>(myMap.values());

then produce the index along with the maps:

Map<Integer, Map<String, Integer>> resultSet =
            IntStream.range(0, temporaryResult.size())
                    .mapToObj(i -> new AbstractMap.SimpleEntry<>(i,
                            temporaryResult.get(i)))
                    .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey,
                            AbstractMap.SimpleEntry::getValue));

or without mapping to an intermediate AbstractMap.SimpleEntry's

Map<Integer, Map<String, Integer>> resultSet =
               IntStream.range(0, temporaryResult.size())
                        .boxed()
                        .collect(Collectors.toMap(Function.identity(),
                                temporaryResult::get));
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
-2

You can use sequence of integers and zip with them, or map to those integers: IntStream.range(0, yourCollection.length)...

This would be the code, you may need minor adjustments. You can get the idea of zipping. `

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.IntStream;

class JavaTest{
    public int main(String[] args){
        Map<String, String> myMap = new HashMap<>();
        myMap.put("Key1", "Value1");
        myMap.put("Key2", "Value2");
        myMap.put("Key3", "Value3");

        List<String> values = new ArrayList<String>(myMap.values());

        Map<Integer, String> newMap = new HashMap<>();

        IntStream
        .range(0, values.size())
        .forEach(i -> newMap.put(i, values.get(i)));

        return 1;
    }
}

` P.S. Your instant down voting really helps me to answer questions ;)

Ignas
  • 389
  • 2
  • 13