Java 8 Stream API Features Intermediate operations & Terminal operations

Stream API 中提供了findFirst(),orElse() 这样的 method, 这些 method 具体是做什么,可以看看文档:一目了然。

public static void main(String... args){
    List<Integer> values = Arrays.asList(11,22,33,44,55,60,75);
    System.out.println(values.stream()
                             .filter(i -> i%5 == 0)
                             .map(i -> i*2)
                             .findFirst()
                             .orElse(0)
    );
}

findFirst():  它是一个 terminal operator

/**
 * Returns an {@link Optional} describing the first element of this stream,
 * or an empty {@code Optional} if the stream is empty.  If the stream has
 * no encounter order, then any element may be returned.
 *
 * <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
 * terminal operation</a>.
 *
 * @return an {@code Optional} describing the first element of this stream,
 * or an empty {@code Optional} if the stream is empty
 * @throws NullPointerException if the element selected is null
 */
Optional<T> findFirst();

orElse():

/**
 * Return the value if present, otherwise return {@code other}.
 *
 * @param other the value to be returned if there is no value present, may
 * be null
 * @return the value, if present, otherwise {@code other}
 */
public T orElse(T other) {
    return value != null ? value : other;
}

这里举这个 demo 是想说明什么问题呢,现在说 Java 比之前更 efficient ,为什么这么说呢,一点一点分析:我们 demo 示例里的 code 如果我们用 jdk1.7 来实现是这样的:

public static void main(String... args){
    List<Integer> values = Arrays.asList(11,22,33,44,55,60,75);
    System.out.println(values.stream()
                             .filter(i -> i%5 == 0)
                             .map(i -> i*2)
                             .findFirst()
                             .orElse(0)
    );

    int result = 0;
    for (int i: values) {
        if(i % 5 == 0){
            result = i*2;
            break;
        }
    }
    System.out.println(result);
}
两次 output 是相同的。

如果从表面上看,jdk1.7的 implementation 看上去好像比 Stream API 的 efficient 要高一点,因为 jdk1.7里第一个 value 满足条件后就直接 break 了,而 Stream API里呢,它是要先把所有的 number 都检查一遍,看能不能被5整除,再都乘以2,最后再去取第一个,如果找不到就是输出0. 反了? 真的是这样么? Stream API 反而让 Java 的 efficient 变低了,哈哈,不要被表面给欺骗了。其实不是这样的。Stream API 不会这么愚蠢的,可是从 code 上面看,java code 从上而下编译执行,应该就是像我刚说的那样很笨的 execute 才对,现在去推翻它。我们给上面的代码加点东西:

public static void main(String... args){
    List<Integer> values = Arrays.asList(11,22,33,44,55,60,75);
    System.out.println(values.stream()
                             .filter(Java8Demo::isDivisible)
                             .map(Java8Demo::mapDouble)
                             .findFirst()
                             .orElse(0)
    );
}

public static boolean isDivisible(int i){
    System.out.println("in isDvs: " + i);
    return i % 5 == 0;
}

public static int mapDouble(int i){
    System.out.println("in mapDouble: " + i);
    return i * 2;
}
看最终输出的:

in isDvs: 33
in isDvs: 44
in isDvs: 55
in mapDouble: 55
110

看到了吧,也是一样的,找到第一个满足条件的 number 后就不会再去往后面找了。很清楚吧。

解释一下:

我觉得下面这段英文解释的非常到位:

A stream supports two types of operations:

  • Intermediate operations
  • Terminal operations

Intermediate operations are also called lazy operations.

Terminal operations are also called eager operations.

A lazy operation does not process the elements until an eager operation is called on the stream.

An intermediate operation on a stream produces another stream.

Streams link operations to create a stream pipeline.

所以:

In the above code filter() and map() are all lazy operations. While reduce() is eager operation.

Stream API 的efficient 是要比 jdk1.7要高的,而且上面的 code 中使用的internal iteration,所以你 get 到 主要的 point 了么?


更多请参考这里:

http://docs.oracle.com/javase/8/docs/api/

http://www.java2s.com/Tutorials/Java_Streams/Tutorial/Streams/Intermediate_operations_Terminal_operations.htm
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值