JAVA 8 StreamAPI 和 lambda表达式 总结(四)--stream的一些聚合操作

在sql里,一些聚合操作max,count,或者只是进行一些分组,这些我们都很熟悉,在Stream API中,我们也可以做一些聚合操作.

我们定义一个类Group,里面有班级号,分数和学生的名字

package JDK.StreamAndLambda.groupToMap;

/**
 * Created by panqian on 2017/2/28.
 */
public class Group {
    String classes;
    String num;
    String name;

    public Group() {
    }

    public Group(String classes, String num, String name) {
        this.classes = classes;
        this.num = num;
        this.name = name;
    }

    public String getClasses() {
        return classes;
    }

    public void setClasses(String classes) {
        this.classes = classes;
    }

    public String getNum() {
        return num;
    }

    public void setNum(String num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

然后创建一个ArrayList集合,分别添加四个学生,他们可能是同班同学。

ArrayList<Group> groups = new ArrayList<>();

groups.add(new Group("1321813", "88", "panqian01"));
groups.add(new Group("1321813", "100", "panqian02"));
groups.add(new Group("1321814", "99", "panqian03"));
groups.add(new Group("1321815", "70", "panqian04"));


//所有人按班级分组
Map<String, List<Group>> collect = groups.stream().collect(Collectors.groupingBy(Group::getClasses));
Set<String> strings = collect.keySet();
for (String s : strings) {
    System.out.println(s + ":");
    collect.get(s).forEach(x -> System.out.println(x.getName()));
}

程序执行后,我们可以看到如下结果。它往collect方法里面传了一个groupingBy(班级)静态方法,跟sql 的 group by 很像,得到了是一个map结果,我们可以知道每个班里面有哪些人:

1321813:
panqian01
panqian02
1321814:
panqian03
1321815:
panqian04

如果我们想把学生的名字用”,”连接,程序可以稍作修改,groupingBy方法的第二个参数可以对每个结果进行map处理。

//所有人按班级分组(名字用,连接)
        Map collect4 = groups.stream().collect(Collectors.groupingBy(Group::getClasses, Collectors.mapping(Group::getName, Collectors.joining(","))));

        Set strings4 = collect4.keySet();
        for (String s : strings4) {
            System.out.println(s + ":");
            System.out.println(collect4.get(s));
        }

得出结果如下:

1321813:
panqian01,panqian02
1321814:
panqian03
1321815:
panqian04

第三个需求是我们以90分为界限,分别找出90以上的人和90分以下的人,partitioningBy静态方法返回的是带布尔值的Collector,可以对元素处理之后返回的true或false为依据进行分组。

//按成绩90分为界限  进行分组
Map> collect1 = groups.stream().collect(Collectors.partitioningBy(x -> Integer.valueOf(x.getNum()) > 90));
Set strings1 = collect1.keySet();
for (Boolean s : strings1) {
    System.out.println(s + ":");
    collect1.get(s).forEach(x -> System.out.println(x.getName()));
}
//90分以下的人
false:
panqian01
panqian04
//90分以上的人
true:
panqian02
panqian03

第四个需求,计算每个班的班级人数,先用groupingBy静态方法进行班级分组,然后第二个参数传入counting静态方法进行聚合操作,从而对每个组计算总人数

//计算每个班的班级人数
Map collect2 = groups.stream().collect(Collectors.groupingBy(Group::getClasses, Collectors.counting()));
Set strings2 = collect2.keySet();
for (String s : strings2) {
    System.out.println(s + ":");
    System.out.println(collect2.get(s));
}
1321813:
2
1321814:
1
1321815:
1

最后一个需求,计算每个班的最高分,在groupingBy的第二个参数,我们可以传入maxBy方法,求最大值,在maxBy方法里,需要我们传入自定义的Comparator比较器,从而对分数进行排序,最后得出每个班得分最高的人

//计算每个班的最高分
Map<String, Optional<Group>> collect3 = groups.stream().collect(Collectors.groupingBy(Group::getClasses, Collectors.maxBy(new Comparator<Group>() {
    @Override
    public int compare(Group o1, Group o2) {
        if (Integer.valueOf(o1.getNum()) > Integer.valueOf(o2.getNum()))
            return 1;
        return -1;
    }
})));
Set<String> strings3 = collect3.keySet();
for (String s : strings3) {
    System.out.println(s + ":");
    Optional<Group> group = collect3.get(s);
    group.ifPresent(x -> System.out.println(x.getName()));
}
1321813:
panqian02
1321814:
panqian03
1321815:
panqian04

你可能感兴趣的:(JAVASE,技术分享)