目录
一、泛型为Integer、Long、Double、BigDecimal求和
对对象中的多个字段求和时 如果对象中属性非常非常多 还像上边一样写不现实
stream对list进行分组,并对分组后的数据进行map操作 获取其中的某一项属性值
Java List集合Stream流按条件分组获取每组最大值
Java List集合Stream流按条件分组获取每组中第一个对象
如果要获取某个属性值 就value.get(0).getxxx
一、泛型为Integer、Long、Double、BigDecimal求和
Integer sum = scores.stream().reduce(Integer::sum).orElse(0);
Long sum = scores.stream().reduce(Long::sum).orElse(0L);
Double sum = scores.stream().reduce(Double::sum).orElse(0.00);
BigDecimal sum = scores.stream().reduce(BigDecimal::add).orElse(new BigDecimal(0.00));
二、泛型为实体类
对单个属性求和
Integer sum = sales.stream().mapToInt(Sale::getOrderNum).sum();
Long sum = sales.stream().mapToLong(Sale::getOrderNum).sum();
Double sum = sales.stream().mapToDouble(Sale::getOrderNum).sum();
BigDecimal sum = sales.stream().map(Sale::getAppleSale).reduce(BigDecimal.ZERO,BigDecimal::add);
对多个属性分别分组求和 并返回聚合后的对象
// 类型为BigDecimal
Sale result = sales.stream().reduce((x, y) -> newSale(x.getAppleSale().add(y.getAppleSale()),x.getBananaSale().add(y.getBananaSale()),x.getGrapeSale().add(y.getGrapeSale()))).orElse(new Sale(BigDecimal.ZERO,BigDecimal.ZERO,BigDecimal.ZERO));
// 类型为Integer、Long、Double(注:orElse中需输入对应类型初始值)
Sale sale = sales.stream().reduce((x, y) -> new Sale(x.getAppleSale() + y.getAppleSale(), x.getBananaSale() + y.getBananaSale(), x.getGrapeSale() + y.getGrapeSale())).orElse(new Sale(0.00, 0.00,0.00));
多字段乘积求和(基本数据类型)
int prices = list.stream().mapToInt(x-> x.getprice * x.getTotal).sum();
多字段乘积求和(BigDecimal)
BigDecimal prices = list.stream().map(x-> x.getPrice().multiply(new BigDecimal(x.getTotal()))).reduce(BigDecimal.ZERO, BigDecimal::add);
对对象中的多个字段求和时 如果对象中属性非常非常多 还像上边一样写不现实
解决办法“转为map 遍历赋值 下边json处理使用的事hutool 的json处理
//构造返回结果
SafeJwggaqhhsetj one = new SafeJwggaqhhsetj();
//把结果转为map方便赋值
Map<String, Object> resMap = JSONUtil.toBean(JSONUtil.toJsonStr(one), Map.class);
//要求和的对象的list集合
List<SafeJwggaqhhsetj> list = this.list(queryWrapper);
//将对象list转为json数组
JSONArray array = JSONUtil.parseArray(JSONUtil.toJsonStr(list));
//将对象list转为map数组
List<Map> dataMap = JSONUtil.toList(array, Map.class);
//遍历变量名集合 keylist可能是 Arrays.asList(new String[]
{"personAmountChinese", "personManhoursChinese", })
for (String s : keylist) {
//求和
resMap.put(s, dataMap.stream().mapToInt(o -> {
AtomicReference<Integer> d = new AtomicReference<>();
Optional.ofNullable(o.get(s))
.map(p -> {
d.set((Integer) p);
return p;
})
.orElseGet(() -> {
d.set(0);
return 0;
});
return d.get();
}).sum());
}
one = JSONUtil.toBean(JSONUtil.toJsonStr(resMap), SafeJwggaqhhsetj.class);
对对象集合中的属性求和
单个bigdecimal属性的话直接 用map get 出来求和即可
例如 :
BigDecimal result2 = userList.stream()
// 将user对象的mongey取出来map为Bigdecimal
.map(User::getMoney)
// 使用reduce聚合函数,实现累加器
.reduce(BigDecimal.ZERO,BigDecimal::add);
此处为 将每个对象中多个属性求乘积以后再求和
p.getSkuCount() * p.getVolumeLength().multiply(p.getVolumeHeight()).multiply(p.getVolumeWidth()).intValue()
并且此处需要返回的count 是integer类型 如果是bigdecimal 参考 对单个属性求和 中的bigdecimal 即可
public static void main(String[] args) {
List<ExtSkuLocationParam> locationAllSku = new ArrayList<>();
for (int i = 1; i < 3; i++) {
ExtSkuLocationParam a = new ExtSkuLocationParam();
a.setSkuCount(i);
a.setVolumeLength(new BigDecimal(i * 10));
a.setVolumeWidth(new BigDecimal(i * 10));
a.setVolumeHeight(new BigDecimal(i * 10));
locationAllSku.add(a);
}
Integer reduce = locationAllSku.stream().reduce(0, (sum, p) -> sum += p.getSkuCount() * p.getVolumeLength().multiply(p.getVolumeHeight()).multiply(p.getVolumeWidth()).intValue(), Integer::sum);
System.out.println(reduce);
}
只查找集合中符合条件的第一个元素并且返回
Map matchMap = nodeMapList.stream().filter(o -> o.get("id").equals(node.get("id"))).findFirst().get();
排序
直接排序数值
List<Integer> step = stepOrign.sorted().collect(Collectors.toList())
获取对象数组某个属性最小值那条记
bookList.stream().min(Comparator.comparing(Book::getSort)).get();
根据对象数组某个属性排序
ProjectApprovalGroup.get(id).stream().sorted(Comparator.comparing(ProjectApproval::getProcessStep)).collect(Collectors.toList());
排序List 的集合 集合内容是String 类型的数字
childrenArgList={"1","2","3"}
childrenArgList = childrenArgList.stream().sorted(Comparator.comparing(o-> Integer.parseInt((String) o)).reversed()).collect(Collectors.toList());
//此为按倒序排序
结果为{"3","2","1"}
多字段排序
public class User {
//学生id
private Integer userId;
//学生姓名
private String userName;
//学生年龄
private Integer age;
//学生班级
private Integer classNo;
}
List<User> userList = new ArrayList<>();
userList.add(new User(1, "shy01", 20, 1));
userList.add(new User(2, "shy02", 18, 3));
userList.add(new User(3, "shy03", 20, 4));
userList.add(new User(4, "shy04", 19, 2));
userList.add(new User(5, "shy05", 17, 5));
userList.add(new User(6, "shy06", 16, 4));
userList.add(new User(7, "shy07", 18, 9));
userList.add(new User(8, "shy08", 19, 8));
userList.add(new User(9, "shy09", 21, 7));
单个字段排序
根据年龄升序排序
userList = userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
userList.forEach(System.out::println);
根据年龄降序排序
//方法1:先对年龄进行升序,结果进行反转
userList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
//方法2:直接对年龄进行降序
userList = userList.stream().sorted(Comparator.comparing(User::getAge, Comparator.reverseOrder())).collect(Collectors.toList());
userList.forEach(System.out::println);
多个字段排序
年龄升序,班级升序
userList = userList.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getClassNo)).collect(Collectors.toList());
年龄降序,班级升序
//方法1:先对年龄进行升序,升序结果进行反转,再进行班级升序
userList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed().thenComparing(User::getClassNo)).collect(Collectors.toList());
//方法2:直接对年龄进行降序,再对班级进行升序
userList = userList.stream().sorted(Comparator.comparing(User::getAge,Comparator.reverseOrder()).thenComparing(User::getClassNo)).collect(Collectors.toList());
年龄降序,班级降序
//方法1:先对年龄进行升序,升序结果进行反转,再对班级进行降序
userList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed().thenComparing(User::getClassNo, Comparator.reverseOrder())).collect(Collectors.toList());
//方法2:直接对年龄进行降序,再对班级进行降序
userList = userList.stream().sorted(Comparator.comparing(User::getAge,Comparator.reverseOrder()).thenComparing(User::getClassNo,Comparator.reverseOrder())).collect(Collectors.toList());
//方式3:先对年龄进行升序,再对班级进行升序,最后对结果进行反转
userList = userList.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getClassNo).reversed()).collect(Collectors.toList());
年龄升序,班级降序
//方法1:先对年龄进行升序,升序结果进行反转,再进行班级升序,结果进行反转(有点绕,年龄被排了三次升-降-升)
userList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed().thenComparing(User::getClassNo).reversed()).collect(Collectors.toList());
//方法2:直接对年龄进行升序,再对班级进行降序
userList = userList.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getClassNo, Comparator.reverseOrder())).collect(Collectors.toList());
分组
多字段分组
自定义分组规则 u.getCity() + "|" + u.getSex()
public class Demo2 {
public static void main(String[] args) {
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss");
// data list
List<User> userList = Arrays.asList(
User.builder().id(123456).name("Zhang,San").city("ShangHai").sex("man").birthDay(LocalDateTime.parse("2022-07-0112:00:00", df)).build(),
User.builder().id(777777).name("Zhang,San").city("ShangHai").sex("woman").birthDay(LocalDateTime.parse("2022-07-0112:00:00", df)).build(),
User.builder().id(888888).name("Li,Si").city("ShangHai").sex("man").birthDay(LocalDateTime.parse("2022-07-0112:00:00", df)).build(),
User.builder().id(999999).name("Zhan,San").city("HangZhou").sex("woman").birthDay(LocalDateTime.parse("2022-07-0112:00:00", df)).build(),
User.builder().id(555555).name("Li,Si").city("NaJin").sex("man").birthDay(LocalDateTime.parse("2022-07-0112:00:00", df)).build()
);
Map<String, List<User>> groupMap = userList.stream().collect(Collectors.groupingBy(u -> u.getCity() + "|" +u.getSex()));
groupMap.forEach((k, v) -> {
System.out.println(k);
System.out.println(v);
});
}
}
格式化时间 分组
list.stream().collect(Collectors.groupingBy(item -> new SimpleDateFormat("yyyy-MM-dd HH").format(item.getCreateTime())));
stream对list进行分组,并对分组后的数据进行map操作 获取其中的某一项属性值
Map<String, List> map = list.stream().collect(Collectors.groupingBy(CourseTeacherDTO::getCourseId, Collectors.mapping(CourseTeacherDTO::getName, Collectors.toList())));
Java List集合Stream流按条件分组获取每组最大值
先根据时间分组,然后根据时间排序取最大
Map<String, ProjectReport> collect = a.stream().collect(Collectors.groupingBy( item->
new SimpleDateFormat("yyyy-MM").format(item.getCreateTime()),
Collectors.collectingAndThen(Collectors.reducing((c1,c2) -> c1.getCreateTime().compareTo(c2.getCreateTime())>0 ? c1 : c2), Optional::get)));
//此时map中每个键 只有 一个值 再将map 转为list集合 并按照时间倒序排序
List<ProjectReport> endepot = new ArrayList<>(collect.values()).stream().sorted(Comparator.comparing(ProjectReport::getCreateTime).reversed()).collect(Collectors.toList());
Java List集合Stream流按条件分组获取每组中第一个对象
如果要获取某个属性值 就value.get(0).getxxx
Map<Integer, Coupon> resultList = couponList.stream().collect(Collectors.groupingBy(Coupon::getCouponId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
理论
- 分区:将 stream 按条件分为两个 Map ,比如员工按薪资是否高于8000分为两部分。
- 分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。
案例:将员工按薪资是否高于8000分为两部分;将员工按性别和地区分组
public class StreamTest {
public static void main(String[] args) {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Tom", 8900, "male", "New York"));
personList.add(new Person("Jack", 7000, "male", "Washington"));
personList.add(new Person("Lily", 7800, "female", "Washington"));
personList.add(new Person("Anni", 8200, "female", "New York"));
personList.add(new Person("Owen", 9500, "male", "New York"));
personList.add(new Person("Alisa", 7900, "female", "New York"));
// 将员工按薪资是否高于8000分组
Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
// 将员工按性别分组
Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
// 将员工先按性别分组,再按地区分组
Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
System.out.println("员工按薪资是否大于8000分组情况:" + part);
System.out.println("员工按性别分组情况:" + group);
System.out.println("员工按性别、地区:" + group2);
}
}
输出结果:
员工按薪资是否大于8000分组情况:{false=[mutest.Person@2d98a335, mutest.Person@16b98e56, mutest.Person@7ef20235], true=[mutest.Person@27d6c5e0, mutest.Person@4f3f5b24, mutest.Person@15aeb7ab]}
员工按性别分组情况:{female=[mutest.Person@16b98e56, mutest.Person@4f3f5b24, mutest.Person@7ef20235], male=[mutest.Person@27d6c5e0, mutest.Person@2d98a335, mutest.Person@15aeb7ab]}
员工按性别、地区:{female={New York=[mutest.Person@4f3f5b24, mutest.Person@7ef20235], Washington=[mutest.Person@16b98e56]}, male={New York=[mutest.Person@27d6c5e0, mutest.Person@15aeb7ab], Washington=[mutest.Person@2d98a335]}}
- 本文出处: 【Java】 Stream流求和、排序、分组 - 尽 - 博客园
- 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。