0%

java stream操作

java stream操作

Stream是什么

Stream又称为流,可以将集合转换为一种流,对集合中的每个元素进行一系列的流式操作。

数据源 ——转换为–》流—-》进行中间操作—-》终止操作

多个中间操作可以连接起来形成一个流水线,除非流水线触发终止操作,否则中间操作不会执行任何处理,在终止操作时一次性全部处理

转化为流

使用stream()或者parallelStream()方法将集合转为流

中间操作

筛选

filter

过滤操作,只返回为true的数据

1
2
// filter方法接收的是Predicate
Stream<T> filter(Predicate<? super T> predicate);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* filter 接收lambda,从流中排除某些元素
*/
public static void testFilter(){
// 中间操作
// 使用的Predicate boolean test(T t);
Stream<String> stream = list.stream()
.filter(e ->
{
System.out.println("filter中间操作");
return e.equals("张三");
}
);
// 这时中间操作还没有执行执行
System.out.println("----中间操作结束----");
//终止操作:一次执行全部操作
stream.forEach(
System.out::println
);
}
distinct

去重

1
2
3
4
5
6
/**
* distinct 筛选,通过流所生成元素的hashCode()和equals()方法去重
*/
public static void testDistinct(){
list.stream().distinct().forEach(System.out::println);
}

切片

limit

返回前n个元素

1
2
3
4
5
6
/**
* limit 截断流,使其元素不超过给定数量
*/
public static void testLimit(){
list.stream().limit(2).forEach(System.out::println);
}
skip

去除(跳过)前n个元素

1
2
3
4
5
6
/**
* skip 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回空流
*/
public static void testSkip(){
list.stream().skip(2).forEach(System.out::println);
}
1
2
3
4
5
6
public static void testLimitAndSkip(){
System.out.println("--------先limit再skip---------");
list.stream().limit(2).skip(1).forEach(System.out::println);
System.out.println("--------先skip再limit---------");
list.stream().skip(1).limit(2).forEach(System.out::println);
}

注意:在limit和skip搭配使用的时候,两个的顺序不同会导致结果不同

  • 先进行limit,再进行skip时,会选择前两个数据,然后再跳过第一个数据,只会筛选出一条数据
  • 先进行skip,再进行limit时,会先跳过一条数据,在选择剩下数据的前两条,最终会筛选出两条数据

排序

sorted

排序可以有两种排序方式,第一种是进行排序的类要实现Comparable接口,第二种是在自己实现一个Comparator接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 /**
* sorted()自然排序 Comparable 所要排序的类必须实现Comparable接口
*/
public static void test(){
list.stream().map(User::getAge).sorted().forEach(System.out::println);
}

/**
* sorted(Comparator com) 定制排序(Comparator)
*/
public static void test1(){
list.stream().sorted(
(o1, o2) -> {
if(o1.getAge() > o2.getAge()){
return -1;
}
return 0;
}
).forEach(System.out::println);
}

映射

map

转换功能

1
2
// map方法接收的参数为Function接口
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
1
2
3
4
5
6
7
8
9
10
/**
* map 接收lambda,将元素转换为其他形式或提取信息。接收一个函数作为函数,
* 该函数会被应用到每个元素上,并将其映射成一个新的元素
*
* 如果函数返回的是一个流的话,使用map会使得流里存储着多个流
*/
public static void testMap(){
// 使用Function R apply(T t);
list.stream().map(User::getAge).forEach(System.out::println);
}
flatmap

将多个Stream合并成一个Stream

1
2
// flatMap方法接收的参数为Function接口
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* flatMap 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
*
* 如果函数返回的是一个流,使用flatMap会使得函数返回的流中的元素放到一个流中
*/
public static void testFlatMap(){
// 要求Function R apply(T t);中返回值是一个Stream流
List<String> add = new ArrayList<>();
add.add("添加元素");
List<String> strings = list.stream().map(User::getName).collect(Collectors.toList());
strings.stream().flatMap(
TestStreamApi1::joinStream
).forEach(System.out::println);
}

终止操作

allMatch

流中所有元素都要匹配给定的条件为true,否则为false 相当于且

1
2
3
4
5
6
7
8
9
/**
* allMatch测试
*/
public static void testAllMatch(){
boolean isSex = list.stream().allMatch(
l -> l.getSex() == 0
);
System.out.println(isSex);
}

anyMatch

流中有任意一条数据匹配给定的条件为true,否则为false 相当于并

1
2
3
4
5
6
7
8
9
/**
* anyMatch测试
*/
public static void testAnyMatch(){
boolean isSex = list.stream().anyMatch(
l -> l.getSex() == 0
);
System.out.println(isSex);
}

noneMatch

流中所有的数据都不匹配给定条件时为true,否则为false 相当于非

1
2
3
4
5
6
7
8
9
/**
* noneMatch测试
*/
public static void testNoneMatch(){
boolean isSex = list.stream().noneMatch(
l -> l.getSex() == 0
);
System.out.println(isSex);
}

findFirst

找到第一个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* findFirst测试
*/
public static void testFindFirst(){
User user = list.stream().sorted(
((o1, o2) -> {
if(o1.getAge() > o2.getAge()){
return -1;
} else if(o1.getAge() < o2.getAge()){
return 1;
}
return 0;
})
).findFirst().get();
System.out.println(user);
}

findAny

找到其中任意一个元素

1
2
3
4
5
6
7
8
9
/**
* findAny测试
*/
public static void testFindAny(){
User user = list.stream().filter(
l -> l.getSex() == 0
).findAny().get();
System.out.println(user);
}

count

返回流中元素的数量

1
2
3
4
5
6
7
/**
* count测试
*/
public static void testCount(){
long count = list.stream().count();
System.out.println(count);
}

max

返回流中根据比较之后的最大值元素

1
2
// max方法接收的是Comparator接口
Optional<T> max(Comparator<? super T> comparator);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* max测试
*/
public static void testMax(){
User user = list.stream().max(
((o1, o2) -> {
if(o1.getAge() > o2.getAge()){
return 1;
} else if(o1.getAge() < o2.getAge()){
return -1;
}
return 0;
})
).get();
System.out.println(user);
}

min

返回流中根据比较之后的最小值元素

1
2
// min方法接收的是Comparator接口
Optional<T> min(Comparator<? super T> comparator);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* min测试
*/
public static void testMin(){
User user = list.stream().min(
((o1, o2) -> {
if(o1.getAge() > o2.getAge()){
return 1;
} else if(o1.getAge() < o2.getAge()){
return -1;
}
return 0;
})
).get();
System.out.println(user);
}

归约和收集

归约reduce

使用reduce来进行运算,从一组值中生成一个值

1
2
// reduce方法接收的是BinaryOperator接口(二元运算操作)  
Optional<T> reduce(BinaryOperator<T> accumulator);
1
2
3
4
5
6
7
8
9
10
11
12
/**
* 归约 将流中元素反复结合起来,得到一个值
* reduce(T identity, BinaryOperator<T> accumulator) /BinaryOperator<T> accumulator/U identity,
* BiFunction<U, ? super T, U> accumulator,
* BinaryOperator<U> combiner
*/
public static void testReduce(){
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
// BinaryOperator 二元运算 R apply(T t, U u);
int sum = list.stream().reduce((x, y) -> x+y).get();
System.out.println(sum);
}

收集collect

根据不同的收集器collect(Collectors.toList())、collect(Collectors.toSet())来返回不同的集合

1
2
3
4
5
6
7
8
/**
* 收集 collect -- 将流转换为其他形式 接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
*/
public static void testCollect(){
// Collector是一个接口 有一个Collectors提供了各种转换方式
List<String> strings = list.stream().map(User::getName).collect(Collectors.toList());
System.out.println(strings);
}