Streaming Text: lines, chars, split

Streams · lesson 25 of 42 · 4 min read

Turn a document into lines, lines into words and words into counts, all as streams.

Open this lesson in the learning hub

Key points

  • String.lines() streams the lines of a string lazily and handles every line ending for you.
  • Files.lines(path) does the same for a file, but it holds an open handle, so wrap it in try with resources.
  • split returns an array, so pair it with Arrays.stream(...) inside a flatMap to get one stream of words.
  • Pattern.splitAsStream is the lazy version: it stops splitting as soon as the terminal op stops pulling.
  • String.chars() is an IntStream of code units, not characters, so cast back with (char) c before printing.
  • Word counting is groupingBy(word, counting()). That one line replaces a map, a loop and a null check.

Example

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        String doc = """
                the quick brown fox
                jumps over the lazy dog
                the end""";

        System.out.println("lines    : " + doc.lines().count());
        System.out.println("first    : " + doc.lines().findFirst().orElse(""));

        List<String> words = doc.lines()
                .flatMap(line -> Arrays.stream(line.split(" ")))
                .toList();
        System.out.println("words    : " + words.size());

        Map<String, Long> freq = words.stream()
                .collect(Collectors.groupingBy(w -> w, TreeMap::new, Collectors.counting()));
        System.out.println("the x    : " + freq.get("the"));
        System.out.println("longest  : " + words.stream()
                .max(Comparator.comparingInt(String::length)).orElseThrow());

        // chars() is an IntStream of code units, so map back to text before printing.
        System.out.println("vowels   : " + "streams".chars().filter(c -> "aeiou".indexOf(c) >= 0).count());
        System.out.println("shout    : " + "abc".chars()
                .mapToObj(c -> String.valueOf((char) Character.toUpperCase(c)))
                .collect(Collectors.joining()));

        // splitAsStream is the lazy regex split: it stops when the terminal op stops.
        System.out.println("csv head : " + java.util.regex.Pattern.compile(",")
                .splitAsStream("a,b,c,d").limit(2).toList());
    }
}

Text is already a stream source; you rarely need to build a list first.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.