《Java高并发程序设计》学习 --6.3 一步一步走入函数式编程

45 篇文章 0 订阅
首先从简单的例子开始。
static int[] arr = {1,2,3,4,5,6,7,8,9,10};
public static void main(String[] args) {
    for(int i:arr) {
        System.out.println(i);
    }
}
上述代码循环遍历了数组内的元素,并且进行了数值的打印。使用Java 8写法如下:
static int[] arr = {1,2,3,4,5,6,7,8,9,10};
public static void main(String[] args) {
    Arrays.stream(arr).forEach(new IntConsumer() {
        @Override
        public void accept(int value) {
            System.out.println(value);
        }
    });
}
这里值得注意的是这个流对象的forEach()方法,它接收一个IntConsumer接口的实现,用于对每个流内的对象进行处理。之所以是IntConsumer接口,因为当前流是IntStream,也就是装有Integer元素的流,因此,它自然需要一个处理Integer元素的接口。函数forEach()会挨个将流内的元素送入IntConsumer进行处理,循环过程被封装在forEach()内部,也就是JDK框架内。
除了IntStream流外,Arrays.stream()还支持DoubleStream、LongStream和普通的对象流Stream,这完全取决于它所接受的参数。
forEach()函数的参数是可以从上下文中推导出来的,于是:
static int[] arr = {1,2,3,4,5,6,7,8,9,10};
public static void main(String[] args) {
    Arrays.stream(arr).forEach((final int x) -> {
        System.out.println(x);
    });
}
从上述代码中可以看到,IntStream接口名称被省略了,这里只使用了参数和一个实现体。因为参数的类型也是可以推导的。既然是IntConsumer接口,参数自然是int了,于是:
static int[] arr = {1,2,3,4,5,6,7,8,9,10};
public static void main(String[] args) {
    Arrays.stream(arr).forEach((x) -> {
        System.out.println(x);
    });
}
可以去掉一对花括号,把参数申明和接口实现放在一行:
static int[] arr = {1,2,3,4,5,6,7,8,9,10};
public static void main(String[] args) {
    Arrays.stream(arr).forEach((x) -> System.out.println(x));
}
此时,forEach()函数的参数依然是IntConsumer,但是它却以一种新的形式被定义,这就是lambda表达式。表达式由“->”分割,左半部分表示参数,右半部分表示实现体。因此,可以简单地理解lambda表达式只是匿名对象实现的一种新的方式。
Java 8还支持了方法引用,通过方法引用的推导,可以连参数申明和传递省略。
static int[] arr = {1,2,3,4,5,6,7,8,9,10};
public static void main(String[] args) {
    Arrays.stream(arr).forEach(System.out::println);
}
使用lambda表达式不仅可以简化匿名类的编写,与接口的默认方法结合,还可以使用更顺畅的流式API对各种组件进行更自由的装配。
下面这个例子对集合中所有元素进行两次输出,一次输出到标准错误,一次输出到标准输出中。
static int[] arr = {1,2,3,4,5,6,7,8,9,10};
public static void main(String[] args) {
    IntConsumer outprintln = System.out::println;
    IntConsumer errprintln = System.err::println;
    Arrays.stream(arr).forEach(outprintln.andThen(errprintln));
}
这里首先使用函数引用,直接定义了两个IntConsumer接口实例,一个指向标准输出,另一个指向标准错误。使用接口默认函数IntConsumer.addThen(),将两个IntConsumer进行组合,得到一个新的IntConsumer,这个新的IntConsumer会依次调用outprintln和errprintln,完成对数组中元素的处理。
其中errprintln.addThen()的实现如下(仅供参考):
default IntConsumer addThen(IntConsumer after) {
    Objects.requireNonNull(after);
    return (int t) -> {accept(t); after.accept(t);
}
可以看到,addThen()方法返回一个新的IntConsumer,这个新的IntConsumer会先调用第1个IntConsumer进行处理,接着调用第2个IntConsumer处理,从而实现多个处理器的整合。


注:本篇博客内容总结自《Java高并发程序设计》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值