JDK8新特性

Lambda表达式

Lambda是一个匿名函数,可以理解为一段可传递的代码,将代码将数据一样进行传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* @author zyz
* @description lambda表达式的写法
* 格式:lambda参数列表(接口中的抽象方法的形参列表)->lambda体(重写的抽象方法的方法体)
* lambda表达式的本质:作为函数式接口的一个实例
* 函数式接口:@FunctionalInterface 只声明了一个抽象方法的接口
* @create 2020-03-24 11:09
*/
public class LambdaTest1 {
@Test // 方式一:无参,无返回值,一条执行语句 (可以省略return)
public void test1(){
Runnable r1 = ()-> System.out.println("歪比巴卜");
r1.run();
}

@Test // 方式二:一个参数,无返回值 参数数据类型可以省略(编译器类型推断)
public void test2(){
Consumer<String> c1 = (String s)-> {
System.out.println(s);
};
c1.accept("茉莉~");
}

@Test // 方式三:一个参数,参数的小括号可以省略
public void test3(){
Consumer<String> c1 = s -> {
System.out.println(s);
};
//方法引用 使用操作符“::” 将类(或对象) 与方法名分隔开来。
// Consumer<String> c1 = System.out::println;
c1.accept("起 飞");
}

@Test // 方式四:两个或以上的参数,多条执行语句
public void test4(){
Comparator<Integer> com1 = (o1,o2)->{
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com1.compare(1,2));
}
}

Lambda表达式的应用

forEach 遍历Map

1
2
3
4
5
6
7
8
Map<String,Object> map = new HashMap<String,Object>();
map.put("key1", 1);
map.put("key2", 2);
map.put("key3", 3);
map.put("key4", 4);
map.forEach((key,value) -> {
System.out.println("key:" + key + ",value:" + value);
})

forEach 遍历List

1
2
3
4
5
6
7
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.forEach(value -> {
System.out.println("value:" + value);
})

创建并开启线程

1
new Thread(()->System.out.println("new Thread start")).start();

Stream 流

以集合为例,一个流式处理的操作我们首先需要调用stream()函数将其转换成流,然后再调用相应的中间操作达到我们需要对集合进行的操作,比如筛选、转换等,最后通过终端操作对前面的结果进行封装,返回我们需要的形式。

常用api的使用

创建实体类

1
2
3
4
5
6
7
8
@Data
@NoArgsConstructor
@AllArgsConstructor
class User{
private Long id;
private String name;
private Integer age;
private String school;

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<User> list = new ArrayList<User>(){
{
add(new User(1L,"张三",10, "清华大学"));
add(new User(2L,"李四",12, "清华大学"));
add(new User(3L,"王五",15, "清华大学"));
add(new User(4L,"赵六",12, "清华大学"));
add(new User(5L,"田七",25, "北京大学"));
add(new User(6L,"小明",16, "北京大学"));
add(new User(7L,"小红",14, "北京大学"));
add(new User(8L,"小华",14, "浙江大学"));
add(new User(9L,"小丽",17, "浙江大学"));
add(new User(10L,"小何",10, "浙江大学"));
}
};

filter 过滤

1
2
3
4
5
6
7
// 筛选出学校是清华大学的所有用户并打印输出他们的姓名
List<User> userList = list.stream()
.filter(user -> "清华大学".equals(user.getSchool()))
.collect(Collectors.toList());
userList.forEach(user -> {
System.out.print(user.getName() + " ");
});

输出结果:

1
张三 李四 王五 赵六

distinct

1
2
3
4
5
6
7
8
9
10
// distinct 获取所有user的年龄(年龄不重复)
// map 方法用于映射每个元素到对应的结果
// List<Integer> userAgeList = list.stream().map(User::getAge)
List<Integer> userAgeList = list.stream()
.map(user -> user.getAge())
.distinct()
.collect(Collectors.toList());
userAgeList.forEach(age -> {
System.out.print(age + " ");
});

输出结果:

1
18 20 16 19 25 22 21

limit 返回前n个元素的流,当集合长度小于n时,则返回所有集合

1
2
3
4
5
6
7
8
// 获取年龄是偶数的前2名user
List<User> userList2 = list.stream()
.filter(user -> user.getAge() % 2 == 0)
.limit(2)
.collect(Collectors.toList());
userList2.forEach(user -> {
System.out.print(user.getName() + " ");
});
1
张三 李四

sorted

1
2
3
4
5
// 将所有user按年龄从大到小排序
List<User> userList3 = list.stream()
.sorted((user1, user2) -> user2.getAge() - user1.getAge())
.collect(Collectors.toList());
System.out.println(userList3);

输出结果:

1
[User{id=5, name='田七', age=25, school='北京大学'}, User{id=8, name='小华', age=22, school='浙江大学'}, User{id=9, name='小丽', age=21, school='浙江大学'}, User{id=2, name='李四', age=20, school='清华大学'}, User{id=7, name='小红', age=20, school='北京大学'}, User{id=4, name='赵六', age=19, school='清华大学'}, User{id=1, name='张三', age=18, school='清华大学'}, User{id=10, name='小何', age=18, school='浙江大学'}, User{id=3, name='王五', age=16, school='清华大学'}, User{id=6, name='小明', age=16, school='北京大学'}]

skip 跳过几个元素再输出

1
2
3
4
5
6
// 跳过前两个user,输出之后的user
List<User> userList4 = list
.stream()
.skip(2)
.collect(Collectors.toList());
System.out.println(userList4);

输出结果:

1
[User{id=3, name='王五', age=16, school='清华大学'}, User{id=4, name='赵六', age=19, school='清华大学'}, User{id=5, name='田七', age=25, school='北京大学'}, User{id=6, name='小明', age=16, school='北京大学'}, User{id=7, name='小红', age=20, school='北京大学'}, User{id=8, name='小华', age=22, school='浙江大学'}, User{id=9, name='小丽', age=21, school='浙江大学'}, User{id=10, name='小何', age=18, school='浙江大学'}]

map 映射元素结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 筛选出学校是清华大学的所有学生
List<String> nameList = list.stream()
.filter(user -> "清华大学".equals(user.getSchool()))
.map(user -> user.getName())
.collect(Collectors.toList());
System.out.println(nameList);

/**
* 除了上面这类基础的map,java8还提供了mapToDouble(ToDoubleFunction<? super T> mapper),
* mapToInt(ToIntFunction<? super T> mapper),
* mapToLong(ToLongFunction<? super T> mapper),
* java8为这些流设定了一些特殊的操作
*/
// 统计学校为北京大学的所有用户的人数
long count = list.stream()
.filter(user -> "北京大学".equals(user.getSchool()))
.mapToInt(user -> user.getAge()).count();
System.out.println("北京大学用户的人数:" + count);

输出结果:

1
2
[张三, 李四, 王五, 赵六]
北京大学用户的人数:3

匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// allMatch
// 用于检测是否全部都满足指定的参数行为,如果全部满足则返回true
// 判断所有用户的年龄是否都大于18岁
boolean isAllAdult = list.stream().allMatch(user -> user.getAge() > 18);
System.out.println(isAllAdult);

// anyMatch
// 检测是否存在一个或多个满足指定的参数行为,如果满足则返回true
// 判断是否有大于18岁的用户
boolean isAnyAdult = list.stream().anyMatch(user -> user.getAge() > 18);
System.out.println(isAnyAdult);

// noneMatch  
// 检测是否不存在满足指定行为的元素,如果不存在则返回true

输出结果:

1
2
false
true

findFirst 用于返回满足条件的第一个元素

1
2
3
4
5
Optional<User> first = list.stream()
.filter(user -> user.getAge() == 18)
.findFirst();
User user = first.get();
System.out.println(user);

输出结果:

1
User{id=1, name='张三', age=18, school='清华大学'}

counting 计算个数

1
2
3
// Long counting = list.stream().collect(Collectors.counting());
long counting = list.stream().count();
System.out.println("总人数:"+counting);

输出结果:

1
总人数:10

maxBy minBy 计算最大值 最小值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Integer maxAge = list.stream()
.collect(Collectors.maxBy((user1, user2) -> user1.getAge() - user2.getAge()))
.get().getAge();
Integer minAge = list.stream()
.collect(Collectors.minBy((user1, user2) -> user1.getAge() - user2.getAge()))
.get().getAge();
System.out.println("最大年龄:" + maxAge);
System.out.println("最小年龄:" + minAge);
// 方式二: 使用比较器
Integer maxAge2 = list.stream()
.collect(Collectors.maxBy(Comparator.comparing(User::getAge)))
.get()
.getAge();
Integer minAge2 = list.stream()
.collect(Collectors.minBy(Comparator.comparing(User::getAge)))
.get()
.getAge();
System.out.println("最大年龄:" + maxAge2);
System.out.println("最小年龄:" + minAge2);

输出结果:

1
2
3
4
最大年龄:25
最小年龄:16
最大年龄:25
最小年龄:16

summingInt、summingLong、summingDouble 计算总和

1
2
Integer ageSum = list.stream().collect(Collectors.summingInt(User::getAge));
System.out.println("年龄总合为:" + ageSum);

输出结果:

1
年龄总合为:195

averageInt、averageLong、averageDouble 计算平均值

1
2
Double ageAverage = list.stream().collect(Collectors.averagingInt(User::getAge));
System.out.println("年龄平均值:" + ageAverage);

输出结果:

1
年龄平均值:19.5

summarizingInt、summarizingLong、summarizingDouble

一次性查询元素个数、总和、最大值、最小值和平均值

1
2
3
IntSummaryStatistics collect = list.stream()
.collect(Collectors.summarizingInt(User::getAge));
System.out.println(collect);

输出结果:

1
IntSummaryStatistics{count=10, sum=195, min=16, average=19.500000, max=25}

joining 字符串拼接

1
2
3
4
String names = list.stream()
.map(User::getName)
.collect(Collectors.joining(","));
System.out.println(names);

输出结果:

1
张三,李四,王五,赵六,田七,小明,小红,小华,小丽,小何

groupingBy 分组

1
2
3
4
// 根据大学划分用户
Map<String, List<User>> userBySchool = list.stream()
.collect(Collectors.groupingBy(User::getSchool));
System.out.println(userBySchool);

输出结果:

1
{浙江大学=[User{id=8, name='小华', age=22, school='浙江大学'}, User{id=9, name='小丽', age=21, school='浙江大学'}, User{id=10, name='小何', age=18, school='浙江大学'}], 北京大学=[User{id=5, name='田七', age=25, school='北京大学'}, User{id=6, name='小明', age=16, school='北京大学'}, User{id=7, name='小红', age=20, school='北京大学'}], 清华大学=[User{id=1, name='张三', age=18, school='清华大学'}, User{id=2, name='李四', age=20, school=

partitioningBy 分区

1
2
3
4
// 按照是否是清华大学的user将所有user分为两个部分
Map<Boolean, List<User>> userByQinghua = list.stream()
.collect(Collectors.partitioningBy(user1 -> "清华大学".equals(user1.getSchool())));
System.out.println(userByQinghua);

输出结果:

1
{false=[User{id=5, name='田七', age=25, school='北京大学'}, User{id=6, name='小明', age=16, school='北京大学'}, User{id=7, name='小红', age=20, school='北京大学'}, User{id=8, name='小华', age=22, school='浙江大学'}, User{id=9, name='小丽', age=21, school='浙江大学'}, User{id=10, name='小何', age=18, school='浙江大学'}], true=[User{id=1, name='张三', age=18, school='清华大学'}, User{id=2, name='李四', age=20, school='清华大学'}, User{id=3, name='王五', age=16, school='清华大学'}, User{id=4, name='赵六', age=19, school='清华大学'}]}