Java8:一次性应用流映射和过滤器

Java8:一次性应用流映射和过滤器,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,我正在用Java8为一个文件编写解析器。使用Files.lines读取文件,并返回顺序流 每一行都映射到一个数据对象结果,如下所示: Result parse(String _line) { // ... code here Result _result = new Result(). if (/* line is not needed */) { return null; } else { /* parse line into result */ retu

我正在用Java8为一个文件编写解析器。使用
Files.lines
读取文件,并返回顺序

每一行都映射到一个数据对象
结果
,如下所示:

Result parse(String _line) {
  // ... code here
  Result _result = new Result().
  if (/* line is not needed */) {
    return null;
  } else {
    /* parse line into result */
   return _result;
  }
}
现在,我们可以将流中的每一行映射到其相应的结果:

public Stream<Result> parseFile(Path _file) {
  Stream<String> _stream = Files.lines(_file);
  Stream<Result> _resultStream = _stream.map(this::parse);
}

如我在
parseLine/\u stream.map中所知,如果需要结果,如何组合map/filter操作?

如注释中所述,流将在一次过程中处理,因此实际上不需要更改任何内容。您可以使用
flatMap
并让
parse
返回流:

Stream<Result> parse(String _line) {
  .. code here
  Result _result = new Result().
  if (/* line is not needed */) {
    return Stream.empty();
  } else {
    /** parse line into result */
   return Stream.of(_result);
  }
}  

public Stream<Result> parseFile(Path _file) {
  return Files.lines(_file)
              .flatMap(this::parse);
}
流解析(字符串_行){
…这里是代码
结果_Result=新结果()。
如果(/*行不需要*/){
返回Stream.empty();
}否则{
/**将行解析为结果*/
返回流。of(_结果);
}
}  
公共流解析文件(路径_文件){
返回文件。行(_文件)
.flatMap(this::parse);
}

这样一来,您首先就不会有任何
null
值。

针对Java 9的更新:

使用
Stream
似乎是
parse()
函数的错误返回类型。一个流可以包含很多很多值,因此
parse()
的用户要么假设流中最多有一个值,要么使用
collect
之类的方法提取并使用
parse()
操作的结果。如果函数和它的用法只被几行代码隔开,这可能没问题,但是如果距离增加了,比如在一个完全不同的JUnit测试文件中,接口契约与返回值之间就不清楚了

与其返回
,不如在不需要行时返回空的
可选

Optional<Result> parse(String _line) {
   ... code here
   Result _result = null;
   if (/* line needed */) {
      /** parse line into result */
   }
   return Optional.ofNullable(_result);
}

可选
值流转换为
结果
值流,不带任何空选项

我不明白,
returnfiles.line(_file).map(this::parse).filter(v->v!=null)有什么问题?仅当您使用需要完全迭代的终端操作(例如forEach、collect、reduce)时,才会在一次运行中处理流。@user3001另请参见:您关于多个过程的假设不正确。过滤和映射在单个过程中处理。(通常,整个管道在一次过程中处理,除非有排序等操作必须在生成任何数据之前查看所有数据。)在这种情况下,您将把
map&filter
替换为
map&flatMap
。直接使用
null
然后将其过滤掉没有多大区别。
Optional<Result> parse(String _line) {
   ... code here
   Result _result = null;
   if (/* line needed */) {
      /** parse line into result */
   }
   return Optional.ofNullable(_result);
}
public Stream<Result> parseFile(Path _file) {
  return Files.lines(_file)
      .map(this::parse)
      .flatMap(Optional::stream)
}