使用Stream快速对List进行一些操作
首先定义一个 Apple 类,示例如下:
public class Apple { private Integer id; private String name; private BigDecimal money; private Integer num; public Apple(Integer id, String name, BigDecimal money, Integer num) { this.id = id; this.name = name; this.money = money; this.num = num; } }
然后添加一些测试数据:
List<Apple> appleList = new ArrayList<>(); //存放apple对象集合 Apple apple1 = new Apple(1,"苹果1",new BigDecimal("3.25"),10); Apple apple12 = new Apple(1,"苹果2",new BigDecimal("1.35"),20); Apple apple2 = new Apple(2,"香蕉",new BigDecimal("2.89"),30); Apple apple3 = new Apple(3,"荔枝",new BigDecimal("9.99"),40); appleList.add(apple1); appleList.add(apple12); appleList.add(apple2); appleList.add(apple3);
1. 排序
可以使用 sort 方法对对象中的单字段或者多字段进行排序:
//排序 //单字段排序,根据id排序 appleList.sort(Comparator.comparing(Apple::getId)); //多字段排序,根据id,数量排序 appleList.sort(Comparator.comparing(Apple::getId).thenComparing(User::getNum));
2. 分组
可快速对 List 中的对象元素以对象的某一属性进行分类,比如以 ID 进行分组,将 ID 相同的对象放在一起,那么可以直接这么做:
//List 以ID分组 Map<Integer,List<Apple>> Map<Integer, List<Apple>> groupBy = appleList.stream().collect(Collectors.groupingBy(Apple::getId)); System.out.println("groupBy:" + groupBy); {1=[Apple{id=1, name='苹果1', money=3.25, num=10}, Apple{id=1, name='苹果2', money=1.35, num=20}], 2=[Apple{id=2, name='香蕉', money=2.89, num=30}], 3=[Apple{id=3, name='荔枝', money=9.99, num=40}]}
3. List 转 Map
这是一个会用到的常用操作,比如 List 中存放的 Apple 对象,现在要转换成 ID 为键,对象为值的 Map,那么可以直接这么操作:
/** * List -> Map * 需要注意的是: * toMap 如果集合对象有重复的key,会报错 Duplicate key .... * apple1,apple12的id都为 1。 * 可以用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2 */ Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));
然后我们打印 Map 结果:
{1=Apple{id=1, name='苹果1', money=3.25, num=10}, 2=Apple{id=2, name='香蕉', money=2.89, num=30}, 3=Apple{id=3, name='荔枝', money=9.99, num=40}}
4. 过滤查找元素
这个也使用的比较频繁,比如我们要从 List 中找到名称为香蕉的对象,那么可以这么操作:
//过滤出符合条件的数据 List<Apple> filterList = appleList.stream().filter(a -> a.getName().equals("香蕉")).collect(Collectors.toList()); System.out.println("filterList:"+filterList); [Apple{id=2, name='香蕉', money=2.89, num=30}]
5. 求和
将集合中的数据按照某个属性求和,如果是基本类型,可以使用 mapToInt 然后调用 sum 方法,如果是大树则使用 reduce 并调用 BigDecimal::add
方法。
//计算 总金额 //基本类型 int total = appleList.stream().mapToInt(Apple::getMoney).sum(); //大数 BigDecimal totalMoney = appleList.stream().map(Apple::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add); System.out.println("totalMoney:" + totalMoney); //totalMoney:17.48
注意,上面的求和不能过滤 BigDecimal 对象为 null 的情况,可能会报空指针,这种情况,我们可以用 filter 方法过滤,或者重写求和方法。
6. 查找流中最大/小值
利用 Collectors.maxBy
和 Collectors.minBy
来计算流中的最大或最小值。
Optional<Dish> maxDish = Dish.menu.stream(). collect(Collectors.maxBy(Comparator.comparing(Dish::getCalories))); maxDish.ifPresent(System.out::println); Optional<Dish> minDish = Dish.menu.stream(). collect(Collectors.minBy(Comparator.comparing(Dish::getCalories))); minDish.ifPresent(System.out::println);
7. 根据属性去重
import static java.util.Comparator.comparingLong; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toCollection; // 根据id去重 List<Person> unique = appleList.stream().collect( collectingAndThen( toCollection(() -> new TreeSet<>(comparingLong(Apple::getId))), ArrayList::new) );
8. 获取交集/并集/差集/去重并集
import static java.util.stream.Collectors.toList; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { List<String> list1 = new ArrayList(); list1.add("1111"); list1.add("2222"); list1.add("3333"); List<String> list2 = new ArrayList(); list2.add("3333"); list2.add("4444"); list2.add("5555"); // 交集 拓展:list2里面如果是对象,则需要提取每个对象的某一属性组成新的list,多个条件则为多个list List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList()); System.out.println("---得到交集 intersection---"); intersection.parallelStream().forEach(System.out :: println); // 差集 (list1 - list2) 同上拓展 List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(Collectors.toList()); System.out.println("---得到差集 reduce1 (list1 - list2)---"); reduce1.parallelStream().forEach(System.out :: println); // 差集 (list2 - list1) List<String> reduce2 = list2.stream().filter(item -> !list1.contains(item)).collect(Collectors.toList()); System.out.println("---得到差集 reduce2 (list2 - list1)---"); reduce2.parallelStream().forEach(System.out :: println); // 并集 List<String> listAll = list1.parallelStream().collect(toList()); List<String> listAll2 = list2.parallelStream().collect(Collectors.toList()); listAll.addAll(listAll2); System.out.println("---得到并集 listAll---"); listAll.parallelStream().forEach(System.out :: println); // 去重并集 List<String> listAllDistinct = listAll.stream().distinct().collect(Collectors.toList()); System.out.println("---得到去重并集 listAllDistinct---"); listAllDistinct.parallelStream().forEach(System.out :: println); System.out.println("---原来的List1---"); list1.parallelStream().forEach(System.out :: println); System.out.println("---原来的List2---"); list2.parallelStream().forEach(System.out :: println); // 一般有filter 操作时,不用并行流parallelStream ,如果用的话可能会导致线程安全问题 } }
9.根据list里的对象去重操作
1、根据对象中某个属性去重
1.1、创建提取方法
private <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) { Map<Object, Boolean> concurrentHashMap = new ConcurrentHashMap<>(); return t -> concurrentHashMap.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; }
1.2、利用filter
List<TestCommodity> codeDistinctList = testCommodityList
.stream()
.filter(distinctByKey(TestCommodity::getCode))
.collect(Collectors.toList());
2、根据对象中多个个属性去重,利用collectingAndThen
List<TestCommodity> cbList = testCommodityList .stream() .collect( Collectors.collectingAndThen( Collectors.toCollection( () -> new TreeSet<>( Comparator.comparing( tc -> tc.getCode() + ";" + tc.getBarCode()))), ArrayList::new));
摘自:https://bestzuo.cn/posts/stream-list.html#1-%E6%8E%92%E5%BA%8F
分类:
java
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2020-04-22 Beautiful Soup4库入门
2020-04-22 python学习之——Requests库的5个小实例
2020-04-22 Python中的 __name__属性的含义和作用
2020-04-22 http协议详细介绍
2020-04-22 Http和Https的区别
2020-04-22 爬虫——requests库使用方法
2020-04-22 设置centos7静态IP以及解决CentOS7使用静态IP地址不能上网问题