前期工作准备,实体类(ParkingLot ,Area ,ParkingLotType,ParkingCarIO),
CombineInfo类用于整合ParkingLot与ParkingCarIO数据
@Data
@AllArgsConstructor
public class ParkingLot { // 停车场
private Integer id;
private String parklotName; // 停车场名称
private Area area; // 所在区域
private ParkingLotType parkingLotType; // 停车场类型
private int total; // 总车位
private int usedNum; // 使用泊位数
}
@Data
@AllArgsConstructor
public class Area { // 区域信息
private Integer id;
private String areaName; // 区域名称
}
@Data
@AllArgsConstructor
public class ParkingLotType { // 停车场类型
private Integer id;
private String parklotTypeName; // 停车场类型名称
}
@Data
@AllArgsConstructor
public class ParkingCarIO{ // 流水信息表
private Integer id;
private String parklotName; // 停车场名称
private Date inOutTime; // 出场/入场时间
}
@Data
public class CombineInfo{ // 流水表和停车场合并表
private String parklotName; // 停车场名称
private Date inOutTime; // 出场/入场时间
private String areaName; // 所在区域
private String parklotTypeName; // 停车场类型
public combineInfo(String parklotName, Date inOutTime, String parklotTypeName, String areaName) {
this.parklotName = parklotName;
this.inOutTime = inOutTime;
this.areaName = areaName;
this.parklotTypeName = parklotTypeName;
}
}
@Test
public void Test() {
Area areaOne = new Area(01,"区域01");
Area areaTwo = new Area(02,"区域02");
Area areaThree = new Area(03,"区域03");
Area areaFour = new Area(04,"区域04");
Date date = new Date();
ArrayList<ParkingCarIO> carIOList = new ArrayList<>();
carIOList.add(new ParkingCarIO(01,"一号停车场",date));
carIOList.add(new ParkingCarIO(01,"一号停车场",date));
carIOList.add(new ParkingCarIO(01,"二号停车场",date));
carIOList.add(new ParkingCarIO(01,"三号停车场",date));
carIOList.add(new ParkingCarIO(01,"三号停车场",date));
ParkingLotType residentialLand = new ParkingLotType(01,"住宅");
ParkingLotType commercialLand = new ParkingLotType(02,"商业");
List<ParkingLot> parkingLotList = new ArrayList<ParkingLot>();
parkingLotList.add(new ParkingLot(10501, "一号停车场", areaOne,residentialLand,50,30));
parkingLotList.add(new ParkingLot(10603, "二号停车场", areaTwo,residentialLand,100,70));
parkingLotList.add(new ParkingLot(40514, "三号停车场",areaThree,residentialLand,100,10));
parkingLotList.add(new ParkingLot(59562, "四号停车场", areaFour,commercialLand,150,60));
parkingLotList.add(new ParkingLot(29415, "五号停车场", areaFour,commercialLand,200,100));
parkingLotList.add(new ParkingLot(61812, "七号停车场", areaTwo,residentialLand,100,50));
parkingLotList.add(new ParkingLot(61812, "八号停车场", areaTwo,commercialLand,100,50));
parkingLotList.add(new ParkingLot(61812, "九号停车场", areaOne,commercialLand,100,50));
parkingLotList.add(new ParkingLot(61812, "十号停车场", areaThree,residentialLand,100,50));
}
筛选(filter)
筛选,按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。
- 需求1:当需获取某个对象集合中符合条件的数据时,例如,筛选出泊位大于100的停车场
List<ParkingLot> list = parkingLotList.stream()
.filter(x -> x.total > 100).collect(Collectors.toList()); // x即表示ParkingLot
映射(map/flatMap)
映射,将流中的每个
元素按照一定的规则映射为另一种元素
- 需求1:当需获取对象集合中的某一属性时。例如,从停车场集合中获取各个停车场的名称
List<String> nameList = parkingLotList.stream()
.map(ParkingLot::getParklotName).collect(Collectors.toList()); // ::方法引用,引用getParklotName方法
结果:[一号停车场, 二号停车场, 三号停车场, 四号停车场, 五号停车场, 六号停车场]
- 需求2:当需获取对象集合中多个属性时,例如,从所有停车场集合中获取的名称和总泊位数
List<Map> list1 = parkingLotList.stream().map(new Function<ParkingLot, Map>() {
@Override
public Map apply(ParkingLot parkingLot) {
Map<String, Object> map = new HashMap<>();
map.put("parklotName", parkingLot.getParklotName());
map.put("total", parkingLot.getTotal());
return map;
}
}).collect(Collectors.toList());
结果:[{total=50, parklotName=一号停车场}, {total=100, parklotName=二号停车场}…]
收集(collect)
收集,将流中的数据中心归集到新的集合中,相当于再整合,常用的有toList
,toSet
,toMap
分组(groupingBy)
- 需求1:单条件分组,例如,根据街道名称进行分组
Map<String, List<ParkingLot>> collect = parkingLotList.stream()
.collect(Collectors.groupingBy(x -> x.getArea().getAreaName()));
- 需求2:多条件分组,例如,根据街道名称与类型名称进行分组
Map<String, Map<String, List<ParkingLot>>> collect1 = parkingLotList.stream()
.collect(Collectors.groupingBy(x -> x.getArea().getAreaName()
, Collectors.groupingBy(x -> x.getParkingLotType().getParklotTypeName())));
- 需求3:分组后,按需设置返回数据的格式,例如,根据街道名称分组后,只保留集合中对象的名称与总数
Map<String, List<Map>> map= parkingLotList.stream()
.collect(Collectors.groupingBy(x -> x.getArea().getAreaName(), Collectors.collectingAndThen(Collectors.toList(), m -> {
return m.stream().map(new Function<ParkingLot, Map>() {
@Override
public Map apply(ParkingLot parkingLot) {
HashMap<String, Object> map = new HashMap<>();
map.put("parklotName", parkingLot.getParklotName());
map.put("total", parkingLot.getTotal());
return map;
}
}).collect(Collectors.toList());
})));
- 需求4:对分组后的数据进行计算合并,例如,根据街道名称分组后,获取每组数据中平均占有率
注意:乘法、除法运算时,使用--BigDecimal
Map<String, Integer> map= parkingLotList.stream().collect(Collectors.groupingBy(x -> x.getArea().getAreaName()
, Collectors.collectingAndThen(Collectors.toList(), m -> {
int usedSum = m.stream().mapToInt(ParkingLot::getUsedNum).sum(); // 总使用数量
int totalSum = m.stream().mapToInt(ParkingLot::getTotal).sum(); // 总数量
int avgNum = BigDecimal.valueOf(usedSum).divide(BigDecimal.valueOf(totalSum), 2, BigDecimal.ROUND_HALF_UP).intValue();//分组后,各组的平均占用率
return avgNum;
})));
- 需求5:分组,并对分组后的key进行格式化
注意:乘法、除法运算时,使用--BigDecimal
// 由于表中存储的 评定结果为: 1,2,null 所以,为了前端好接收,特将key改为英文
Map<String, Long> collect = parkingLotList.stream().collect(Collectors.groupingBy(parkingLot-> {
if (parkingLot.getArea() != null) {
if (parkingLot.getArea.getId().equals("1")) {
return "pass";
} else if (parkingLot.getArea.getId().equals("0")) {
return "notPass";
}
}
return "weiPingDing";
}, Collectors.counting()));
排序(sorted)
- 需求1:对集合进行操作,根据对象的某一属性(int)进行排序。例如,根据停车场的总车位数量进行倒叙排序
注意: .reversed()倒叙排列 ,需要正序排列去掉.reversed()
List<ParkingLot> resultList = parkingLotList.stream()
.sorted(Comparator.comparing(ParkingLot::getTotal).reversed())
.collect(Collectors.toList());
- 需求2:对Map进行操作,实现排序功能(思路,将Map转换为List),例如,对分组后的数据进行排序时,可用该方法
Map<String, Integer> map = parkingLotList.stream()
.collect(Collectors.groupingBy(x -> x.getArea().getAreaName()
, Collectors.collectingAndThen(Collectors.toList(), m -> {
int usedSum = m.stream().mapToInt(ParkingLot::getUsedNum).sum();
int totalSum = m.stream().mapToInt(ParkingLot::getTotal).sum();
int avgNum = BigDecimal.valueOf(usedSum).divide(BigDecimal.valueOf(totalSum), 2, BigDecimal.ROUND_HALF_UP).intValue();//分组后,各组的平均占用率
return avgNum;
})));
List<Map<String, Object>> resultList = new ArrayList<>();
map.forEach((k, v) -> {
Map<String, Object> temp = new HashMap<>();
temp.put("name", k);
temp.put("rate", v);
resultList.add(temp);
});
resultList.sort((e1, e2) -> {
return Integer.valueOf(e2.get("total").toString()) - Integer.valueOf(e1.get("total").toString());
});
对两集合进行操作
- 交集:将两集合中含有某一共同属性的数据筛选出来,并整合出新的集合
CombineInfo是专门创建的类,根据所需属性,创建对应的有参构造方法
List<CombineInfo> list2 = carIOList.stream()
.flatMap(x -> parkingLotList.stream()
.filter(y -> x.getParklotName().equals(y.getParklotName()))
.map(y -> new CombineInfo(x.getParklotName(),x.getInOutTime(), y.getParkingLotType().getParklotTypeName(), y.getArea().getAreaName()))) // 此处为,将筛选出来的进行加工
.collect(Collectors.toList());
- 差集:现有A,B两集合,根据某一共同属性筛选出A有B没有的数据,并整合出新的集合
注意: 使用 .noneMatch()
List<StatementManagementRequest> collectList = parkList.stream()
.filter(park -> statementManagementList.stream()
.noneMatch(stateInfo -> stateInfo.getParkName().equals(park.getParklotName())))
.map(y -> new StatementManagementRequest(y.getParklotName(), y.getParkingLotType().getParklotTypeName(), 0, 0, 0, 0, (double) 0, chooseTime, 0)) // 此处为,将筛选出来的进行加工
.collect(Collectors.toList());