Following code snippet shows how you can write a word count program using Java 8 Stream API.
public class WordCountExample {
public static void main(String[] args) throws IOException {
Path path = Paths.get("src/main/resources/book.txt");
Map<String, Integer> wordCount = Files.lines(path)
.flatMap(line -> Arrays.stream(line.trim().split(" ")))
.map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
.filter(word -> word.length() > 0)
.map(word -> new SimpleEntry<>(word, 1))
.sorted((e1, e2) -> e1.getKey().compareTo(e2.getKey()))
.reduce(new LinkedHashMap<>(), (acc, entry) -> {
acc.put(entry.getKey(), acc.compute(entry.getKey(), (k, v) -> v == null ? 1 : v + 1));
return acc;
}, (m1, m2) -> m1);
wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
}
}
The better solution is using toMap collector as shown below.
public static void main(String[] args) throws IOException {
Path path = Paths.get("src/main/resources/book.txt");
Map<String, Integer> wordCount = Files.lines(path).flatMap(line -> Arrays.stream(line.trim().split("s")))
.map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
.filter(word -> word.length() > 0)
.map(word -> new SimpleEntry<>(word, 1))
.collect(toMap(e -> e.getKey(), e -> e.getValue(), (v1, v2) -> v1 + v2));
wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
}
Even better version can be written using grouping and counting collector as shown below.
public static void main(String[] args) throws IOException {
Path path = Paths.get("src/main/resources/book.txt");
Map<String, Long> wordCount = Files.lines(path).flatMap(line -> Arrays.stream(line.trim().split("\s")))
.map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
.filter(word -> word.length() > 0)
.map(word -> new SimpleEntry<>(word, 1))
.collect(groupingBy(SimpleEntry::getKey, counting()));
wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
}