0
\$\begingroup\$

Code:

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Created by IDEA on 16/11/14.
 */
public class TestStream {
    private final static Pattern pattern = Pattern.compile("^(\\S+)\\s+");
    public static String firstWord(String s) {
        Matcher matcher = pattern.matcher(s);
        if(matcher.find()) {
            return matcher.group();
        }
        return null;
    }
    public static void main(String[] args) throws Exception {
        List<String> x =  Files.lines(Paths.get("/tmp/testfile"), Charset.defaultCharset()).map(line -> firstWord(line)).collect(Collectors.toList());
        System.out.println(x);

    }
}
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Your code will fail with a single-column input like:

one
two
three
four

Additionally, it will produce odd results with space-prefixed lines like:

normal line
   spaceprefixed line

The reason it will fail is because the Files.lines method trims the line terminators off of each line, so, the input to the regex will be just one, etc. Since there's no whitespace after the one, the match will fail, and the method will return null.

You should consider an alternative approach of doing a limited split, and returning the first value:

private final static Pattern pattern = Pattern.compile("\\s+");

public static String firstWord(String s) {
    return pattern.split(s, 2)[0];
}

This also changes the logic slightly because empty lines will return empty-string, instead of null.

Additionally, your code will match " spaceprefixed" from " spaceprefixed line" whereas my code will consider the leading space to be a separator (and not part of the first word), and will match the empty string "" from " spaceprefixed line"

In other words, I disagree with some of the handling you have with edge cases.

I would handle the edge cases in a different way in the stream too:

List<String> x = Files.lines(Paths.get("/tmp/testfile"), Charset.defaultCharset())
            .map(line -> firstWord(line))
            .filter(word -> !word.isEmpty())
            .collect(Collectors.toList());
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.