关于一次性处理中间操作?

时间:2017-01-10 19:30:20

标签: java java-8 java-stream

采取以下代码:

// trader (name, city) 
Trader raoul = new Trader("Raoul", "Cambridge");
Trader mario = new Trader("Mario", "Milan");
Trader alan = new Trader("Alan", "Cambridge");
Trader brian = new Trader("Brian", "Cambridge");
// transaction(trader, year, value)
List<Transaction> transactions = Arrays.asList(
    new Transaction(brian, 2011, 300),
    new Transaction(raoul, 2012, 1000),
    new Transaction(raoul, 2011, 400),
    new Transaction(mario, 2012, 710),
    new Transaction(mario, 2012, 700),
    new Transaction(alan, 2012, 950)
);
transactions.stream()
    .filter( t -> {
        System.out.println("filtring "+t.getValue());
        return t.getValue()>=700;
    })
    .map(t -> {
        System.out.println("mapping "+t.getValue());
        return t.getValue();
    })
    .count();

多次运行上面的代码总是给出以下输出:

filtring 300
filtring 1000
mapping 1000
filtring 400
filtring 710
mapping 710
filtring 700
mapping 700
filtring 950
mapping 950

我不会动摇这个输出。有人可以给我一个关于这个结果的解释。我期待这个输出:

filtring 300
filtring 1000
filtring 400
filtring 710
filtring 700
filtring 950
mapping 1000
mapping 710
mapping 700
mapping 950

2 个答案:

答案 0 :(得分:3)

这是预期的。整个管道(一个懒惰的方式 - 这就是为什么你一次只能在元素上看到第一个过滤300 而没有后映射的原因)。

你可以这样思考:首先过滤第一个元素,然后映射;然后过滤第二个然后映射。如果过滤返回false,则不需要执行映射,无论如何都会省略结果(这就是为什么它是懒惰的。)

实际上,当涉及到流时,这是非常基本的东西。

顺便说一句,这似乎是“ java-8 in action ”中的一个例子,如果我没有弄错的话,那本书解释了这些基本的东西。请务必再次阅读(如果需要,请再次阅读)。

答案 1 :(得分:3)

在以下表达式中

transaction.stream().filter(conditionPredicate).map(mapperFunction).count();

每次方法调用后返回的对象的类型是

List<Transaction> => Stream<Transaction> => Stream<Transaction> => Stream<Integer> => long

Stream库主要是懒惰地实现的。这意味着操作管道中的所有lambda都应用于第一个元素,然后应用于第二个元素上的所有lambdas,依此类推。中间集合(流)根本不存储。

希望这有帮助。