Writing grep with Java 8 streams

Intro

We’re going to write our very own grep command using Java 8 streams. By the end, we will be able to run it on the command line, just like the normal UNIX grep program.

Pre-reqs

This post assumes you have some familiarity with Java 8 streams and a basic understanding of regular expressions. We’re actually going to review grep, so it’s ok if you do not yet know it.

What is grep?

According to wikipedia, “grep is a command-line utility for searching plain-text data sets for lines matching a regular expression.” And if you were wondering, grep stands for globally search a regular expression and print.

For example,

grep .*public.* MyJavaClass.java 

might yield

public class MyJavaClass {
public static void main(String[] args) {
public static final int MY_INT_CONST = 3;

As input, grep takes a pattern and some text to search (maybe a file, maybe the output of another program). As output, it then prints out all lines of the input text that match the pattern.

Our grep implementation will only take files as input, and will only use Regular Expressions as patterns.

Not so bad, right?

Grep implementation

The grep method

This is where we will write the bulk of the logic of our program. With streams, the method body is just one line, styled across two. (note: I omitted the throws clause to keep the code clean).

public static Stream<String> grep (String pattern, String fileName) {
    return Files.lines(Paths.get(fileName))
                .filter(line -> line.matches(pattern));
}

Fortunately, Java 8 streams shipped with some pretty sweet I/O functions, like java.nio.Files::lines(). This function takes a file name and returns a stream of the lines of that file.

All we need to do after that is filter those lines by matching on our pattern (built into Java.lang.String), and we’re done!

The main method

Now, we can give our Grep class a main method so that we can call it from the command line.

public static void main(String[] args) throws IOException {
    grep(args[0], args[1]).forEach(System.out::println);
}

All we’re doing here is calling our grep function, then printing out each line in the stream that gets returned.

The whole program

Putting it all back together, our grep program in its entirety looks like:

public class Grep {

    public static void main(String[] args) throws IOException {
        grep(args[0], args[1]).forEach(System.out::println);
    }

    public static Stream<String> grep(String pattern, String fileName)
            throws IOException {
        return Files.lines(Paths.get(fileName))
                    .filter(line -> line.matches(pattern));
    }

}

Running our grep program

Now, we can find all the lines that have the word ‘public’ in Grep.java, using Grep.java.

java Grep ".*public.*" Grep.java

and see as output:

public class Grep {
    public static void main(String[] args) throws IOException {
    public static Path getPath(String fileName) throws IOException {
    public static Stream<String> grep(String pattern, String fileName)
rss facebook twitter github youtube mail spotify instagram linkedin google pinterest medium