List、Set集合通过Stream流求和

发布于:2025-04-13 ⋅ 阅读:(42) ⋅ 点赞:(0)

目录

一、泛型为Integer、Long、Double、BigDecimal求和

二、泛型为实体类

对单个属性求和

对多个属性分别分组求和 并返回聚合后的对象

多字段乘积求和(基本数据类型)

多字段乘积求和(BigDecimal)

对对象中的多个字段求和时 如果对象中属性非常非常多 还像上边一样写不现实

对对象集合中的属性求和

只查找集合中符合条件的第一个元素并且返回

排序

直接排序数值

获取对象数组某个属性最小值那条记

根据对象数组某个属性排序

排序List 的集合 集合内容是String 类型的数字

多字段排序

单个字段排序

根据年龄升序排序

根据年龄降序排序

多个字段排序

年龄升序,班级升序

年龄降序,班级升序

年龄降序,班级降序

年龄升序,班级降序

分组

多字段分组

格式化时间 分组

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]}}

 

 


网站公告

今日签到

点亮在社区的每一天
去签到