Java 创建单词';流式扫描仪

Java 创建单词';流式扫描仪,java,loops,java-stream,builder,word,Java,Loops,Java Stream,Builder,Word,需要从文件中返回包含3个字母及更多字母的所有单词的流。有没有比下面更好的方法,可能是使用Stream.iterate: private Stream<String> getWordsStream(String path){ Stream.Builder<String> wordsStream = Stream.builder(); FileInputStream inputStream = null; try { inputStre

需要从文件中返回包含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();
}
私有流getWordsStream(字符串路径){
Stream.Builder wordsStream=Stream.Builder();
FileInputStream inputStream=null;
试一试{
inputStream=新文件inputStream(路径);
}catch(filenotfounde异常){
e、 printStackTrace();
}
扫描仪s=新扫描仪(inputStream);
s、 使用分隔符(([^a-zA-Z]);
Pattern=Pattern.compile(([a-zA-Z]{3,})”;
而((s.hasNext())){
如果(s.hasNext(模式)){
添加(s.next().toUpperCase());
}
否则{
s、 next();
}
}
s、 close();
返回wordsStream.build();
}

方法简单得多:从文件读取行到
,并使用所需条件(例如长度>=3)对其进行过滤
Files.lines()
具有延迟加载,因此它不会在开始时准备好文件中的所有单词,而是在每次需要下一个单词时都这样做

public static void main(String... args) throws IOException {
    getWordsStream(Paths.get("d:/words.txt")).forEach(System.out::println);
}

public static Stream<String> getWordsStream(Path path) throws IOException {
    final Scanner scan = new Scanner(path);

    return StreamSupport.stream(new Spliterators.AbstractSpliterator<String>(Long.MAX_VALUE,
            Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED) {
        @Override
        public boolean tryAdvance(Consumer<? super String> action) {
            while (scan.hasNext()) {
                String word = scan.next();

                // you can use RegExp if you have more complicated condition
                if (word.length() < 3)
                    continue;

                action.accept(word);
                return true;
            }

            return false;
        }
    }, false).onClose(scan::close);
}
publicstaticvoidmain(String…args)抛出IOException{
getWordsStream(path.get(“d:/words.txt”)).forEach(System.out::println);
}
公共静态流getWordsStream(路径路径)引发IOException{
最终扫描仪扫描=新扫描仪(路径);
返回StreamSupport.stream(新的拆分器.AbstractSpliterator(Long.MAX_值,
Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED){
@凌驾

public boolean tryAdvance(ConsumerThre’s更简单的方法:从文件到
流中读取行,并使用所需条件(例如长度>=3)对其进行过滤。
Files.lines()
具有延迟加载,因此它不会在开始时准备好文件中的所有字,每次需要下一个字时都会这样做

public static void main(String... args) throws IOException {
    getWordsStream(Paths.get("d:/words.txt")).forEach(System.out::println);
}

public static Stream<String> getWordsStream(Path path) throws IOException {
    final Scanner scan = new Scanner(path);

    return StreamSupport.stream(new Spliterators.AbstractSpliterator<String>(Long.MAX_VALUE,
            Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED) {
        @Override
        public boolean tryAdvance(Consumer<? super String> action) {
            while (scan.hasNext()) {
                String word = scan.next();

                // you can use RegExp if you have more complicated condition
                if (word.length() < 3)
                    continue;

                action.accept(word);
                return true;
            }

            return false;
        }
    }, false).onClose(scan::close);
}
publicstaticvoidmain(String…args)抛出IOException{
getWordsStream(path.get(“d:/words.txt”)).forEach(System.out::println);
}
公共静态流getWordsStream(路径路径)引发IOException{
最终扫描仪扫描=新扫描仪(路径);
返回StreamSupport.stream(新的拆分器.AbstractSpliterator(Long.MAX_值,
Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED){
@凌驾

public boolean tryAdvance(Consumer您可以使用
Files.lines()
模式

private static final Pattern SPACES = Pattern.compile("[^a-zA-Z]+");

public static Stream<String> getWordStream(String path) throws IOException{
    return Files.lines(Paths.get(path))
        .flatMap(SPACES::splitAsStream)
        .filter(word -> word.length() >= 3);
}
private static final Pattern SPACES=Pattern.compile(“[^a-zA-Z]+”);
公共静态流getWordStream(字符串路径)引发IOException{
返回文件.line(路径.get(路径))
.flatMap(空格::拆分流)
.filter(word->word.length()>=3);
}

您可以使用
文件.lines()
模式

private static final Pattern SPACES = Pattern.compile("[^a-zA-Z]+");

public static Stream<String> getWordStream(String path) throws IOException{
    return Files.lines(Paths.get(path))
        .flatMap(SPACES::splitAsStream)
        .filter(word -> word.length() >= 3);
}
private static final Pattern SPACES=Pattern.compile(“[^a-zA-Z]+”);
公共静态流getWordStream(字符串路径)引发IOException{
返回文件.line(路径.get(路径))
.flatMap(空格::拆分流)
.filter(word->word.length()>=3);
}

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

FileInputStream inputStream = null;
try {
    inputStream = new FileInputStream(path);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
Scanner s = new Scanner(inputStream);
因此,当文件不存在时,您将打印
FileNotFoundException
堆栈跟踪,并继续执行
null
输入流,导致
NullPointerException
。与要求调用方处理虚假的
NullPointerException
不同,您应该在t中声明
FileNotFoundException
方法签名。否则,在错误的情况下返回空流

但是您根本不需要构造
FileInputStream
,因为
Scanner
为构造函数提供了接受
文件
路径
的功能。将此功能与返回匹配流的功能结合起来(自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();
    }
}

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

FileInputStream inputStream = null;
try {
    inputStream = new FileInputStream(path);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
Scanner s = new Scanner(inputStream);
因此,当文件不存在时,您将打印
FileNotFoundException
堆栈跟踪,并继续执行
null
输入流,导致
NullPointerException
。与要求调用方处理虚假的
NullPointerException
不同,您应该在t中声明
FileNotFoundException
方法签名。否则,在错误的情况下返回空流

但是您根本不需要构造
FileInputStream
,因为
Scanner
为构造函数提供了接受
文件
路径
的功能。将此功能与返回匹配流的功能结合起来(自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();
    }
}

哪个Java版本?您是想调用
s.next(pattern)
?可能将整个流作为字符串读取,然后用空格(或您正在使用的任何内容)将其拆分Java 9.我的意思是:有没有可能编写更接近流样式的方法,而不使用while循环,哪一个Java版本?你的意思是调用
s.next(pattern)
?可能将整个流读取为字符串,然后用空格(或任何你正在使用的)将其拆分Java 9。我的意思是:有没有可能编写更接近流样式的方法,而不在alland
lines()处执行while循环
将返回一个字流?对于这种方法来说,这是一个非常糟糕的名称-可能是Java 9,但可以肯定的是,在Java 11中,它返回的是一个行流。它返回的行在任何Java中都超过3个字母符号。我有一个未准备好的文本。因此需要再次循环以查找行中的所有匹配项。实际上,
行()
返回所有行,不仅仅是包含3个以上字母的行。返回包含3个或更多字母的行的是
getWordsStream()
。但问题是包含3个或更多字母的单词,而不是包含3个或更多字母的行,您不需要更改该方法的签名,可以使用
Files.lines(Path.of(Path))
代替.Fixed.Sa