Steam流是Java8新增的特性,对于集合的处理更加简洁,有更高的可读性和可维护性,可以使用Lambda表达式作为参数
Goods.class
package priv.cwr.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import priv.cwr.enums.GoodsTypeEnum;
import java.math.BigDecimal;
/**
* @Description 商品
* @Author CWR
* @Date 2021/7/8 18:07
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Goods implements Comparable {
/**
* id
*/
private Long id;
/**
* 商品姓名
*/
private String name;
/**
* 商品类型
*/
private GoodsTypeEnum type;
/**
* 商品价格
*/
private Double price;
/**
* 销量
*/
private Integer salesVolume;
/**
* 产地
*/
private String city;
@Override
public int compareTo(Object o) {
return 0;
}
}
GoodsVo.class
package priv.cwr.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import priv.cwr.enums.GoodsTypeEnum;
/**
* @Description 商品Vo
* @Author CWR
* @Date 2021/7/8 18:07
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GoodsVo {
/**
* id
*/
private Long id;
/**
* 商品姓名
*/
private String name;
/**
* 商品类型
*/
private GoodsTypeEnum type;
/**
* 商品价格
*/
private Double price;
/**
* 销量
*/
private Integer salesVolume;
/**
* 产地
*/
private String city;
}
GoodsTypeEnum.class
package priv.cwr.enums;
/**
* @Description 商品类型枚举
* @Author CWR
* @Date 2021/7/8 18:08
*/
public enum GoodsTypeEnum {
/**
* 服装
*/
CLOTHING(0, "服装"),
/**
* 电子产品
*/
ELECTRONIC_PRODUCT(1, "电子产品"),
/**
* 其他
*/
OTHER(2, "其他");
int value;
String text;
/**
* 私有构造
*
* @param value
* @param text
*/
GoodsTypeEnum(int value, String text) {
this.value = value;
this.text = text;
}
/**
* getter
*
* @return
*/
public int getValue() {
return this.value;
}
public String getText() {
return this.text;
}
/**
* 通过value获取text
*
* @param value 枚举值
* @return
*/
public static String getTextByValue(Integer value) {
if (value == null) {
return null;
}
// 遍历当前枚举列表
for (GoodsTypeEnum temp : GoodsTypeEnum.values()) {
// value值相等
if (temp.getValue() == value) {
return temp.getText();
}
}
return null;
}
/**
* 通过Text获取Value
*
* @param text
* @return
*/
public static Integer getValueByText(String text) {
// 遍历当前枚举列表
for (GoodsTypeEnum temp : GoodsTypeEnum.values()) {
// value值相等
if (temp.getText().equals(text)) {
return temp.value;
}
}
return null;
}
}
案例
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import priv.cwr.enums.GoodsTypeEnum;
import priv.cwr.model.Goods;
import priv.cwr.model.GoodsVo;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.*;
/**
* @Description TODO
* @Author CWR
* @Date 2021/7/5 16:59
*/
public class LearnDemo {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
/**
* 初始化数据
*
* @return
*/
public static List<Goods> dataInit() {
List<Goods> goods = new ArrayList<>();
goods.add(new Goods(1001L, "商品1001", GoodsTypeEnum.CLOTHING, 9554.42, 1400, "重庆"));
goods.add(new Goods(1002L, "商品1002", GoodsTypeEnum.CLOTHING, 5899.03, 2548, "北京"));
goods.add(new Goods(1003L, "商品1003", GoodsTypeEnum.ELECTRONIC_PRODUCT, 86522.00, 3685, "上海"));
goods.add(new Goods(1004L, "商品1004", GoodsTypeEnum.ELECTRONIC_PRODUCT, 6521.80, 300, "北京"));
goods.add(new Goods(1005L, "商品1005", GoodsTypeEnum.ELECTRONIC_PRODUCT, 7863.75, 500, "江苏"));
goods.add(new Goods(1006L, "商品1006", GoodsTypeEnum.CLOTHING, 4759.69, 351, "北京"));
goods.add(new Goods(1007L, "商品1007", GoodsTypeEnum.OTHER, 7589.00, 517, "重庆"));
goods.add(new Goods(1008L, "商品1008", GoodsTypeEnum.CLOTHING, 6584.00, 600, "重庆"));
goods.add(new Goods(1009L, "商品1009", GoodsTypeEnum.OTHER, 5785.25, 3025, "重庆"));
goods.add(new Goods(1010L, "商品1010", GoodsTypeEnum.OTHER, 6889.10, 854, "上海"));
goods.add(new Goods(1011L, "商品1011", GoodsTypeEnum.CLOTHING, 5630.50, 3652, "湖南"));
goods.add(new Goods(1012L, "商品1012", GoodsTypeEnum.ELECTRONIC_PRODUCT, 6372.90, 15, "重庆"));
goods.add(new Goods(1013L, "商品1013", GoodsTypeEnum.OTHER, 7470.99, 25, "湖南"));
goods.add(new Goods(1014L, "商品1014", GoodsTypeEnum.ELECTRONIC_PRODUCT, 6396.10, 352, "黑龙江"));
goods.add(new Goods(1015L, "商品1015", GoodsTypeEnum.OTHER, 9554.39, 1500, "重庆"));
return goods;
}
public static void main(String[] args) {
// 初始化数据
List<Goods> goodsList = dataInit();
printResult("完整数据", goodsList);
// 基础使用
// 1.筛选产地为重庆的的服装类商品
List<Goods> cqGoodsList = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()) && GoodsTypeEnum.CLOTHING.equals(t.getType()))
.collect(toList());
printResult("1.重庆服装类商品:", cqGoodsList);
// 2.查询所有商品所在产地并去重
List<String> cityNameList = goodsList.stream()
.map(Goods::getCity)
.distinct()
.collect(toList());
printResult("2.产地:", cityNameList);
// 3.查询所有商品所在产地以逗号分隔(去重)
String cityNames = goodsList.stream()
.map(Goods::getCity)
.distinct()
.collect(joining(","));
printResult("3.产地:", cityNames);
// 4.类型转换
List<GoodsVo> goodsVos = goodsList.stream()
.map(t -> {
GoodsVo vo = new GoodsVo();
// BeanUtils.copyProperties(t, vo);
return vo;
})
.collect(Collectors.toList());
printResult("4.类型转换:", cityNames);
// 排序
// 5.查询重庆商品,按价格降序、销量降序
List<Goods> orderList = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()))
.sorted(
// Comparator.comparing(Goods::getPrice, Comparator.reverseOrder())
// .thenComparing(Goods::getSalesVolume, Comparator.reverseOrder())
Comparator.comparing(t->t.getPrice() * t.getSalesVolume())
)
.collect(toList());
printResult("5.重庆商品排序:", orderList);
// 常规数据处理(平均数、和、最值)
// 6.重庆商品平均价格
OptionalDouble average = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()))
.mapToDouble(Goods::getPrice)
.average();
Double average2 = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()))
.collect(Collectors.averagingDouble(Goods::getPrice));
printResult("6.重庆商品平均价格:", average);
// 7.重庆商品价格总和
double sum = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()))
.mapToDouble(Goods::getPrice)
.sum();
printResult("7.重庆商品价格总和:", sum);
// 8.最高价格商品
Optional<Goods> cqMaxPriceGoods = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()))
.max(Comparator.comparing(Goods::getPrice));
Optional<Goods> cqMaxPriceGoods2 = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()))
.collect(maxBy(Comparator.comparing(Goods::getPrice)));
printResult("8.重庆最高价格商品:", cqMaxPriceGoods.orElse(null));
// 9.重庆商品最高价格
OptionalDouble cqMaxPrice = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()))
.mapToDouble(Goods::getPrice)
.max();
printResult("9.重庆商品最高价格:", cqMaxPrice.orElse(0));
// 10.重庆最高销售额商品
Optional<Goods> cqMaxAmount = goodsList.stream()
.filter(t -> "重庆".equals(t.getCity()))
.max(Comparator.comparing(t -> t.getPrice() * t.getSalesVolume()));
printResult("10.重庆最高销售额商品:", cqMaxAmount.orElse(null));
// reduce(归约,将流中元素反复结合起来,得到一个值)
// 11.重庆商品销量总和
int sumByReduce = goodsList.stream()
.mapToInt(Goods::getSalesVolume)
.reduce(0, (t1, t2) -> t1 + t2);
printResult("11.重庆商品价格总和:", sumByReduce);
// 12.重庆价格最高的商品
Optional<Goods> maxByReduce = goodsList.stream()
.reduce((t1, t2) -> t1.getPrice().compareTo(t2.getPrice()) >= 1 ? t1 : t2);
printResult("12.重庆价格最高的商品:", maxByReduce.orElse(null));
// 进阶使用(分组、二次处理)
// 过去分组方式
groupByBefore(goodsList);
// 13.按产地分组
Map<String, List<Goods>> cityGroup = goodsList.stream()
.collect(Collectors.groupingBy(Goods::getCity));
printResult("13.按产地分组:", cityGroup);
// 14.按产地和商品类型两级分组
Map<String, Map<GoodsTypeEnum, List<Goods>>> cityTypeGroup = goodsList.stream()
.collect(
groupingBy(
Goods::getCity, groupingBy(Goods::getType)
)
);
printResult("14.按产地和商品类型两级分组:", cityTypeGroup);
// 15.按产地和商品类型两级分组并获取最高价格商品
Map<String, Map<GoodsTypeEnum, Optional<Goods>>> cityTypeGroupPriceMaxOptional = goodsList.stream()
.collect(
groupingBy(
Goods::getCity,
groupingBy(
Goods::getType,
maxBy(Comparator.comparing(Goods::getPrice))
)
)
);
printResult("15.按产地和商品类型两级分组并获取最高价格商品:", cityTypeGroupPriceMaxOptional);
// 16.按产地和商品类型两级分组并获取最高价格商品(拆箱)
Map<String, Map<GoodsTypeEnum, Goods>> cityTypeGroupPriceMax = goodsList.stream()
.collect(
groupingBy(
Goods::getCity,
groupingBy(
Goods::getType,
collectingAndThen(
maxBy(Comparator.comparing(Goods::getPrice)),
t -> t.orElse(null)
)
)
)
);
printResult("16.按产地和商品类型两级分组并获取最高价格商品(拆箱):", cityTypeGroupPriceMax);
// 17.按产地分组并计算产地商品总销量
Map<String, Integer> cityPriceSumGroup = goodsList.stream()
.collect(
groupingBy(Goods::getCity, summingInt(Goods::getSalesVolume))
);
printResult("17.按产地分组并计算产地商品总销量:", cityPriceSumGroup);
// 18.按产地分组并查询最高价格商品
Map<String, Optional<Goods>> cityPriceMaxGoodsGroup = goodsList.stream()
.collect(
groupingBy(Goods::getCity, maxBy(Comparator.comparing(Goods::getPrice)))
);
printResult("18.按产地分组并查询最高价格商品:", cityPriceMaxGoodsGroup);
// 19.按产地分组并统计价格(数量、最大值、最小值、平均数)
Map<String, DoubleSummaryStatistics> cityPriceInfoGroup = goodsList.stream()
.collect(
groupingBy(Goods::getCity, summarizingDouble(Goods::getPrice))
);
printResult("19.按产地分组并统计价格:", cityPriceInfoGroup);
// 20.按产地分组并统计销售总额
Map<String, Double> citySalesTotalGroup = goodsList.stream()
.collect(
groupingBy(Goods::getCity, summingDouble(t -> t.getPrice() * t.getSalesVolume()))
);
printResult("20.按产地分组并统计销售总额:", citySalesTotalGroup);
}
/**
* 过去方式分组
*
* @param list
*/
public static void groupByBefore(List<Goods> list) {
// 结果map
Map<String, List<Goods>> resultMap = new HashMap<>(16);
// 按产地分组
for (Goods t : list) {
String key = t.getCity();
// 是否已有对应key
if (resultMap.containsKey(key)) {
// 是否value为空
List<Goods> value = resultMap.get(key);
if (value == null) {
value = new ArrayList<>();
value.add(t);
} else {
value.add(t);
}
} else {
// 不存在则新增
List<Goods> value = new ArrayList<>();
value.add(t);
resultMap.put(key, value);
}
}
printResult("过去分组", resultMap);
}
/**
* 输出结果
*
* @param message 提示信息
* @param object 结果值
*/
public static void printResult(String message, Object object) {
try {
System.out.println(message + " -> " + OBJECT_MAPPER.writeValueAsString(object));
System.out.println();
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}