Java 8 Streams 和 lambdas 保持严格的 FP

标签 java lambda functional-programming java-8 java-stream

Java 8 lambda 在许多情况下都非常有用,可以以紧凑的方式以 FP 方式实现代码。
但是在某些情况下,我们可能必须访问/改变外部状态,这不是按照 FP 实践的好做法。
(因为 Java 8 Functional 接口(interface)有严格的输入和输出签名,我们不能传递额外的参数)

例如:

class Country{
        List<State> states;
    }
    class State{
        BigInt population;
        String capital;
    }

    class Main{
        List<Country> countries;

        //code to fill
    }

假设用例是获取所有国家的所有首都和所有州的总人口

正常执行:

List<String> capitals = new ArrayList<>();
BigInt population = new BigInt(0);

for(Country country:countries){
    for(State state:states){
        capitals.add(state.capital);
        population.add(state.population)
    }
}

如何以更优化的方式使用 Java 8 Streams 实现同样的功能?

Stream<State> statesStream = countries.stream().flatMap(country->country.getStates());

    capitals = statesStream.get().collect(toList());
    population = statesStream.get().reduce((pop1,pop2) -> return pop1+pop2);

但是上面的实现不是很有效。任何使用 Java 8 Streams 操作多个集合的其他更好的方法

最佳答案

如果您想在一个管道中收集多个结果,您应该创建一个结果容器和一个自定义的Collector

class MyResult {
  private BigInteger population = BigInteger.ZERO;
  private List<String> capitals = new ArrayList<>();

  public void accumulate(State state) {
    population = population.add(state.population);
    capitals.add(state.capital);
  }

  public MyResult merge(MyResult other) {
    population = population.add(other.population);
    capitals.addAll(other.capitals);
    return this;
  }
}
MyResult result = countries.stream()
  .flatMap(c -> c.getStates().stream())
  .collect(Collector.of(MyResult::new, MyResult::accumulate, MyResult::merge));

BigInteger population = result.population;
List<String> capitals = result.capitals;

或者像你一样直播两次。

关于Java 8 Streams 和 lambdas 保持严格的 FP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44697631/

相关文章:

java - 多级层次结构的 Hibernate 混合继承策略

python - pyspark使用lambda内的正则表达式分割字符串

java - 方法引用是否摆脱了可重写的方法调用?

c++17:lambda 到 std::function 转换失败

compiler-construction - 为什么像 Haskell 这样的函数式语言中没有尖端的编译器后端?

scala - 将 monad 组合成元组运算符 scalaz

java - 接口(interface)实例如何访问Object类的方法?

java - 查询从日期时间字段返回一天的记录

java - JAX-RS 是否需要数据传输对象 (DTO)?

algorithm - 为什么 F# 核心库不提供通用的序列切片功能?