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)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.