java8 分组 和 排序
1. 排序
list.sort((o1, o2) -> o2.getAge() - o1.getAge());
汉字排序:
private final static Comparator
mylist.sort((o1,o2) ->{Collator collator = Collator.getInstance(java.util.Locale.CHINA);return collator.compare(o1.getname(),o2.getname()) ;});
// 中文排序List collect = mylist.stream().sorted((o1, o2) -> {Comparator comparator = Collator.getInstance(Locale.CHINA);return comparator.compare(o1.getName(),o2.getName());}).collect(Collectors.toList());

1. 多个分组
Map>> map = list.stream().collect(Collectors.groupingBy(RStudentExam::getId,Collectors.groupingBy(RStudentExam::getSchoolId)));
2. 分组后求和
参考链接:
https://blog.csdn.net/weixin_44905182/article/details/105792291
需求:
求得每个学生的总成绩
模拟数据如下:
List studentScoreList = new ArrayList<>();StudentScore studentScore1 = new StudentScore("慕容皝","语文",BigDecimal.valueOf(99));StudentScore studentScore2 = new StudentScore("慕容皝","数学",BigDecimal.valueOf(99));StudentScore studentScore3 = new StudentScore("慕容皝","英语",BigDecimal.valueOf(97));StudentScore studentScore4 = new StudentScore("慕容皝","历史",BigDecimal.valueOf(97));studentScoreList.add(studentScore1) ;studentScoreList.add(studentScore2) ;studentScoreList.add(studentScore3) ;studentScoreList.add(studentScore4) ;StudentScore studentScore5 = new StudentScore("慕容垂","语文",BigDecimal.valueOf(89));StudentScore studentScore6 = new StudentScore("慕容垂","数学",BigDecimal.valueOf(89));StudentScore studentScore7 = new StudentScore("慕容垂","英语",BigDecimal.valueOf(87));StudentScore studentScore8 = new StudentScore("慕容垂","历史",BigDecimal.valueOf(87));studentScoreList.add(studentScore5) ;studentScoreList.add(studentScore6) ;studentScoreList.add(studentScore7) ;studentScoreList.add(studentScore8) ;StudentScore studentScore9 = new StudentScore("慕容雪","语文",BigDecimal.valueOf(79));StudentScore studentScore10 = new StudentScore("慕容雪","数学",BigDecimal.valueOf(79));StudentScore studentScore11 = new StudentScore("慕容雪","英语",BigDecimal.valueOf(77));StudentScore studentScore12 = new StudentScore("慕容雪","历史",BigDecimal.valueOf(77));studentScoreList.add(studentScore9) ;studentScoreList.add(studentScore10) ;studentScoreList.add(studentScore11) ;studentScoreList.add(studentScore12) ;
常规做法:
map 的merge 方法
java8 分组后对组内数据的处理(扩展)
常规:
// 法① 常规做法Map studentScoreMap1 = new HashMap<>();studentScoreList.forEach(studentScore -> {if (studentScoreMap1.containsKey(studentScore.getName())) {studentScoreMap1.put(studentScore.getName(),// 拿到旧值,在原来的基础上操作studentScoreMap1.get(studentScore.getName()).add(studentScore.getScore()));} else {studentScoreMap1.put(studentScore.getName(), studentScore.getScore());}});studentScoreMap1.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v));System.out.println("-----------------------------sum----------------------");
merge:
// 法②Map studentScoreMap2 = new HashMap<>();studentScoreList.forEach(studentScore -> studentScoreMap2.merge(// keystudentScore.getName(),// valuestudentScore.getScore(),(a,b) ->{// add 是返回一个新的 BigDecimal 对象a = a.add(b);return a;}));studentScoreMap2.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v));
merge方法定义在 java.util.Map 中,方法定义如下:
default V merge(K key, V value,BiFunction super V, ? super V, ? extends V> remappingFunction) {Objects.requireNonNull(remappingFunction);Objects.requireNonNull(value);// 获取旧值V oldValue = get(key);// 旧值为null ,用value 直接作为新value ; 旧值非null ,执行 函数接口V newValue = (oldValue == null) ? value :remappingFunction.apply(oldValue, value);if(newValue == null) {remove(key);} else {// insert or updateput(key, newValue);}return newValue;}
BiFunction 定义:
@FunctionalInterface
public interface BiFunction {/*** Applies this function to the given arguments* @param t the first function argument* @param u the second function argument* @return the function result*/R apply(T t, U u);
}
法③
需要自定义 函数式接口 etc(参考int 的算法,比较麻烦)
// 法③ Java8原生只提供了summingInt、summingLong、summingDouble三种基础类型的方法,想要对BigDecimal类型的数据操作需要自己新建工具类System.out.println("-----------------------------sum 3.1 ----------------------");Map studentScoreMap4 =studentScoreList.stream().collect(Collectors.groupingBy(StudentScore::getName , CollectorsUtil.summarizingBigDecimal(StudentScore::getScore)) );studentScoreMap4.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v.getSum()));

这个最常用:
public static Collector>>groupingBy(Function super T, ? extends K> classifier) {return groupingBy(classifier, toList());}
上面的用到的底层是下面的
public static Collector> groupingBy(Function super T, ? extends K> classifier,Collector super T, A, D> downstream) {return groupingBy(classifier, HashMap::new, downstream);}

而上面两个方法的最底层调用的都是 下面的:
public static >Collector groupingBy(Function super T, ? extends K> classifier,Supplier mapFactory,Collector super T, A, D> downstream) {Supplier downstreamSupplier = downstream.supplier();BiConsumer downstreamAccumulator = downstream.accumulator();BiConsumer
对分组后,组内数据是int 的求和
Foo foo1 = new Foo(1, 2);Foo foo2 = new Foo(2, 23);Foo foo3 = new Foo(2, 6);List list = new ArrayList<>(4);list.add(foo1);list.add(foo2);list.add(foo3);Map collect = list.stream().collect(Collectors.groupingBy(Foo::getCode, Collectors.summarizingInt(Foo::getCount)));IntSummaryStatistics statistics1 = collect.get(1);System.out.println(statistics1.getSum());System.out.println(statistics1.getAverage());System.out.println(statistics1.getMax());System.out.println(statistics1.getMin());System.out.println(statistics1.getCount());
源码如下:
public static Collector summarizingInt(ToIntFunction super T> mapper) {return new CollectorImpl(IntSummaryStatistics::new,(r, t) -> r.accept(mapper.applyAsInt(t)),(l, r) -> { l.combine(r); return l; }, CH_ID);}
构造器定义如下:
static class CollectorImpl implements Collector {private final Supplier supplier;private final BiConsumer accumulator;private final BinaryOperator combiner;private final Function finisher;private final Set characteristics;CollectorImpl(Supplier supplier,BiConsumer accumulator,BinaryOperator combiner,Function finisher,Set characteristics) {this.supplier = supplier;this.accumulator = accumulator;this.combiner = combiner;this.finisher = finisher;this.characteristics = characteristics;}CollectorImpl(Supplier supplier,BiConsumer accumulator,BinaryOperator combiner,Set characteristics) {this(supplier, accumulator, combiner, castingIdentity(), characteristics);}
package java.util;import java.util.function.IntConsumer;
import java.util.stream.Collector;/*** @since 1.8*/
public class IntSummaryStatistics implements IntConsumer {private long count;private long sum;private int min = Integer.MAX_VALUE;private int max = Integer.MIN_VALUE;public IntSummaryStatistics() { }@Overridepublic void accept(int value) {// 计数,求平均数用的++count;// 求和sum += value;// 最小值min = Math.min(min, value);// 最大值max = Math.max(max, value);}// 计算对应的值public void combine(IntSummaryStatistics other) {count += other.count;sum += other.sum;min = Math.min(min, other.min);max = Math.max(max, other.max);}public final long getCount() {return count;}// 返回和 public final long getSum() {return sum;}// 返回最小值public final int getMin() {return min;}// 返回最大值public final int getMax() {return max;}// 返回平均值(sum 除以 count)public final double getAverage() {return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;}@Overridepublic String toString() {return String.format("%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",this.getClass().getSimpleName(),getCount(),getSum(),getMin(),getAverage(),getMax());}
}
而他的父接口是函数式接口
package java.util.function;import java.util.Objects;/*** @since 1.8*/
@FunctionalInterface
public interface IntConsumer {void accept(int value);}

@FunctionalInterface
public interface BiConsumer {void accept(T t, U u);
}
@FunctionalInterface
public interface BinaryOperator extends BiFunction{}
@FunctionalInterface
public interface BiFunction {R apply(T t, U u);
}
自定义函数式接口
@FunctionalInterface
public interface ToIntFunction {int applyAsInt(T value);
}


接下来改写 一个针对BigDecimal 类型的 group by
先定义初始化对象 ,返回对象
package com.example.demo.service.Impl;import com.example.demo.entity.annotation.BigDecimalConsumer;import java.math.BigDecimal;/*** @author: guoyiguang**/
public class BigDecimalSummaryStatistics implements BigDecimalConsumer {private BigDecimal sum;public BigDecimalSummaryStatistics() { }public BigDecimal combine(BigDecimalSummaryStatistics other) {// 求和return sum = sum.add(other.sum) ;}@Overridepublic void accept(BigDecimal value) {if (null == sum){sum = value ;}else {// 计算sum = sum.add(value);}}@Overridepublic String toString() {return "BigDecimalSummaryStatistics{" +"sum=" + sum +'}';}// 要获取到这个对象里的 sum 需要get 方法public BigDecimal getSum() {return sum;}
}
自定义函数式接口
@FunctionalInterface
public interface ToBigDecimalFunction {// 传一个 ,返回 BigDecimal 对象BigDecimal applyAsBigDecimal(T value);
}
提供一个返回 stream 流 里的 Collector 的工具类
package com.example.demo.utils;import com.example.demo.entity.annotation.ToBigDecimalFunction;
import com.example.demo.service.Impl.BigDecimalSummaryStatistics;
import java.util.Collections;
import java.util.Set;
import java.util.function.*;
import java.util.stream.Collector;public class CollectorsUtil {static final Set CH_NOID = Collections.emptySet();private CollectorsUtil() {}@SuppressWarnings("unchecked")private static Function castingIdentity() {return i -> (R) i;}static class CollectorImpl implements Collector {private final Supplier supplier;private final BiConsumer accumulator;private final BinaryOperator combiner;private final Function finisher;private final Set characteristics;CollectorImpl(Supplier supplier, BiConsumer accumulator, BinaryOperator combiner,Function finisher, Set characteristics) {this.supplier = supplier;this.accumulator = accumulator;this.combiner = combiner;this.finisher = finisher;this.characteristics = characteristics;}// 模仿int写的CollectorImpl(Supplier supplier, BiConsumer accumulator, BinaryOperator combiner,Set characteristics) {this(supplier, accumulator, combiner, castingIdentity(), characteristics);}@Overridepublic BiConsumer accumulator() {return accumulator;}@Overridepublic Supplier supplier() {return supplier;}@Overridepublic BinaryOperator combiner() {return combiner;}@Overridepublic Function finisher() {return finisher;}@Overridepublic Set characteristics() {return characteristics;}}// CollectorImpl(Supplier supplier,// BiConsumer accumulator,// BinaryOperator combiner,// Set characteristics)
// T 不管
// 第一个 BigDecimalSummaryStatistics 是初始化对象
// 第二个 BigDecimalSummaryStatistics 是返回对象public static Collector summarizingBigDecimal(ToBigDecimalFunction super T> mapper) {
// T 不管
// 第一个 BigDecimalSummaryStatistics 是初始化对象
// 第二个 BigDecimalSummaryStatistics 是返回对象return new CollectorImpl(BigDecimalSummaryStatistics::new ,// 上一行 new 出来的 BigDecimalSummaryStatistics 对象作为 BiConsumer 的第一个参数(r, t) -> r.accept(mapper.applyAsBigDecimal(t)),// 上一行 new 出来的 BigDecimalSummaryStatistics 对象作为 BinaryOperator 的第二个参数(l, r) -> { l.combine(r); return l; }, CH_NOID);}}
测试代码如下:
// 法③ Java8原生只提供了summingInt、summingLong、summingDouble三种基础类型的方法,想要对BigDecimal类型的数据操作需要自己新建工具类System.out.println("-----------------------------sum 3.1 ----------------------");Map studentScoreMap4 =studentScoreList.stream().collect(Collectors.groupingBy(StudentScore::getName , CollectorsUtil.summarizingBigDecimal(StudentScore::getScore)) );studentScoreMap4.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v.getSum()));
测试结果:
-----------------------------sum 3.1 ----------------------
key: 慕容皝 , value: 392
key: 慕容垂 , value: 352
key: 慕容雪 , value: 312
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
