Java 8 Lambda表达式,常用接口,Stream流式处理

Lambda

Lambda表达式

函数式接口

1
2
3
4
5
6
7
函数式接口:有且只有一个抽象方法的接口,称之为函数式接口
当然接口中可以包含其他的方法(默认,静态,私有)

`@FunctionalInterface`注解
作用:定义在接口上,可以检测接口是否是一个函数式接口
是:编译成功
否:编译失败(接口中没有抽象方法抽象方法的个数多余1个)

基本语法

()->{}

1
2
3
4
5
6
7
8
1. `()`参数,参数声明可以省略
数量=0,必须写成`()`
数量=1,可写成`(x)`,也可省略小括号直接写成`x`
数量>1,必须加上括号,例如两个参数可写成`(x,y)`
2. `->`传递,表示参数传递给方法体,不可省略
3. `{}`重写的方法体
无返回值,必须加上大括号`{}`,如果只有一行执行语句可省略大括号
有返回值,可直接写成`()->2`等同于`()->{return 2;}`

在这里插入图片描述

日志优化案例

在这里插入图片描述

使用场景

作为方法参数

在这里插入图片描述

作为方法返回值

在这里插入图片描述

对象名引用成员方法

在这里插入图片描述

类名引用静态方法

在这里插入图片描述

super引用父类方法

在这里插入图片描述

this引用本类方法

在这里插入图片描述

类构造器引用

在这里插入图片描述

数组构造器引用

在这里插入图片描述

常用接口

Supplier

提供者

1
2
3
4
5
@FunctionalInterface
public interface Supplier<T> {

T get();
}

在这里插入图片描述

Consumer

消费者

1
2
3
4
5
6
7
8
9
10
@FunctionalInterface
public interface Consumer<T> {

void accept(T t);

default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}

在这里插入图片描述

Predicate

布尔值函数

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
@FunctionalInterface
public interface Predicate<T> {

boolean test(T t);

default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}

default Predicate<T> negate() {
return (t) -> !test(t);
}

default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}

static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}

在这里插入图片描述

Function

类型转换函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@FunctionalInterface
public interface Function<T, R> {

R apply(T t);

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}

static <T> Function<T, T> identity() {
return t -> t;
}
}

在这里插入图片描述

Stream

Stream流式处理

思想

流式思想
所以流只能被消费一次。再次使用会有异常。请见异常案例
在这里插入图片描述

获取

获取Stream流

1
2
3
4
5
6
7
java.util.stream.Stream<T>是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
- 所有的Collection集合都可以通过stream默认方法获取流;
default Stream<E> stream​()
- Stream接口的静态方法of可以获取数组对应的流。
static <T> Stream<T> of​(T... values)
参数是一个可变参数,那么我们就可以传递一个数组

在这里插入图片描述

forEach

循环
在这里插入图片描述

filter

过滤
在这里插入图片描述

map

转换
在这里插入图片描述

count

统计
在这里插入图片描述

limit

限制
在这里插入图片描述

skip

跳过
在这里插入图片描述

concat

合并
在这里插入图片描述

distinct

去重
在这里插入图片描述

max

最大值
在这里插入图片描述

min

最小值
在这里插入图片描述

average

平均值
在这里插入图片描述

sum

求和
在这里插入图片描述

sorted

排序
在这里插入图片描述

toList

collect转List
在这里插入图片描述

toMap

collect转Map

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
44
45
46
47
48
49
50
51
52
53
54
55
56
public class Person
{

private Integer id;

private String name;

private String sex;

private Integer age;

省略构造/set/get/toString
}

List<Person> personList = Arrays.asList(
new Person(1, "大牛", "男", 11),
new Person(2, "二蛋", "女", 22),
new Person(3, "三驴", "男", 33),
new Person(4, "四毛", "男", 55),
new Person(5, "五虎", "女", 55),
new Person(6, "六豹牛", "男", 55));


/*Id,对应对象*/
Map<Integer, Person> collect3 = personList.stream().collect(Collectors.toMap(Person::getId, p -> p));
System.out.println(collect3);
/*
{1=Person{id=1, name='大牛', sex='男', age=11},
2=Person{id=2, name='二蛋', sex='女', age=22},
3=Person{id=3, name='三驴', sex='男', age=33},
4=Person{id=4, name='四毛', sex='男', age=55},
5=Person{id=5, name='五虎', sex='女', age=55},
6=Person{id=6, name='六豹牛', sex='男', age=55}}
*/

/*Id,对应名字*/
Map<Integer, String> collect4 = personList.stream().collect(Collectors.toMap(Person::getId, Person::getName));
System.out.println(collect4);
/*
{1=大牛, 2=二蛋, 3=三驴, 4=四毛, 5=五虎, 6=六豹牛}
*/

/*年龄,对应姓名
* (k1, k2) -> k1) 姓名不覆盖
* (k1, k2) -> k2) 姓名覆盖
* */
Map<Integer, String> collect6 = personList.stream().collect(Collectors.toMap(Person::getAge, Person::getName, (k1, k2) -> k1));
System.out.println(collect6);
/*
{33=三驴, 22=二蛋, 55=四毛, 11=大牛}
*/


//案例:把data_init的转为 Map<String, String>
Map<String, Object> data_init = (Map<String, Object>) entry.getValue();
Map<String, String> data = data_init.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, node -> node.getValue().toString()));

groupingBy

分组

1
2
3
4
5
6
7
8
9
/*按照年龄分组*/
Map<Integer, List<Person>> collect5 = personList.stream().collect(Collectors.groupingBy(Person::getAge));
System.out.println(collect5);
/*
{33=[Person{id=3, name='三驴', sex='男', age=33}],
22=[Person{id=2, name='二蛋', sex='女', age=22}],
55=[Person{id=4, name='四毛', sex='男', age=55}, Person{id=5, name='五虎', sex='女', age=55}, Person{id=6, name='六豹牛', sex='男', age=55}],
11=[Person{id=1, name='大牛', sex='男', age=11}]}
*/