Jdk1.8新特性
- Lambda表达式:Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。可以使代码变的更加简洁紧凑。
Lambda表达式的实质其实还是匿名内部类,而匿名内部类在访问外部局部变量时,要求变量必须声明为final
!不过我们在使用Lambda表达式时无需声明final
,这并不是说违反了匿名内部类的规则,因为Lambda底层会隐式的把变量设置为final
,在后续的操作中,一定不能修改该变量:
基本语法:
(参数列表) -> {代码块}
需要注意:
-
参数类型可省略,编译器可以自己推断
-
如果只有一个参数,圆括号可以省略
-
代码块如果只是一行代码,大括号也可以省略
-
如果代码块是一行,且是有结果的表达式,
return
可以省略
注意:事实上,把Lambda表达式可以看做是匿名内部类的一种简写方式。当然,前提是这个匿名内部类对应的必须是接口,而且接口中必须只有一个函数!Lambda表达式就是直接编写函数的:参数列表、代码体、返回值等信息,用函数来代替完整的匿名内部类
!
用法示例
@Test
public void lambdaDemo(){
//准备一个集合
List<Integer> list = Arrays.asList(1, 3, 5, 3, 1, 3, 67, 8);
// 对集合进行Jdk1.7写法,倒序和正序
Collections.sort(list,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
System.out.println(list);// [-15, 5, 10, 20, 25]
// Jdk1.8写法,参数列表的数据类型可省略: lambda表达式做排序
Collections.sort(list,(Integer a,Integer b)->{ return b-a; });
System.out.println(list);
// Jdk8写法 简洁版
// 因为代码块是一个有返回值的表达式,可以省略大括号以及return
Collections.sort(list,(a,b)->a-b);
System.out.println(list);
}
示例2:单个参数
还以刚才的集合为例,现在我们想要遍历集合中的元素,并且打印。
jdk1.8给集合添加了一个方法:foreach()
,接收一个对元素进行操作的函数:
// JDK1.7遍历并打印集合
for (Integer i : list) {
System.out.println(i);
}
// JDK1.8遍历并打印集合,因为只有一个参数,所以我们可以省略小括号:
list.forEach(i -> System.out.println(i));
Lambda表达式的实质其实还是匿名内部类,所以我们其实可以把Lambda表达式赋值给某个变量。
-
Lambda表达式是接口的匿名内部类的简写形式
-
接口必须满足:内部只有一个函数
-
其实这样的接口,我们称为函数式接口,我们学过的
Runnable
、Comparator
都是函数式接口的典型代表。但是在实践中,函数接口是非常脆弱的,只要有人在接口里添加多一个方法,那么这个接口就不是函数接口了,就会导致编译失败。Java 8提供了一个特殊的注解@FunctionalInterface
来克服上面提到的脆弱性并且显示地表明函数接口。而且jdk8版本中,对很多已经存在的接口都添加了@FunctionalInterface
注解,例如Runnable
接口:
另外,Jdk8默认提供了一些函数式接口供我们使用:
- Function类型接口
@FunctionalInterface
public interface Function<T, R> {
// 接收一个参数T,返回一个结果R
R apply(T t);
}
Function代表的是有参数,有返回值的函数。还有很多类似的Function接口:
接口名 | 描述 |
---|---|
BiFunction<T,U,R> |
接收两个T和U类型的参数,并且返回R类型结果的函数 |
DoubleFunction<R> |
接收double类型参数,并且返回R类型结果的函数 |
IntFunction<R> |
接收int类型参数,并且返回R类型结果的函数 |
LongFunction<R> |
接收long类型参数,并且返回R类型结果的函数 |
ToDoubleFunction<T> |
接收T类型参数,并且返回double类型结果 |
ToIntFunction<T> |
接收T类型参数,并且返回int类型结果 |
ToLongFunction<T> |
接收T类型参数,并且返回long类型结果 |
DoubleToIntFunction |
接收double类型参数,返回int类型结果 |
DoubleToLongFunction |
接收double类型参数,返回long类型结果 |
-
Consumer系列
@FunctionalInterface
public interface Consumer<T> {
// 接收T类型参数,不返回结果
void accept(T t);
}
-
Predicate系列
@FunctionalInterface
public interface Predicate<T> {
// 接收T类型参数,返回boolean类型结果
boolean test(T t);
}
- Supplier系列
@FunctionalInterface
public interface Supplier<T> {
// 无需参数,返回一个T类型结果
T get();
}
Streams流
新增 java.util.Stream API
把一个集合变成一个流, Lists.stream()
案例一、 对集合进行排序然后去除所有的偶数再把所有数*2
这些个所有操作只经过一次遍历,
@Test
public void streamLambdaDemo03() {
// 对集合进行排序然后去除所有的偶数再把所有数*2
List<Integer> list = Arrays.asList(1, 3, 5, 3, 1, 3, 67, 8);
//过滤偶数(传入一个参数然后返回一个参数)
list.stream().filter(i-> i%2!=0)// 打印 1,3,5,3,1,3,67
//把集合中的每个数据用函数处理
.map(i->i*2) // 打印 2,6,10,6,2,6,134
//排序
.sorted((i1,i2)->i1-i2) // 打印 2,2,6,6,6,10,134
//JDK1.8遍历并打印集合
.forEach(i-> System.out.println(i));
list.stream()
//加上parallel()方法还可以使这个流多线程处理极大的提高效率
.parallel()
.filter(i -> { System.out.println(Thread.currentThread().getName());
return i % 2 != 0; })// 打印 1,3,5,3,1,3,67
//把集合中的每个数据用函数处理
.map(i -> {
System.out.println(Thread.currentThread().getName());
return i * 2;
}) // 打印 2,6,10,6,2,6,134
//排序
.sorted((i1, i2) -> {
System.out.println(Thread.currentThread().getName());
return i1 - i2;
}) // 打印 2,2,6,6,6,10,134
//JDK1.8遍历并打印集合
.forEach(i -> System.out.println(i));
}
上一篇: JAVA网络爬虫的实现
下一篇: 网络爬虫原理详解及案例实现(二)
推荐阅读
-
*民族大学新校区什么时候搬迁?什么时候开始使用?附*民族大学新校区地址
-
Intellij IDEA 2017新特性之Spring Boot相关特征介绍
-
友盟+CEO朋新宇:DI进化,是选择更是态度
-
SQL学习笔记五去重,给新加字段赋值的方法
-
MySQL5.7 group by新特性报错1055的解决办法
-
12寸新MacBook可兼容大绝大部分第三方配件 甚至是充电器
-
C#6.0中你可能不知道的新特性总结
-
Spring MVC温故而知新系列教程之请求映射RequestMapping注解
-
超过40个新的改进 coreldraw x3图像软件包新功能揭密
-
教你如何免费看优酷 爱奇艺付费电影 新破解地址免费观看