一小时上手Java 8新特性
一小时上手Java 8新特性
本文摘译自 https://www.journaldev.com/2389/java-8-features-with-examples,并做了适当增补。
Iterable 接口里的 forEach() 方法
Java 8 在 java.lang.Iterable 接口里引入了forEach方法,所以我们可以只关注业务逻辑(不需要关注迭代细节)。
public class ForEach {
public static void main(String[] args) {
ArrayList<Integer> myList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
myList.add(i);
}
myList.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(".." + integer);
}
});
}
}
class MyConsumer implements Consumer<Integer> {
@Override
public void accept(Integer integer) {
}
}
接口中的default和static方法
如果仔细查看forEach例子中的细节的话,会注意到forEach方法是定义在Iterable接口内的;但是我们知道接口并不能拥有方法体。
Java 8增强了接口的功能,可以使用default关键字来创建拥有方法实现的接口。Iterable接口的forEach方法实现如下:
/**
* Performs the given action for each element of the {@code Iterable}
* until all elements have been processed or the action throws an
* exception. Unless otherwise specified by the implementing class,
* actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* for (T t : this)
* action.accept(t);
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
我们知道Java是不支持类的多继承的,但是由于现在接口和抽象类更像了,我们可以使用接口来实现。如果一个类实现的多个接口里,有相同的default方法,那么它必须要实现自己的该方法。
接口里的static method (静态方法),可以通过接口名来调用,但是不能被重写。
Java 8在集合API里重度使用了default和static方法。
函数性接口和Lambda表达式
函数性接口是Java 8中引入的新概念:一个只有一个抽象方法的接口,被称为函数性接口。我们并不需要显示使用@FunctionalInterface 注解来声明一个接口成为函数性接口。@FunctionalInterface注解和@Override注解类似,用来帮助发现错误的操作。@FunctionalInterface注解用来避免意外向接口里添加额外方法。
Runnable接口内只有一个run方法,是函数性接口的一个很好的例子。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
使用函数性接口的一个重要好处是我们可以使用Lamba表达式来实例化一个接口。
使用匿名类实例化一个接口,但是代码看起来很笨重:
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("My Runnable");
}
};
使用Lamba表达式,来提供方法参数和业务逻辑:
Runnable r = () -> {
System.out.println("My Runnable");
};
如果实现里只有一行语句的话,我们甚至可以省掉花括号:
Runnable r = () -> System.out.println("My Runnable");
所以Lambda表达式意味着可以更简单的创建函数性接口的匿名类,但是Lambda表达式在运行时并没有任何额外的好处。如果不介意多写一点代码的,建议谨慎使用Lamba表达式。
Lamba表达式是个大话题,此处不展开细说。
批量操作集合数据的 Java Stream API
Java.util.stream 被添加到Java 8中,用来在集合上执行filter/map/reduce等操作。Stream API支持线性和并行执行。
filter
filter用来使用指定条件过滤集合。
示例代码:过滤出 > 90 的元素。
import java.util.ArrayList;
import java.util.stream.Stream;
public class StreamAPI {
public static void main(String[] args) {
ArrayList<Integer> myList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
myList.add(i);
}
//parallel stream
Stream<Integer> parallelStream = myList.parallelStream();
//sequential stream
Stream<Integer> sequentialStream = myList.stream();
Stream<Integer> highNums = parallelStream.filter(p -> p > 90);
highNums.forEach(p -> System.out.println("High Nums parallel=" + p));
Stream<Integer> sequentialHighNums = sequentialStream.filter(p -> p > 90);
sequentialHighNums.forEach(p -> System.out.println("High Nums sequential=" + p));
}
}
结果
High Nums parallel=93
High Nums parallel=94
High Nums parallel=95
High Nums parallel=98
High Nums parallel=91
High Nums parallel=96
High Nums parallel=92
High Nums parallel=99
High Nums parallel=97
High Nums sequential=91
High Nums sequential=92
High Nums sequential=93
High Nums sequential=94
High Nums sequential=95
High Nums sequential=96
High Nums sequential=97
High Nums sequential=98
High Nums sequential=99
可以看到filter Lambda表达式p -> p > 90,过滤出了大于90的元素。并且可以看到parallelStream()输出的结果是乱序的(由并发执行引起),而stream()是按照原顺序输出的。
map
map则是在每个元素上应用给定的函数做操作。
示例代码:如果元素大有5,则增加100。
import java.util.ArrayList;
import java.util.stream.Stream;
public class StreamAPI {
public static void main(String[] args) {
ArrayList<Integer> myList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
myList.add(i);
}
//parallel stream
Stream<Integer> parallelStream = myList.parallelStream();
//sequential stream
Stream<Integer> sequentialStream = myList.stream();
Stream<Integer> mapNums = parallelStream.map((p) -> {
if (p > 5) {
return p + 100;
} else {
return p;
}
});
mapNums.forEach(p -> System.out.println("High Nums parallel=" + p));
Stream<Integer> sequentialMapNums = sequentialStream.map((p) -> {
if (p > 5) {
return p + 100;
} else {
return p;
}
});
sequentialMapNums.forEach(p -> System.out.println("High Nums sequential=" + p));
}
}
结果
High Nums parallel=106
High Nums parallel=5
High Nums parallel=1
High Nums parallel=0
High Nums parallel=107
High Nums parallel=108
High Nums parallel=4
High Nums parallel=109
High Nums parallel=3
High Nums parallel=2
High Nums sequential=0
High Nums sequential=1
High Nums sequential=2
High Nums sequential=3
High Nums sequential=4
High Nums sequential=5
High Nums sequential=106
High Nums sequential=107
High Nums sequential=108
High Nums sequential=109
reduce
reduce是相对复杂的一个函数,他用来对集合元素做一些聚合操作,如求和、计数、最大值、最小值等等。
package com.alibaba.toolkit.demo.java8;
import java.util.ArrayList;
import java.util.Optional;
import java.util.stream.Stream;
public class StreamAPI {
public static void main(String[] args) {
ArrayList<Integer> myList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
myList.add(i);
}
//parallel stream
Stream<Integer> parallelStream = myList.parallelStream();
//sequential stream
Stream<Integer> sequentialStream = myList.stream();
Optional<Integer> sumResult = parallelStream.reduce((sum, i) -> {
return sum + i;
});
System.out.println("sumResult: " + sumResult.get());
Optional<Integer> sequentialSumResult = sequentialStream.reduce((sum, i) -> {
return sum + i;
});
System.out.println("sequentialSumResult: " + sequentialSumResult.get());
}
}
结果
sumResult: 45
sequentialSumResult: 45
reduce方法的第一个参数是当前的中间结果,第二个参数是当前遍历到的元素。
如果写完整的话,代码为
Optional<Integer> sequentialSumResult = stream.reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer sum, Integer i) {
return sum + i;
}
});
Java Time API
之前版本的Java,使用Date, Time, 和Time Zones都很繁琐,Joda-Time等库变得很流行。Java 8在java.time包中提供了对时间流式操作的新API。Java 8的Time API很大程度上也参考了Joda-Time。
import java.time.LocalDate;
import java.time.Month;
public class TimeAPI {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
System.out.println("Current Date=" + today);
today = LocalDate.of(2019, Month.MARCH, 31);
System.out.println("today=" + today);
LocalDate tomorrow = today.plusDays(1);
System.out.println("tomorrow=" + tomorrow);
LocalDate nextMonth = today.plusMonths(1);
System.out.println("nextMonth=" + nextMonth);
}
}
结果
Current Date=2019-03-31
today=2019-03-31
tomorrow=2019-04-01
nextMonth=2019-04-30
其他
Java 8 还增强了Collection API,Concurrency API,Java IO,以及众多的微小改进。篇幅所限,不一一展开了。
一小时上手Java 8新特性的更多相关文章
- Java 8新特性解读
(四)Java 8 相关知识 关于 Java 8 中新知识点,面试官会让你说说 Java 8 你了解多少,下面分享一我收集的 Java 8 新增的知识点的内容,前排申明引用自:Java8新特性及使用 ...
- Java 8 新特性——实践篇
Java 8 新特性--实践篇 参考 Java8新特性 重要更新:Lambda 表达式和Stream API Lambda 表达式 Lambda 表达式引入之前: 举个场景例子:当我们要对一个班级里的 ...
- Java 8新特性-4 方法引用
对于引用来说我们一般都是用在对象,而对象引用的特点是:不同的引用对象可以操作同一块内容! Java 8的方法引用定义了四种格式: 引用静态方法 ClassName :: staticMetho ...
- Spring 4支持的Java 8新特性一览
有众多新特性和函数库的Java 8发布之后,Spring 4.x已经支持其中的大部分.有些Java 8的新特性对Spring无影响,可以直接使用,但另有些新特性需要Spring的支持.本文将带您浏览S ...
- java 8 新特性
最近在IDEA的️驱使下,看了点java8的东西,链接贴一下,,,,, 1.Java 8新特性概述2.Java 8中的 Stream API 详解[3.Java 8新特性终极指南] 简单的使用看完新特 ...
- Java 8 新特性终极版
声明:本文翻译自Java 8 Features Tutorial – The ULTIMATE Guide,翻译过程中发现并发编程网已经有同学翻译过了:Java 8 特性 – 终极手册,我还是坚持自己 ...
- Java 8新特性前瞻
快端午小长假了,要上线的项目差不多完结了,终于有时间可以坐下来写篇博客了. 这是篇对我看到的java 8新特性的一些总结,也是自己学习过程的总结. 几乎可以说java 8是目前为止,自2004年jav ...
- Java 8新特性探究(八)精简的JRE详解
http://www.importnew.com/14926.html 首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 Java小组 工具资源 - 导航条 - 首页 所有文章 资讯 ...
- Java 8 新特性1-函数式接口
Java 8 新特性1-函数式接口 (原) Lambda表达式基本结构: (param1,param2,param3) -> {代码块} 例1: package com.demo.jdk8; i ...
随机推荐
- 服务器启动socket服务报错 java.net.BindException:Cannot assign requested address
错误信息: 2017-06-13 11:18:00,865 [GateServer.java:82][ERROR]:启动服务出错了java.net.BindException: Cannot ass ...
- git官网和安装使用教程链接
git官网 https://git-scm.com/download/win git安装教程 https://www.cnblogs.com/wj-1314/p/7993819.html
- day13.装饰器进阶,迭代器
1.from functools import wraps 这个函数可以保留原来函数的属性 # from functools import wraps def car_time(fun): # @wr ...
- Servlet(八):ServletContext对象和ServletConfig对象
ServletContext 对象:问题: Request 解决了一次请求内的数据共享问题,session 解决了用户不同请求的数据共享问题,那么不同的用户的数据共享该怎么办呢?解决: 使用 Serv ...
- Linux中的 openssl-opensslv
问题 在安装内核模块系统突然出现以下错误 寻找问题 一开始我以为是openssl没有安装,故先进行openssl的检查: 输入yum info openssl 从图中可知,openssl是已经安装过了 ...
- 20172328 2018-2019《Java软件结构与数据结构》第五周学习总结
20172328 2018-2019<Java软件结构与数据结构>第五周学习总结 概述 Generalization 本周学习了第九章:排序与查找,主要包括线性查找和二分查找算法和几种排序 ...
- VS的Mvc项目右键没有控制器右键菜单(转)
今天遇到了一个比较少见的问题,我用vs2012打开一个从Svn上拉下来的mvc5项目,在Controller文件夹上右键却发现没有新建控制器的选项,在View文件夹上右键也没有新建视图的选项. 我的第 ...
- STS的安装以及IDEA安装和破解过程
一.STS的下载 1·下载地址:直接百度搜索STS,选择Download STS 3 2.选择电脑对应的版本 直接下载 3.安装包解压后在有jdk的情况下就可以直接使用 二.IDEA的安装 下载网址: ...
- Restful概念的理解和践行
在实习是leader有让我们实习生看restful相关的知识,奈何当初根基很浅,看了一篇博文,但是还是很难用自己的话来描述.现在又接触了Restful的内容,就补上一篇文章. 在Spring Fram ...
- Hibernate用注解方式实现一对多、多对多关系
一.一对多关系 1.在上一篇日志中用.xml配置文件项目基础上,再往lib目录先添加一个包-hibernate-jpa-2.0-api-1.0.0.Final.jar 2.新建一个com.st.bea ...