JDK8新特性笔记(八):JDK8流和lambda内容综合练习
1.综合JDK8新特性,collection和lambda完成数据处理需求整理
需求描述:电商订单数据处理,根据下面的list1和list2各十个订单
- 统计出同时被两个人购买的商品列表(取交集)
- 统计出两个人购买商品的差集
- 统计出全部被购买商品的去重并集
- 统计两个人的分别购买订单的平均价格
- 统计两个人的分别购买订单的总价格
准备类对象:
public class VideoOrder {
private String tradeNO;
private int money;
private String title;
public VideoOrder() {
}
public VideoOrder(String tradeNO, String title, int money) {
this.tradeNO = tradeNO;
this.money = money;
this.title = title;
}
public String getTradeNO() {
return tradeNO;
}
public void setTradeNO(String tradeNO) {
this.tradeNO = tradeNO;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "VideoOrder{" +
"title='" + title +
", money=" + money + '\'' +
'}';
}
}
自己想的憨憨的解决办法:
public class Requirement1 {
public static void main(String[] args) {
// 总价 35
List<VideoOrder> videoOrders1 = Arrays.asList(new VideoOrder("20190242812", "springboot教程", 3),
new VideoOrder("20194350812", "微服务SpringCloud", 5),
new VideoOrder("20190814232", "Redis教程", 9),
new VideoOrder("20190523812", "⽹⻚开发教程", 9),
new VideoOrder("201932324", "百万并发实战Netty", 9));
// 总价 54
List<VideoOrder> videoOrders2 = Arrays.asList(new VideoOrder("2019024285312", "springboot教程", 3),
new VideoOrder("2019081453232", "Redis教程", 9),
new VideoOrder("20190522338312", "⽹⻚开发教程", 9),
new VideoOrder("2019435230812", "Jmeter压⼒测试", 5),
new VideoOrder("2019323542411", "Git+Jenkins持续集成", 7),
new VideoOrder("2019323542424", "Idea全套教程", 21));
List<VideoOrder> sameVideoOrders = matchingSame(videoOrders1, videoOrders2);
System.out.println("两订单相同商品:"+sameVideoOrders);
// 差集
List<VideoOrder> videoOrdersDifferent1 = matchingDifferent(videoOrders1, videoOrders2);
List<VideoOrder> videoOrdersDifferent2 = matchingDifferent(videoOrders2, videoOrders1);
System.out.println("订单1——两订单不同商品:"+videoOrdersDifferent1);
System.out.println("订单2——两订单不同商品:"+videoOrdersDifferent2);
// 并集
List<VideoOrder> videoOrdersAll = matchingAll(videoOrders1, videoOrders2);
System.out.println("两订单商品集合种类:"+videoOrdersAll);
// 订单价格计算
IntSummaryStatistics video1 = videoOrders1.stream().collect(Collectors.summarizingInt(obj -> obj.getMoney()));
IntSummaryStatistics video2 = videoOrders2.stream().collect(Collectors.summarizingInt(obj -> obj.getMoney()));
System.out.println("订单1平均价格:"+video1.getAverage()+"------订单2平均价格:"+video2.getAverage());
System.out.println("订单1总价:"+video1.getSum()+"------订单2总价:"+video2.getSum());
}
/**
* 一个找出两个订单中相同商品的方法并返回
* @param inputA
* @param inputB
* @return
*/
public static List<VideoOrder> matchingSame(List<VideoOrder> inputA,List<VideoOrder> inputB){
ArrayList<VideoOrder> result = new ArrayList<>();
inputA.forEach(obj1 ->{
boolean match = inputB.stream().anyMatch(obj2 -> obj2.getTitle().equals(obj1.getTitle()));
if (match) {
result.add(obj1);
}
});
return result;
}
/**
* 取两订单的差集
* @param inputA
* @param inputB
* @return
*/
public static List<VideoOrder> matchingDifferent (List<VideoOrder> inputA,List<VideoOrder> inputB){
ArrayList<VideoOrder> result = new ArrayList<>();
inputA.forEach(obj1 ->{
boolean match = inputB.stream().anyMatch(obj2 -> obj2.getTitle().equals(obj1.getTitle()));
if (!match) {
result.add(obj1);
}
});
return result;
}
/**
* 取并集的方法就是将交集和差集的结果整合到一块 我觉得这样有点憨
* @param inputA
* @param inputB
* @return
*/
public static List<VideoOrder> matchingAll (List<VideoOrder> inputA,List<VideoOrder> inputB){
List<VideoOrder> result1 = matchingSame(inputA, inputB);
List<VideoOrder> result2 = matchingDifferent(inputA, inputB);
List<VideoOrder> result3 = matchingDifferent(inputB, inputA);
result1.addAll(result2);
result1.addAll(result3);
return result1;
}
}
运行结果:
订单1——两订单不同商品:[VideoOrder{title='微服务SpringCloud, money=5'}, VideoOrder{title='百万并发实战Netty, money=9'}]
订单2——两订单不同商品:[VideoOrder{title='Jmeter压⼒测试, money=5'}, VideoOrder{title='Git+Jenkins持续集成, money=7'}, VideoOrder{title='Idea全套教程, money=21'}]
两订单商品集合种类:[VideoOrder{title='springboot教程, money=3'}, VideoOrder{title='Redis教程, money=9'}, VideoOrder{title='⽹⻚开发教程, money=9'}, VideoOrder{title='微服务SpringCloud, money=5'}, VideoOrder{title='百万并发实战Netty, money=9'}, VideoOrder{title='Jmeter压⼒测试, money=5'}, VideoOrder{title='Git+Jenkins持续集成, money=7'}, VideoOrder{title='Idea全套教程, money=21'}]
订单1平均价格:7.0------订单2平均价格:9.0
订单1总价:35------订单2总价:54
老师给的方法:
先重写了videoOrder父类object类中的equals和hashcode方法
@Override
public boolean equals(Object obj) {
if (obj instanceof VideoOrder){
return this.title.equals(((VideoOrder) obj).getTitle());
}
return super.equals(obj);
}
@Override
public int hashCode() {
return this.title.hashCode();
}
// 数据源是相同的 就不再贴上了 减少点篇幅
public static void main(String[] args) {
// 总价 35
List<VideoOrder> videoOrders1 = Arrays.asList(new VideoOrder("20190242812", "springboot教程", 3),
new VideoOrder("20194350812", "微服务SpringCloud", 5),
new VideoOrder("20190814232", "Redis教程", 9),
new VideoOrder("20190523812", "⽹⻚开发教程", 9),
new VideoOrder("201932324", "百万并发实战Netty", 9));
// 总价 54
List<VideoOrder> videoOrders2 = Arrays.asList(new VideoOrder("2019024285312", "springboot教程", 3),
new VideoOrder("2019081453232", "Redis教程", 9),
new VideoOrder("20190522338312", "⽹⻚开发教程", 9),
new VideoOrder("2019435230812", "Jmeter压⼒测试", 5),
new VideoOrder("2019323542411", "Git+Jenkins持续集成", 7),
new VideoOrder("2019323542424", "Idea全套教程", 21));
// 交集
List<VideoOrder> result1 = videoOrders1.stream().filter(obj -> videoOrders2.contains(obj)).collect(Collectors.toList());
System.out.println("交集:"+result1);
// 差集
List<VideoOrder> result2forDiff = videoOrders1.stream().filter(obj -> !videoOrders2.contains(obj)).collect(Collectors.toList());
List<VideoOrder> result3forDiff = videoOrders2.stream().filter(obj -> !videoOrders1.contains(obj)).collect(Collectors.toList());
System.out.println("订单1的差集:"+result2forDiff);
System.out.println("订单2的差集:"+result3forDiff);
// 去重并集
// 先拿到所有的并集 为不影响原集合所以不能直接用addAll()
List<VideoOrder> midList = videoOrders1.parallelStream().collect(Collectors.toList());
midList.addAll(videoOrders2);
List<VideoOrder> resultForAll = midList.stream().distinct().collect(Collectors.toList());
System.out.println("订单去重并集:"+resultForAll);
// 订单平均价格
Double order1Average = videoOrders1.stream().collect(Collectors.averagingInt(VideoOrder::getMoney));
System.out.println("订单1平均价格:"+order1Average);
Double order2Average = videoOrders2.stream().collect(Collectors.averagingInt(VideoOrder::getMoney));
System.out.println("订单2平均价格:"+order2Average);
// 订单总价
int order1Sum = videoOrders1.stream().collect(Collectors.summingInt(VideoOrder::getMoney)).intValue();
System.out.println("订单1总价格:"+order1Sum);
int order2Sum = videoOrders2.stream().collect(Collectors.summingInt(VideoOrder::getMoney)).intValue();
System.out.println("订单1总价格:"+order2Sum);
}
运行结果:
交集:[VideoOrder{title='springboot教程, money=3'}, VideoOrder{title='Redis教程, money=9'}, VideoOrder{title='⽹⻚开发教程, money=9'}]
订单1的差集:[VideoOrder{title='微服务SpringCloud, money=5'}, VideoOrder{title='百万并发实战Netty, money=9'}]
订单2的差集:[VideoOrder{title='Jmeter压⼒测试, money=5'}, VideoOrder{title='Git+Jenkins持续集成, money=7'}, VideoOrder{title='Idea全套教程, money=21'}]
订单去重并集:[VideoOrder{title='springboot教程, money=3'}, VideoOrder{title='微服务SpringCloud, money=5'}, VideoOrder{title='Redis教程, money=9'}, VideoOrder{title='⽹⻚开发教程, money=9'}, VideoOrder{title='百万并发实战Netty, money=9'}, VideoOrder{title='Jmeter压⼒测试, money=5'}, VideoOrder{title='Git+Jenkins持续集成, money=7'}, VideoOrder{title='Idea全套教程, money=21'}]
订单1平均价格:7.0
订单2平均价格:9.0
订单1总价格:35
订单1总价格:54
总结:取交、并、差集这种重写父类equals方法的写法挺好用的,简单,比我自己写的憨憨的方法好多了;统计均价和总价的方式各有千秋吧,我自己写的那种会计算统计最大最小平均多种结果,如果只需要其中一种的话可能会有点浪费资源,如果统计多种结果的话用summarizing的方法刚好。