2

Is there any way to write the following code using Streams?

public Map<String, Integer> process() {
    List<String> words = Arrays.asList(message.toLowerCase().split("[?.\\s]+"));
    Map<String, Integer> countMap = new HashMap<>();

    for (String word : words) {
        if (word.length() > 2) {
            Integer count = countMap.getOrDefault(word, 0);
            countMap.put(word, count + 1);
        }
    }
    return countMap;
}
2
  • I just wanted to count words which are have greater than 2 characters. Commented Apr 17, 2018 at 7:23
  • 1
    It should be like this Pattern.compile("[?.\\s]+").splitAsStream(message.toLowerCase()) .filter(w -> w.length() > 2).count() Commented Apr 17, 2018 at 7:30

2 Answers 2

3

Start out with

Pattern.compile("[?.\\s]+").splitAsStream(message.toLowerCase())

if you can live with a long result, stick with Ravindra's solution, if you need int, use Eran's counter.

So either:

Map<String, Long> r = Pattern.compile("[?.\\s]+").splitAsStream(message.toLowerCase())
    .filter(w -> w.length() > 2)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

or

Map<String, Integer> r = Pattern.compile("[?.\\s]+").splitAsStream(message.toLowerCase())
    .filter(w -> w.length() > 2)
    .collect(Collectors.toMap(Function.identity(), w -> 1, Integer::sum));

or (after the comment below) (even better)

Map<String, Integer> r = Pattern.compile("[?.\\s]+").splitAsStream(message.toLowerCase())
    .filter(w -> w.length() > 2)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(x -> 1)));
Sign up to request clarification or add additional context in comments.

5 Comments

instead Collectors.counting() use Collectors.summingInt(e->1)
@HadiJ Thanks, included in the answer.
Nice answer @mtj
Alternatively Collectors.groupingBy(Function.identity(), Collectors.collectingAndThen(Collectors.counting(), Long::intValue))
Thanks, that helped :)
2

You can use Collectors.toMap to generate the Map:

Map<String, Integer> countMap =
    words.stream()
         .filter(word -> word.length() > 2)
         .collect(Collectors.toMap(Function.identity(),w -> 1, Integer::sum));

Of course you can skip Arrays.asList and create a Stream directly from the array:

Map<String, Integer> countMap =
    Arrays.stream (message.toLowerCase().split("[?.\\s]+"))
          .filter(word -> word.length() > 2)
          .collect(Collectors.toMap(Function.identity(),w -> 1, Integer::sum));

1 Comment

hey can you explain me how do these parameters execute (w -> 1, Integer::sum)

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.