🍰 个人主页:_小白不加班__
🍞文章有不合理的地方请各位大佬指正。
🍉文章不定期持续更新,如果我的文章对你有帮助➡️ 关注🙏🏻 点赞👍 收藏⭐️
一、收集器常用api
二、收集器常用静态方法的代码举例
使用上述收集解决一下问题:
使用收集器静态方法收集如下数据:
- 所有商品名称的集合
- 获取所有商品类型
- 在"水果"分类中有几种商品
- "水果"分类平均价格
- 求所有商品 总库存量
- 将所有水果名称 连起来,中间用逗号隔开
- 库存最多的商品
- 库存最少的商品
- 按类别分组,相同类别的商品存放到同一个集合中
求出每个类别各有多少种商品
求出每个类别 拥有最大库存数的商品- 按谓词分组,筛选库存量 大于350和 小于于等于350 分为两组
1. toList()
所有商品名称的集合
/**
* 所有商品名称的集合
*/
@Test
public void streamDemo110() {
List<Product> products = new ArrayList<>();
// id name description price stockQuantity category
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
List<String> names = products.stream().map(Product::getName).collect(toList());
System.out.println(names);// [苹果, 香蕉, 帽子, 上衣]
}
2. toSet()
获取所有产品类型名称
/**
* 获取所有产品类型
*/
@Test
public void streamDemo111() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
Set<String> category = products.stream().map(Product::getCategory).collect(toSet());
System.out.println(category);// [水果, 衣服]
}
3. counting()
求有几种水果
/**
* 求有几种水果
*/
@Test
public void streamDemo112() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
Long num = products.stream()
.filter(p -> "水果".equals(p.getCategory()))
.collect(counting());
System.out.println("有" + num+"种水果");//有2种水果
}
4. averagingDouble()
水果平均价格
/**
* 求"水果"的评价价格
*/
@Test
public void streamDemo114() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
Double avg = products.stream()
.filter(p -> "水果".equals(p.getCategory()))
.collect(averagingDouble(Product::getPrice));
System.out.println("水果平均价格:"+avg);//水果平均价格:75.0
}
5. summingInt()
求所有商品 总库存量
/**
* 求所有商品 总库存量
*/
@Test
public void streamDemo113() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
Integer stock2 = products.stream().collect(summingInt(Product::getStockQuantity));
System.out.println("库存量:" + stock2);// 库存量:1000
}
6. joining()
将所有水果名称 连起来
/**
* 将所有水果名称 连起来
*/
@Test
public void streamDemo115() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
String names = products.stream()
.filter(p -> "水果".equals(p.getCategory()))
.map(Product::getName).collect(joining(","));
System.out.println(names);// 苹果,香蕉
}
7. maxBy()
库存最多的商品
/**
* 获取商品集合中 最大库存数
*/
@Test
public void streamDemo116() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
Optional<Product> collect = products.stream()
.collect(maxBy(comparing(Product::getStockQuantity)));
System.out.println("库存最多的商品:"+collect.get().getName());
//库存最多的商品:上衣
}
8. minBy()
库存最少的商品
/**
* 获取商品集合中 最大库存数
*/
@Test
public void streamDemo116() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
Optional<Product> collect = products.stream()
.collect(minBy(comparing(Product::getStockQuantity)));
System.out.println("库存最少的商品:"+collect.get().getName());
//库存最少的商品:苹果
}
9. groupingBy()
按属性分组
按类别分组,相同类别的商品存放到同一个集合中
/**
* 按类别分组,相同类别的商品存放到同一个集合中
*/
@Test
public void streamDemo181() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
Map<String,List<Product>> map = products.stream().collect(groupingBy(Product::getCategory));
map.forEach((k,v)->{
System.out.println(k+"====="+v);
});
/*
水果=====[Product(id=1, name=苹果, description=好吃的苹果, price=100.0, stockQuantity=100, category=水果),
Product(id=2, name=香蕉, description=好吃的香蕉, price=50.0, stockQuantity=200, category=水果)]
衣服=====[Product(id=3, name=帽子, description=帽子, price=80.0, stockQuantity=300, category=衣服),
Product(id=4, name=上衣, description=上衣, price=60.0, stockQuantity=400, category=衣服)]
* */
}
groupingBy()拓展使用
groupingBy(Function, Collector)
- 第二个参数可以接受上面任意一个收集器静态方法
求出每个类别各有多少种商品
求出每个类别 拥有最大库存数的商品
/**
* 求出每个类别各有多少种商品
* 求出每个类别 拥有最大库存数的商品
*/
@Test
public void streamDemo21() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
// 求出每个类别各有多少种商品
Map<String, Long> map = products.stream().collect(groupingBy(Product::getCategory, counting()));
map.forEach((k, v) -> {
System.out.println(k + "有" + v+"种商品");
// 水果有2种商品
// 衣服有2种商品
});
// 求出每个类别 拥有最大库存数的商品
Map<String,Optional <Product>> map1 = products.stream().collect(groupingBy(Product::getCategory, maxBy(comparingInt(Product::getStockQuantity))));
map1.forEach((k,v)->{
System.out.println("【"+k+"】库存最多的商品:"+v.get().getName()+",库存量:"+v.get().getStockQuantity());
//【水果】库存最多的商品:香蕉,库存量:200
//【衣服】库存最多的商品:上衣,库存量:400
});
10. partitioningBy()
分区:按谓词分组,筛选库存量 大于350和 小于于等于350 分为两组
/**
* 按谓词分组,筛选库存量 大于350和 小于于等于350 分为两组
*/
@Test
public void streamDemo1181() {
List<Product> products = new ArrayList<>();
products.add(new Product(1L, "苹果", "好吃的苹果", 100.0, 100, "水果"));
products.add(new Product(2L, "香蕉", "好吃的香蕉", 50.0, 200, "水果"));
products.add(new Product(3L, "帽子", "帽子", 80.0, 300, "衣服"));
products.add(new Product(4L, "上衣", "上衣", 60.0, 400, "衣服"));
Map<Boolean, List<Product>> map = products.stream().collect(partitioningBy(p -> stockGt350(p)));
map.forEach((k, v) -> {
System.out.println(k + "=====" + v);
});
/**
* false=====[Product(id=1, name=苹果, description=好吃的苹果, price=100.0, stockQuantity=100, category=水果),Product(id=2, name=香蕉, description=好吃的香蕉, price=50.0, stockQuantity=200, category=水果), Product(id=3, name=帽子, description=帽子, price=80.0, stockQuantity=300, category=衣服)]
* true=====[Product(id=4, name=上衣, description=上衣, price=60.0, stockQuantity=400, category=衣服)]
*/
}
public boolean stockGt350(Product product) {
return product.getStockQuantity() > 350;
}
三、广义归约Collectors.reducing 在收集器中的使用场景和案例
上一篇文章《reduce归约:深入理解java8中的归约reduce》提到了reduce
中间操作的使用规则,这次reducing
是作为终端操作,在搜集器中使用。
收集器常用api都是Collectors.reducing
的特殊情况
1. reducing(BinaryOperator)
流中的前两个元素进行累积计算
/**
* 工资最高人的姓名
*/
@Test
public void streamDemo1081() {
List<Worker> workers = new ArrayList<>();
workers.add(new Worker("张三", 1000, 20, Arrays.asList(1, 2, 45, 23, 22)));
workers.add(new Worker("李四", 2000, 30, Arrays.asList(10, 20, 450, 230, 220)));
Optional<Worker> worker = workers.stream()
.collect(reducing((w1, w2) -> w1.getSalary() > w2.getSalary() ? w1 : w2));
System.out.println("工资最高:"+worker.get().getName());//工资最高:李四
}
2. reducing(Object, BinaryOperator)
- 此方法接受一个初始值(T)和一个二元操作符
(BinaryOperator<T>)
- 首先使用初始值作为累积器的初始值,然后将流中的元素依次与累积器的当前值进行累积计算。
//计算整数流中所有偶数元素的和
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenSums = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.reducing(0, Integer::sum));
System.out.println("Even sums: " + evenSums); // 输出:Even sums: [6]
3. reducing(Object, Function, BinaryOperator)
- 此方法接受一个初始值
(U)
、一个映射函数(Function<U, ? super T, U>)
和一个二元操作符(BinaryOperator<U>)
- 首先使用初始值作为累积器的初始值,然后将流中的元素依次应用映射函数,并将映射函数的结果与累积器的当前值进行累积计算。
/**
* 发放工资总和
*/
@Test
public void streamDemo1081() {
List<Worker> workers = new ArrayList<>();
workers.add(new Worker("张三", 1000, 20, Arrays.asList(1, 2, 45, 23, 22)));
workers.add(new Worker("李四", 2000, 30, Arrays.asList(10, 20, 450, 230, 220)));
Integer countSalary = workers.stream()
.collect(reducing(0, Worker::getSalary, (x, y) -> x + y));
System.out.println("总发放:" + countSalary + "元");// 总发放:3000元
// 等价于 workers.stream().collect(summingInt(Worker::getSalary));
}
参考:《java8 实战》
🍉文章不定期持续更新,如果我的文章对你有帮助➡️ 关注🙏🏻 点赞👍 收藏⭐️