之前想对数据进行分组统计之类的操作,需要使用关系型数据库的group by等操作来实现。但这两天工作中碰到一个问题,数据从其他系统获取而不再是我从数据库中取了,也就是说我没法使用关系型数据库提供的操作方法了。了解了一下java8中stream 对数据的处理。
这次碰到的需求是,拿到通过dubbo接口调用其他系统返回的数据,然后对这些进行一个类似于聚合的操作,把多个属性相同的对象视为同一个对象。
假设有一个车辆类型
@Data
public class Car {
private String name;
private int id;
private String color;
public Car(String name, int id, String color) {
this.name = name;
this.id = id;
this.color = color;
}
//constructors, getter/setters
}
List<Car> cars = Arrays.asList(
new Car("golf", 1, "red"),
new Car("bmw", 2, "red"),
new Car("mini", 3, "black"),
new Car("ds", 4, "white"),
new Car("bmw", 5, "gold"),
new Car("golf", 6, "red"),
new Car("bmw", 7, "gold"),
new Car("ds", 8,"white")
);
如果想根据名称来分类,并且统计各品牌数量
Map<String, Long> sum = cars.stream().collect(
Collectors.groupingBy(Car::getName, Collectors.counting()));
System.out.println(sum);
输出结果是:{golf=2, mini=1, bmw=3, ds=2}
如果想根据多个字段来分类,可以再另外创建一个封装类型,把要分类的字段放进去,Car类再添加一个方法来获取这个类的对象。
@Data
public class Count {
private String name;
private String color;
public Count(String name, String color) {
this.name = name;
this.color = color;
}
}
修改一下Car类
@Data
public class Car {
private String name;
private int id;
private String color;
public Car(String name, int id, String color) {
this.name = name;
this.id = id;
this.color = color;
}
public Count getCount() {
return new Count(name, color);
}
//constructors, getter/setters
}
Map<Count, Long> counting = cars.stream().collect(
Collectors.groupingBy(Car::getCount, Collectors.counting()));
System.out.println(counting);
输出结果:{Count(name=bmw, color=gold)=2, Count(name=mini, color=black)=1, Count(name=ds, color=white)=2, Count(name=bmw, color=red)=1, Count(name=golf, color=red)=2}