0

I'm recently learning about Java stream and try to practice some of stream features by converting some of my previous code snippet. The following traditional for loop in the program is to store the index and its reversed string in the original array to a map.

String[] words = {"hey", "there", "how", "are", "you"};
Map<String, Integer> map = new HashMap<>();
for (int i = 0; i < words.length; i++) {
    String rev = new StringBuilder(words[i]).reverse().toString();
    map.put(rev, i);
}

However, I have a hard time achieving this same thing using pure stream. I think the problem I have is how to keep track of the index and the reversed string at the same time. As you can see from the traditional for loop, I'm converting the string to stringbuilder, then reverse it, and then convert back to string. Finally I put index and string to map. But I couldn't figure out a way to keep track of all these using pure stream. Somebody could enlighten me? Thanks!

  • What is your try so far ? – Eklavya May 12 '20 at 12:56
  • Hint: don't reverse in the stream, reverse in the collector. – RealSkeptic May 12 '20 at 12:58
  • I think that any part of stream programming is learning when to apply it and when not to apply it. I don't see any reason why it should be used here. The order of operations will be N anyway, you won't get any speedup from parallel programming as far as I can see and your code will become less readable. – Maarten Bodewes May 12 '20 at 13:06
  • Does this answer your question? [When should I use IntStream.range in Java?](https://stackoverflow.com/questions/38998514/when-should-i-use-intstream-range-in-java) – Arvind Kumar Avinash Jun 24 '20 at 12:52
  • Does this answer your question? [Replace for-each loop with lambda expression](https://stackoverflow.com/questions/50006972/replace-for-each-loop-with-lambda-expression)? – Arvind Kumar Avinash Jun 24 '20 at 12:54

2 Answers2

3

It can be done via IntStream which imitates for loop:

Map<String, Integer> map = IntStream.range(0, words.length).boxed()
    .collect(Collectors.toMap(
        i -> new StringBuilder(words[i]).reverse().toString(), // key: reversed string
        i -> i // value: index in array
    ));
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
0

As you are learning about streams I offer this alternative Collectors.toMap method. It allows you to use a merge function and specify a type of map. In this case the merge function is not used but by using a LinkedHashMap, the order of the map is preserved.

Map<String, Integer> map =
        IntStream.range(0, words.length).boxed()
                .collect(Collectors.toMap(
                        i -> new StringBuilder(words[i])                                     
                             .reverse().toString(),
                        i -> i,
                        // merge is unused
                        (r, s) -> s, 
                        // supplier for the type of map
                        LinkedHashMap::new));

System.out.println(map);

Prints

{yeh=0, ereht=1, woh=2, era=3, uoy=4}
WJS
  • 36,363
  • 4
  • 24
  • 39