1、首先定義兩個接口SumOperator、AverageOperator;所有要實現求和功能的類都必須實現SumOperator接口,要實現求平均值功能的類都必須實現AverageOperator接口,以下是兩個接口定義:
public interface SumOperator<T> {
/**
* sum
* @desc:
* @author:
* @createTime: 2020/4/29 12:37
* @param t
* @return: T
*/
T sum(T t);
}
public interface AverageOperator<T> extends SumOperator<T>{
/**
* divide
* @desc:
* @author:
* @createTime: 2020/4/29 12:37
* @param number
* @return: T
*/
T divide(long number);
}
2、接下來自定義一個類來生成這兩個Collector:代碼如下
public class CustomCollectors{
public static<T extends SumOperator<T>> Collector<T, List<T>, T> ofSum() {
return new CollectorImpl<T>(
list -> list.stream().reduce((t1, t2) -> t1.sum(t2)).get()
);
}
public static<T extends AverageOperator<T>> Collector<T, List<T>, T> ofAverage() {
return new CollectorImpl<T>(
list -> list.stream().reduce((t1, t2) -> t1.sum(t2)).get().divide(list.size())
);
}
static class CollectorImpl<T> implements Collector<T, List<T>, T>{
private Function<List<T>, T> finisher;
private CollectorImpl(Function<List<T>, T> finisher){
this.finisher = finisher;
}
@Override
public Supplier<List<T>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<T>, T> accumulator() {
return List::add;
}
@Override
public BinaryOperator<List<T>> combiner() {
return (left, right) -> { left.addAll(right); return left; };
}
@Override
public Function<List<T>, T> finisher() {
return finisher;
}
@Override
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
}
}
3、接下來我們做個測試:
public class Test {
@Getter
@Setter
@Accessors(chain = true)
static class Student implements AverageOperator<Student> {
private String name;
private int term;
private double mathScore;
private double englishScore;
/**
* student
* @desc: 爲了不影響List中存儲的Student對象,不需要可以去掉
* @author:
* @createTime: 2020/4/29 16:25
* @param
* @return: Student
*/
private Student student(){
Student student = this;
if(!StringUtils.isEmpty(student.name)){
student = new Student();
student.mathScore = mathScore;
student.englishScore = englishScore;
}
return student;
}
@Override
public Student divide(long number) {
Student student = student();
student.mathScore /= number;
student.englishScore /= number;
return student;
}
@Override
public Student sum(Student student) {
Student s = student();
s.mathScore += student.mathScore;
s.englishScore += student.englishScore;
return s;
}
}
public static void main(String[] args) {
List<Student> students = new ArrayList<Student>(){
{
add(new Student().setName("張三").setTerm(1).setMathScore(90).setEnglishScore(80));
add(new Student().setName("張三").setTerm(2).setMathScore(85).setEnglishScore(77));
add(new Student().setName("張三").setTerm(3).setMathScore(95).setEnglishScore(78));
add(new Student().setName("張三").setTerm(4).setMathScore(88).setEnglishScore(75));
add(new Student().setName("張三").setTerm(5).setMathScore(95).setEnglishScore(78));
add(new Student().setName("張三").setTerm(6).setMathScore(88).setEnglishScore(75));
add(new Student().setName("李四").setTerm(1).setMathScore(90).setEnglishScore(60));
add(new Student().setName("李四").setTerm(2).setMathScore(95).setEnglishScore(67));
add(new Student().setName("李四").setTerm(3).setMathScore(98).setEnglishScore(60));
add(new Student().setName("李四").setTerm(4).setMathScore(98).setEnglishScore(70));
add(new Student().setName("李四").setTerm(5).setMathScore(100).setEnglishScore(68));
add(new Student().setName("李四").setTerm(6).setMathScore(96).setEnglishScore(75));
}
};
//下面分組求出學生的平均分
Collector<Student, List<Student>, Student> collector = CustomCollectors.ofAverage();
Map<String, Student> map = students.stream().collect(Collectors.groupingBy(Student::getName, collector));
map.forEach((name, student) -> {
System.out.println(String.format("學生【%s】的平均分爲;(數學:%f, 英語:%f)", name, student.getMathScore(), student.getEnglishScore()));
});
}
}
打印結果如下:
學生【李四】的平均分爲;(數學:96.166667, 英語:66.666667)
學生【張三】的平均分爲;(數學:90.166667, 英語:77.166667)