项目中偶有使用Java8,了解一些基本的用法,但是没有来得及系统的学习,所以一些概念比较模糊,没有理解透彻,最近把一些教程和书籍细细地看了一下,觉得豁然开朗了许多,之前有些不理解的概念也理清了,在这里总结了一下。
在Java8中,会看到很多类似下面风格的代码:使用Labmda表达式。这种写法就是一种声明式的写法:告诉计算机要做什么,而不是怎么做。
//我们通过函数声明式的过滤出我们想要的结果。而不是在写个for循环做条件判断,然后筛选结果(过程式) Arrays.asList(1, 3, 4, 5, 10).stream().filter(v -> v > 5).collect(Collectors.toList()); 复制代码
只有一个抽象方法,可有多个默认实现的接口。定义一个函数接口,如下:
@FunctionalInterface //添加这个注解后,编译器会检查当前的接口是否符合函数接口规范 public interface Formula { double calucalte(int value); default int sum(int v1, int v2) { //默认实现方法,当实现接口时可以不实现 return v1 + v2; } default double maxValue(Double... values) {//计算所给参数的最大值 return Arrays.stream(values).max(Double::compareTo).orElse(0.0); } } 复制代码
之前的接口好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类。对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。我觉得这里就解释的很好: 链接
使得对接口的实现更加简单明了,代码更加清晰,对上面的代码进行测试:
//Java8以前的做法:实例化接口 Formula formu = new Formula() { @Override public double calucalte(int value) { return sum(value, 10);//可以直接调用接口中的默认实现方法 } }; System.out.println(formu.calucalte(10)); //使用Lambda表达式的做法:本质上还是接口实现。 Formula formula = a -> a + 1;//语法:参数列表->Lambda主体(相当于函数接口的实现),编译器会对参数类型进行判断 System.out.println(formula.maxValue()); 复制代码
在Java的核心类库中,经常可以看到在方法中传递函数,下图是 Collections
类中的一个方法:
//Java8之前: List<Integer> values = Arrays.asList(9, 1, 2, 4, 5); Collections.sort(values, new Comparator<Integer>() {//往方法中传递函数的代码,该方法需要用到函数的执行结果 @Override public int compare(Integer o1, Integer o2) { return o1.compareTo(o2); } }); //Java8:一行代码解决 Collections.sort(values, Integer::compareTo);//方法引用:复用已存在的方法 复制代码
JDK中提供了很多实用的函数接口,大概列出了一些,具体可看下API文档,在使用过程看下源码可以理解的更透彻。 Stream API
中很多方法使用了这些函数接口。
函数接口 | 抽象方法 | 说明 |
---|---|---|
Predicate 断定型 | boolean test(T t); | 确定给定类型参数是否满足某种约束 |
Consumer 消费型 | void accept(T t); | 对给定类型参数进行操作 |
Supplier 供给型 | T get(); | 返回结果 |
R apply(T t) 函数性 | R apply(T t); | 对T类型进行操作、返回R类型结果 |
//Strem类中的filter方法:通过某种规则进行过滤。 Stream<T> filter(Predicate<? super T> predicate); //使用时用Lambda表达式实现接口 List list = Stream.of(1, 3, 4, 5, 10).filter(v -> v > 5).collect(Collectors.toList()); 复制代码
如何从值序列、数组、文件来构建流?可用 Stream.of()
、 Arrays.stream()
方法
//由值构建 String s = "sunnyDay"; List list = Stream.of(s).collect(Collectors.toList());//使用Stream.of()构建流 //由数组构建 int[] numbers = {2, 0, 2, 0}; int sum = Arrays.stream(numbers).sum(); 复制代码
对 stream
中的元素作汇总:生成List、Map