使用扫描仪创建单词'流

a_c*_*nko 1 java loops builder cpu-word java-stream

需要从文件中返回包含3个或更多单词的所有单词的流.是否有更好的方式,然后使用Stream.iterate:

private Stream<String> getWordsStream(String path){
    Stream.Builder<String> wordsStream = Stream.builder();
    FileInputStream inputStream = null;
    try {
        inputStream = new FileInputStream(path);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    Scanner s = new Scanner(inputStream);
    s.useDelimiter("([^a-zA-Z])");
    Pattern pattern = Pattern.compile("([a-zA-Z]{3,})");
    while ((s.hasNext())){
        if(s.hasNext(pattern)){
            wordsStream.add(s.next().toUpperCase());
        }
        else {
            s.next();
        }
    }
    s.close();
    return wordsStream.build();
}
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 5

代码中最糟糕的部分是以下部分

FileInputStream inputStream = null;
try {
    inputStream = new FileInputStream(path);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
Scanner s = new Scanner(inputStream);
Run Code Online (Sandbox Code Playgroud)

因此,当文件不存在时,您将打印FileNotFoundException堆栈跟踪并继续null输入流,从而导致a NullPointerException.NullPointerException您应该FileNotFoundException在方法签名中声明,而不是要求调用者处理虚假.否则,在错误的情况下返回空流.

但是你根本不需要构建一个FileInputStream,因为Scanner提供构造函数接受一个File或者Path.将此与返回匹配流的能力(自Java 9)相结合,您将得到:

private Stream<String> getWordsStream(String path) {
    try {
        Scanner s = new Scanner(Paths.get(path));
        return s.findAll("([a-zA-Z]{3,})").map(mr -> mr.group().toUpperCase());
    } catch(IOException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        return Stream.empty();
    }
}
Run Code Online (Sandbox Code Playgroud)

或者最好

private Stream<String> getWordsStream(String path) throws IOException {
    Scanner s = new Scanner(Paths.get(path));
    return s.findAll("([a-zA-Z]{3,})").map(mr -> mr.group().toUpperCase());
}
Run Code Online (Sandbox Code Playgroud)

你甚至不需要.useDelimiter("([^a-zA-Z])")这里,因为跳过所有不匹配的东西是默认行为.

关闭返回的Stream也将关闭Scanner.

所以调用者应该像这样使用它

try(Stream<String> s = getWordsStream("path/to/file")) {
    s.forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)