内容简介:Java8的改进比历史上任何一次改变都比较深远。Java不断改进也是编程语言生态变化的使然——诸如大数据需要在多核上面运行,而Java此前是不支持这种操作的。在Java8之前,如果想要利用多个计算机的内核,你要使用线程,并且要处理复杂的同步逻辑。但是在Java8中,你可以很容易地使用流让自己的代码在多个内核上面执行。此外,它还借鉴了其他语言和开源库的内容,比如Scala、Guava等。我们总结一下Java8的主要几个特征或者改进:
Java8的改进比历史上任何一次改变都比较深远。Java不断改进也是编程语言生态变化的使然——诸如大数据需要在多核上面运行,而 Java 此前是不支持这种操作的。
在Java8之前,如果想要利用多个计算机的内核,你要使用线程,并且要处理复杂的同步逻辑。但是在Java8中,你可以很容易地使用流让自己的代码在多个内核上面执行。
此外,它还借鉴了其他语言和开源库的内容,比如Scala、Guava等。我们总结一下Java8的主要几个特征或者改进:
- 函数式编程和Lambda表达式;
- 流(Stream)编程;
- 时间API的改进;
- 默认方法
2、行为参数化
“行为”就是指方法,“行为参数化”就是指将方法作为参数传入,说白了就是指 策略模式 。而Java8只是使用了Lambda表达式简化了匿名类的代码,使匿名类看起来更加简洁。在这块内容上,你所需要掌握的东西并不多。
2.1 Lambda表达式基本语法
(parameters) -> expression // 表达式
(parameters) -> {statements;} // 语句,语句尾带分号且要用花括号括起来
上面是Lambda的基本语法,第一行中是Lambda中使用表达式的情况,第二行中式Lambda中使用语句的情况。
下面是一些使用Lambda表达式的示例:
public static void main(String...args) {
// 创建对象
ICreateObject createObject = Employee::new;
IExpression expression = employees -> employees.get(0);
// 可以进一步简化为 IExpression expression2 = List::isEmpty;
IExpression expression2 = employees -> employees.isEmpty();
IConsumeObject consumeObject = employee -> System.out.println(employee.name);
IAdd add = (a, b) -> a + b;
IAdd add1 = Java8LambdaExample::cal;
// 会报出不是Function接口异常
// Object object = Employee::new;
}
从上面的示例代码,我们可以总结出一些结论:
@FunctionalInterface -> 函数接口
下面我们总结一些常见的方法引用的示例:
上面代码中的 Employee::new
就是所谓的方法引用,下面是常见的方法引用的例子:
| 编号 | Lambda | 等效的方法引用 |
|---|---|---|
| 1 |
(Employee e)->e.getName()
|
Employee::getName
|
| 2 |
(String s) -> System.out.println(s)
|
System.out::println
|
| 3 |
(str, i) -> str.substring(i)
|
String::substring
|
所以,我们总结下来的三种方法引用的情形:
| 编号 | Lambda | 等效的方法引用 |
|---|---|---|
| 1 |
(参数) -> 类名.静态方法(参数)
|
类名::静态方法
|
| 2 |
(参数1, 其他参数) -> 参数1.实例方法(其他参数)
|
类名::实例方法
|
| 3 |
(参数) -> 表达式.实例方法(参数)
|
表达式::实例方法
|
2.2 Java API 中的函数式接口
Java8的API中为我们提供了几个函数式接口,这些接口有必要了解一下。因为自从Java8开始接口可以定义默认方法了,所以这些接口里面又提供了一些有意思的默认方法。这可能对我们编程比较有帮助。
public interface Predicate<T> {
boolean test(T t);
}
public interface Consumer<T> {
void accept(T t);
}
public interface Function<T, R> {
R apply(T t);
}
上面就是这三个接口的定义。它们的应用场景的不同就体现再返回的参数上面:
- 第一个用来判断的,大致用来实现过滤的效果;
- 第二是没有返回类型,只能用来对传入的参数进行处理;
- 第三个是用来映射的,也就是说,当你想要实现的行为的参数和返回是不同的类型的时候可以用它(当然,如果是相同类型的话也是可以的)。
因为对于数值类型,Java需要做额外的装箱和拆箱的操作,这是需要成本的。所以,对于上面的三个接口(其他的接口也是),Java8中提供了不需要装箱的版本,也就是从泛型变成了数值类型而已。以IntPredicate为例:
public interface IntPredicate {
boolean test(int value);
}
2.3 复合Lambda表达式
Java8中提供的一些接口还是可以复合操作的。使用复合操作可以实现更复杂的逻辑。这些复合操作是以默认方法的形式定义的,每个函数式接口略有不同。所以,我们这里只列举出部分用于复合的方法。在实际的开发过程中,你可以直接进入到指定的函数式接口中查看这些方法的定义。
2.3.1 比较器Comparator
假设有一个数据列表employees,其中的对象是Employee,它有getName()和getAge()两个方法。
employees.sort(Comparator.comparing(Employee::getName)); employees.sort(Comparator.comparing(Employee::getName).reversed().thenComparing(Employee::getAge));
上面的两行代码中,第一行实现对employees按照getName()的结果进行排序。第二行代码对employees,先按照getName()的结果进行排序,然后将返回的结果逆序,再按照getAge()的结果进行排序。
2.3.2 谓词复合 negate()、or()和and()
Predicate<Employee> employeePredicate = (employee -> employee.getAge() > 13) employeePredicate.negate() employeePredicate.and(employee -> employee.getAge() <= 15).or(employee -> "LiHua".equals(employee.getName()))
这里首先定义了employeePredicate,它可以用来过滤“年龄大于13的雇员”。对其调用了negate()方法将返回一个Predicate,可以用来过滤“年纪小于等于13的雇员”。最后的复合操作则表示“年龄大于13并且小于15的雇员或者名字为LiHua的雇员”。
注意,这里的and和or操作的顺序是从左向右的,也就是 a.or(b).and(c)
将被看作 (a || b) and c
。
2.3.3 函数Function复合
Function有andThen和compose两个默认方法,它们都会返回一个Function实例。
Function<Integer, Integer> f = x -> x + 1; Function<Integer, Integer> g = x -> x * 2; Function<Integer, Integer> h1 = f.andThen(g); // h1(x) = g(f(x)) = (x + 1) * 2 Function<Integer, Integer> h2 = f.compose(g); // h2(x) = f(g(x)) = (x * 2) + 1 System.out.println(h1.apply(1)); System.out.println(h2.apply(1));
上面是Function的复合操作的示例,其实它的效果就相当于数学中的复合函数。不过,应当注意一下两个方法的实际的复合效果是不同的。
总结
以上就是Java8改进的第一部分,总结一下:行为参数化其实就是策略模式,使用Lambda可以简化函数接口的形式;Java API中提供了一些有用的函数式接口,这些接口又可以使用复合方法实现更加强大的功能。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法竞赛入门经典(第2版)
刘汝佳 / 清华大学出版社 / 2014-6-1 / CNY 49.80
《算法竞赛入门经典(第2版)》是一本算法竞赛的入门与提高教材,把C/C++语言、算法和解题有机地结合在一起,淡化理论,注重学习方法和实践技巧。全书内容分为12 章,包括程序设计入门、循环结构程序设计、数组和字符串、函数和递归、C++与STL入门、数据结构基础、暴力求解法、高效算法设计、动态规划初步、数学概念与方法、图论模型与算法、高级专题等内容,覆盖了算法竞赛入门和提高所需的主要知识点,并含有大量......一起来看看 《算法竞赛入门经典(第2版)》 这本书的介绍吧!