Java常用的stream流操作,附源码
- 问题背景
- stream操作方法
- 1 去重
- 2 对象无序去重, 通过name去重
- 3 对象无序去重, 通过name且age去重,注意:不是先使用name去重,再使用age去重
- 3.1 对象有序去重
- 4 整个对象去重, 使用distinct需要重写User的equals和hashcode
- 5 流的基本操作
- 6 取出List中某个属性值
- 7 转为排序的list
- 8 转为set集合
- 9 转为map
- 10 转换为一个数组
- 11 取出最大值
- 12 取出最小值
- 13 返回总个数
- 15 求总和
- 16 anyMatch:只要流中有一个元素满足条件则返 回 true,否则返回 false
- 17 allMatch: 当流中每个元素都符合条件时才返 回 true,否则返回 false
- 18 取出第一个元素
- 19 数组与list的相互转换
- 20 name为key,age为value,如果key重复,取后一个v2值
- 21 升序排序
- 22 降序排序
- 23 排序并去重
- 24 根据两个字段排序
- 25 根据中文字段排序
- 26 通过对象里面的某个字段进行分组
- 27 通过对象里面的某个字段映射为Map
- 28 List<String>转为List<Long>
- 29 List<Long>转为List<String>
- 总结
- Lyric: 包括像猫的狗
问题背景
java8的新特性非常有亮点,stream用起来爽歪歪
注意事项:
- 可以自己创建工程,也可以下载源码进行参考
中间操作
- filter:过滤流中的某些元素,
- sorted(): 自然排序,流中元素需实现 Comparable 接口 。
- distinct: 去除重复元素
- limit(n): 获取 n 个元素
- skip(n): 跳过 n 元素,配合 limit(n)可实现分页 map(): 将其映射成一个新的元素
终端操作
- forEach: 遍历流中的元素
- toArray: 将流中的元素倒入一个数组
- min: 返回流中元素最小值
- max: 返回流中元素最大值
- count: 返回流中元素的总个数
- reduce: 所有元素求和
- anyMatch: 接收一个 Predicate 函数,只要流中有一个元素满足条件则返 回 true,否则返回 false
- allMatch: 接收一个 Predicate 函数,当流中每个元素都符合条件时才返 回 true,否则返回 false
- findFirst:返回流中第一个元素
- collect: 将流中的元素倒入一个集合,Collection 或 Map
stream操作方法
导入类
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.ArrayUtils;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
1 去重
List<String> list = new ArrayList<>();
list.add("a");
list.add("a");
List<String> listDistinct = list.stream().distinct().collect(Collectors.toList());
System.out.println(listDistinct);
2 对象无序去重, 通过name去重
List<User> userList = new ArrayList();
userList.add(new User("yuange", 12));
userList.add(new User("yuange", 12));
userList.add(new User("yuange1", 14));
userList.add(new User("yuange1", 15));
userList.add(new User("pangpang", 12));
userList.add(new User("pangpang", 12));
List<User> result = userList.stream()
.collect(collectingAndThen(toCollection(() ->
new TreeSet<>(comparing(User::getName))), ArrayList::new));
result.forEach(System.out::println);
3 对象无序去重, 通过name且age去重,注意:不是先使用name去重,再使用age去重
List<User> result1 = userList.stream()
.collect(collectingAndThen(toCollection(() ->
new TreeSet<>(comparing(o -> o.getName() + ";" + o.getAge()))), ArrayList::new));
result1.forEach(System.out::println);
3.1 对象有序去重
public class StreamUtils{
//LinkedHashMap有序去重
private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
LinkedHashMap<Object, Boolean> map = new LinkedHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
//ConcurrentHashMap无序去重
private static <T> Predicate<T> distinctByKeyMap(Function<? super T, Object> keyExtractor) {
ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}
List<User> list = new ArrayList<User>();
list.add(new User("小南", 23, "18335888888"));
list.add(new User("小南", 22, "18335888888"));
list.add(new User("小南", 21, "18335888888"));
list.add(new User("小南", 20, "18335888888"));
list = list.stream().filter(StreamUtils.distinctByKey(User :: getName)).collect(Collectors.toList());
System.out.println(list.toString());
4 整个对象去重, 使用distinct需要重写User的equals和hashcode
List<User> result2 = userList.stream().distinct().collect(Collectors.toList());
result2.forEach(System.out::println);
5 流的基本操作
Integer[] integers = new Integer[]{2, 4, 3, 6, 1, 7, 5, 5, 7};
List<Integer> list1 = Arrays.asList(integers);
//list1.stream()等价于Stream.of(2,4,3,6,1,7,5,5,7)
list1.stream()
//中间操作
.filter((e) -> {
return e > 3;
}) //使用Lambda的表达式 表示大于3的留下
//filter的结果为 4,6,7,5,5,7
.sorted() //自然排序,流中元素需实现
//sorted的结果为 4,5,5,6,7,7
.distinct() //去除重复元素
//distinct的结果为 4,5,6,7
.skip(1) //跳过 n 元素 这里意思跳过1个元素,从第二个开始
//skip的结果为 5,6,7
.limit(2) //获取 n 个元素 这里获取了两个元素
//limit的结果为 5,6
//终端操作
.forEach((a) -> {
System.out.println(a);
});
6 取出List中某个属性值
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("小智", 12));
arrayList.add(new User("张三", 12));
arrayList.add(new User("蕾姆", 14));
arrayList.add(new User("亚当", 11));
arrayList.add(new User("夏娃", 7));
arrayList.stream()
//map(方法)将某一个值映射到Stream
//Apple::getNumber意思是将Apple对象中的number 转换为Stream中的流
.map(User::getName)
//之下的操作就是对Apple中所有的number数据进行操作
.forEach((e) -> {
System.out.println(e);
});
arrayList.stream().map(User::getName).collect(Collectors.toList());
7 转为排序的list
List<User> list2 = arrayList.stream()
//中间操作,进行了一个排序的操作
.sorted((o1, o2) -> {
return o1.getAge() - o2.getAge();
})
.collect(Collectors.toList());//将处理完后的流转换为List类型的数据
System.out.println("转换为一个List的集合:");
System.out.println(list);
8 转为set集合
Set<User> set = arrayList.stream()
//中间操作,进行了一个排序的操作
.collect(Collectors.toSet());//将处理完后的流转换为List类型的数据
System.out.println("转换为一个Set的集合:");//set就是不重复
System.out.println(set);
9 转为map
Map<String, Integer> map = arrayList.stream()
//中间操作,进行了一个排序的操作
.collect(Collectors.toMap(User::getName, User::getAge));//将处理完后的流转换为List类型的数据
System.out.println("转换为map的结果:");
System.out.println(map);
10 转换为一个数组
Object[] array = list1.stream().sorted().toArray();
System.out.println(Arrays.toString(array));
11 取出最大值
Integer max = Stream.of(2, 4, 3, 6, 1, 7, 5)
//中间操作
.sorted() //自然排序
//sorted的结果为 1,2,3,4,5,6,7
//终端操作
.max((o1, o2) -> {
return o1 - o2;
})//max的返回值是一个Optional这样的对象中
//再调用Optional中的get的这个方法,将值拿到就行了
.get();
System.out.println(max);
12 取出最小值
Integer min = Stream.of(2, 4, 3, 6, 1, 7, 5)
//中间操作
.sorted() //自然排序
//sorted的结果为 1,2,3,4,5,6,7
//终端操作
.min((o1, o2) -> {
return o1 - o2;
})//min和max一样同理
.get();
System.out.println(min);
13 返回总个数
long count = Stream.of(2, 4, 3, 6, 1, 7, 5)
//中间操作
.sorted() //自然排序
//sorted的结果为 1,2,3,4,5,6,7
//终端操作
.count();//count返回的总共有多少个数据元素
System.out.println(count);
15 求总和
Integer reduce = Stream.of(2, 4, 3, 6, 1, 7, 5)
//中间操作
.sorted() //自然排序
//sorted的结果为 1,2,3,4,5,6,7
//终端操作
.reduce((o1, o2) -> {
return o1 + o2;
})//count返回的总共有多少个数据元素
.get();
System.out.println(reduce);
16 anyMatch:只要流中有一个元素满足条件则返 回 true,否则返回 false
boolean anyMatch = Stream.of(2, 4, 3, 6, 1, 7, 5)
//中间操作
.sorted() //自然排序
//sorted的结果为 1,2,3,4,5,6,7
//终端操作
.anyMatch((e) -> {
return e > 3;
});//表示流中的元素只要有一个大于3就返回true
System.out.println("angMatch:" + anyMatch);
17 allMatch: 当流中每个元素都符合条件时才返 回 true,否则返回 false
boolean allMatch = Stream.of(2, 4, 3, 6, 1, 7, 5)
//中间操作
.sorted() //自然排序
//sorted的结果为 1,2,3,4,5,6,7
//终端操作
.allMatch((e) -> {
return e > 3;
});//表示流中的元素全部都大于3才返回true
System.out.println("allMatch:" + allMatch);
18 取出第一个元素
Integer findFirst = Stream.of(2, 4, 3, 6, 1, 7, 5)
//中间操作
.sorted() //自然排序
//sorted的结果为 1,2,3,4,5,6,7
//终端操作
.findFirst() //findFirst的终端操作也用的是Optional的对象
.get(); //要对数据进行输出,所以也要用的get的方法
System.out.println("findFirst:" + findFirst);
19 数组与list的相互转换
int[] array1 = {1, 2, 5, 5, 5, 5, 6, 6, 7, 2, 9, 2};
/* int[] 转 list */
//方法一:需要导入commons-lang3依赖 ArrayUtils.toObject把int转为Integer
List<Integer> list3 = Arrays.asList(ArrayUtils.toObject(array1));
//方法二:java8及以上版本 boxed()转为Integer
List<Integer> list4 = Arrays.stream(array1).boxed().collect(Collectors.toList());
System.out.println(list3);
System.out.println(list4);
System.out.println();
/* list 转 int[]*/
//方法一:
Integer[] intArr = list3.toArray(new Integer[list3.size()]);
//方法二:java8及以上版本
int[] intArr1 = list3.stream().mapToInt(Integer::valueOf).toArray();
System.out.println(Arrays.toString(intArr));
System.out.println(Arrays.toString(intArr1));
//数组为Integer类型
Integer[] array2 = {1, 2, 5, 5, 5, 5, 6, 6, 7, 2, 9, 2};
List<Integer> list5 = Arrays.asList(array2);
System.out.println(list5);
20 name为key,age为value,如果key重复,取后一个v2值
userMap = userList.stream().collect(Collectors.toMap(User::name, User-> User, (v1, v2) -> v2));
21 升序排序
// 根据age排序 (正序)
list = list.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
//输出
//[User(name=小南, age=20, phone=18335888888), User(name=小南, age=21, phone=18335888888), User(name=小南, age=22, phone=18335888888), User(name=小南, age=23, phone=18335888888)]
// (倒序)
list = list.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
//输出
//[User(name=小南, age=23, phone=18335888888), User(name=小南, age=22, phone=18335888888), User(name=小南, age=21, phone=18335888888), User(name=小南, age=20, phone=18335888888)]
//如果排序字段为空将空的某一条默认排到开头还是结尾
//放到结尾
list = list.stream().sorted(Comparator.comparing(User::getAge,Comparator.nullsLast(Integer::compare).reversed())).collect(Collectors.toList());
//放到开头
list = list.stream().sorted(Comparator.comparing(User::getAge,Comparator.nullsFirst(Integer::compare).reversed())).collect(Collectors.toList());
22 降序排序
stream流降序
list.stream().sorted(Comparator.reverseOrder())
stream流根据某一字段降序
list.stream().sorted(Comparator.comparing(User::getAge).reversed())
23 排序并去重
//需要使用文章上面的工具类StreamUtils
list = list.stream().sorted(Comparator.comparing(User::getAge,Comparator.nullsLast(Integer::compare).reversed())).filter(StreamUtils.distinctByKey(User :: getName)).collect(Collectors.toList());
24 根据两个字段排序
list.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getName)).collect(Collectors.toList());
25 根据中文字段排序
list.stream().sorted(Comparator.comparing(User::getChName,Collator.getInstance(Locale.CHINA))).collect(Collectors.toList());
26 通过对象里面的某个字段进行分组
Map<Long, List<Keyword>> keywords = keywordService.getKeywordsByPaperId(paperIds).stream().collect(Collectors.groupingBy(Keyword::getPaperId));
27 通过对象里面的某个字段映射为Map
Map<String, Item> itemMap = itemList.stream().filter(t -> StringUtils.isNotEmpty(t.getCode())).collect(Collectors.toMap(Item::getCode, Function.identity()));
28 List转为List
list.stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
处理返回LongStream;LongStream.boxed 将 LongStream 转换为 Stream ,然后收集到列表中
list.stream().mapToLong(t -> Long.parseLong(t.trim())).boxed().collect(Collectors.toList());
29 List转为List
list.stream().map(String::valueOf).collect(Collectors.toList());
总结
- 有用到新的就来更新
作为程序员第 163 篇文章,每次写一句歌词记录一下,看看人生有几首歌的时间,wahahaha …