很多时候我们查询出的集合数据有重复,比如查询出产品,有同名的产品,我们需要把同名的产品名称去掉,使用lambda表示式可以优雅的实现
package demo01;
import lombok.Data;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @Author: lidp
* @Date: 2022-04-22 14:28
* @Description:
*/
public class Test01 {
/**
* 遍历
*/
@Test
public void test01ForEach() {
List listNum = Lists.newArrayList(1, 2, 3, 9, 20, 7, 7, 20, 7);
listNum.forEach(x -> System.out.println(x));
}
/**
* stream
* 两句话理解Stream:
*
* 1.Stream是元素的集合,这点让Stream看起来用些类似Iterator;
* 2.可以支持顺序和并行的对原Stream进行汇聚的操作;
* 大家可以把Stream当成一个装饰后的Iterator。原始版本的Iterator,用户只能逐个遍历元素并对其执行某些操作;
* 包装后的Stream,用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,
* 具体这些操作如何应用到每个元素上,就给Stream就好了!原先是人告诉计算机一步一步怎么做,
* 现在是告诉计算机做什么,计算机自己决定怎么做。当然这个“怎么做”还是比较弱的。
*
* filter 条件过滤
* collect 收集结果
* Collectors.toList() -- 转为集合
*/
@Test
public void test02Filter() {
List listNum = Lists.newArrayList(1, 2, 3, 9, 20, 7, 7, 20, 7);
List collect = listNum.stream().filter(x -> x > 10).collect(Collectors.toList());
System.out.println(collect);
}
/**
* map 对值处理或者转换,如将原来集合中的数据都乘以2
*
* mapToInt 是把处理结果转为 int
*/
@Test
public void test03Map() {
List listNum = Lists.newArrayList(1, 2, 3);
List collect = listNum.stream().map(x -> x * 2).collect(Collectors.toList());
System.out.println(collect);
// () -> new ArrayList() 简写为 ArrayList::new
// (list, item) -> list.add(item) 简写为 ArrayList::add
// (result, list) -> result.addAll(list) 简写为: ArrayList::addAll
// List collect1 = listNum.stream().mapToInt(x -> x * 2).collect(() -> new ArrayList(), (list, item) -> list.add(item), (result, list) -> result.addAll(list));
List collect1 = listNum.stream().mapToInt(x -> x * 2).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println(collect1);
int[] ints = listNum.stream().mapToInt(x -> x * 2).toArray();
System.out.println(ints);
}
/**
* 分组统计
* 统计每个数字出现的次数
*/
@Test
public void test04GroupingBy() {
List listNum = Lists.newArrayList("zs", "ls", "ww", "zs", "zs", "zs", "ww");
Map collect = listNum.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// {ww=2, ls=1, zs=4}
System.out.println(collect);
// Function.identity() t -> t,指遍历出来的当前对象
Map> collect1 = listNum.stream().collect(Collectors.groupingBy(Function.identity()));
//{ww=[ww, ww], ls=[ls], zs=[zs, zs, zs, zs]}
System.out.println(collect1);
}
/**
* reduce方法:reduce方法非常的通用,后面介绍的count,sum等都可以使用其实现
*/
@Test
public void test05Reduce() {
List listNum = Lists.newArrayList(1, 2, 3, 9, 20, 7, 7, 20, 7);
System.out.println("对大于5的数累加:" + listNum);
// 对大于⑤的数累加:[1, 2, 3, 9, 20, 7, 7, 20, 7] =>大于5的数 [9, 20, 7, 7, 20, 7]
// 执行累加 9+20=29+7=36+7=43+20=63+7=70 ,如下结果为70
Integer integer = listNum.stream().filter(x -> x > 5).reduce((x, item) -> x + item).get();
System.out.println(integer); // 70
}
/**
* 大小比较&&排序&&去重
* 获取数组中的最大值
* ifPresent 存在时才返回
*/
@Test
public void test06Sort() {
List listNum = Lists.newArrayList(10, 2, 3, 9, 20, 7, 7, 20, 7);
// List listNum =new ArrayList<>();
// 大小比较
listNum.stream().max((x, y) -> (x < y) ? -1 : ((x == y) ? 0 : 1)
).ifPresent(x -> System.out.println(x));
listNum.stream().max((n1, n2) -> n1.compareTo(n2)
).ifPresent(x -> System.out.println(x));
listNum.stream().max(Integer::compareTo).ifPresent(x -> System.out.println(x));
// 从小到大
List collect = listNum.stream().sorted(Integer::compareTo).collect(Collectors.toList());
System.out.println(collect);
// 从大到小
List collect2 = listNum.stream().sorted((x, y) -> (x < y) ? 1 : ((x == y) ? 0 : -1)).collect(Collectors.toList());
System.out.println(collect2);
listNum.sort(Integer::compareTo);
System.out.println(listNum);
// 去重排序
List collect3 = listNum.stream().distinct().sorted(Integer::compareTo).collect(Collectors.toList());
System.out.println(collect3);
}
/**
* – 搜索相关
* – allMatch:是不是Stream中的所有元素都满足给定的匹配条件
* – anyMatch:Stream中是否存在任何一个元素满足匹配条件
* – findFirst: 返回Stream中的第一个元素,如果Stream为空,返回空Optional
* – noneMatch:是不是Stream中的所有元素都不满足给定的匹配条件
* – max和min:使用给定的比较器(Operator),返回Stream中的最大|最小值
*/
@Test
public void test07AllMatch() {
List listNum = Lists.newArrayList(1, 2, 3, 9, 20, 7, 7, 20, 7);
boolean b = listNum.stream().allMatch(x -> x > 10);
System.out.println(b);// false
// java.util.NoSuchElementException: No value present 无数据时报错
Integer first = listNum.stream().filter(x -> x > 2).findFirst().get();
System.out.println(first); // Optional.empty
}
/**
* 测试
* 3.3.1可变汇聚
* 可变汇聚对应的只有一个方法:collect,正如其名字显示的,它可以把Stream中的要有元素收集到一个结果容器中(比如Collection)。
* 先看一下最通用的collect方法的定义(还有其他override方法):
*
* R collect(Supplier supplier,
* BiConsumer accumulator,
* BiConsumer combiner);
* 先来看看这三个参数的含义:
* 参数一:Supplier supplier是一个工厂函数,用来生成一个新的容器;
* 参数二:BiConsumer accumulator也是一个函数,用来把Stream中的元素添加到结果容器中;
* 参数三:BiConsumer combiner还是一个函数,用来把中间状态的多个结果容器合并成为一个(并发的时候会用到)。看晕了?来段代码!
* 集合转为map
*/
@Test
public void test06() {
List list = new ArrayList<>();
list.add(new Product(1, "手机1"));
list.add(new Product(2, "手机2"));
list.add(new Product(3, "手机3"));
// 根据名称获取产品
HashMap resultMap = list.stream()
.collect(
HashMap::new, // 参数一
(map, item) -> map.put(item.getName(), item), // 参数二
HashMap::putAll); // 参数三
System.out.println(resultMap);
// 方式二
HashMap resultMap2 = list.stream()
.collect(
HashMap::new, // 参数一
(map, item) -> map.put(item.getName(), item), // 参数二
(result, map) -> result.putAll(map)); // 参数三
System.out.println(resultMap2);
// 方式三
Map resultMap3 = list.stream()
.collect(Collectors.toMap(Product::getName, x -> x.getId()));
System.out.println(resultMap3);
}
}
@Data
class Product {
private Integer id;
private String name;
public Product(Integer id, String name) {
this.id = id;
this.name = name;
}
}
/**
* 测试
* 去除重复的产品名称
*/
@Test
public void test() {
Map map1 = new HashMap<>();
map1.put("id", "1");
map1.put("name", "苹果");
Map map2 = new HashMap<>();
map2.put("id", "2");
map2.put("name", "香蕉");
Map map3 = new HashMap<>();
map3.put("id", "3");
map3.put("name", "梨子");
Map map4 = new HashMap<>();
map4.put("id", "4");
map4.put("name", "香蕉");
List