项目中偶有使用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