Java常用的stream流操作,附源码

时间:2024-11-09 15:38:47

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转为List
        • 29 List转为List
  • 总结
  • 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);
        //()等价于(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依赖  把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 转换为 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 …

Lyric: 包括像猫的狗