【Lambda】集合的Lambda表达式
- 【一】Stream的方法介绍
- 【1】Stream里常用的方法
- 【2】collect(toList()) & filter
- 【3】map
- 【4】flatMap
- 【5】max&min
- 【6】reduce
- 【二】常用案例总结
- 【1】准备方法查询数据库获取List结果
- 【2】取值
- 【3】分组
- 【4】去重
- 【5】排序
- 【6】list的最值、平均值、求和
- 【7】List集合求和
- 【8】过滤
- 【9】map遍历
- 【10】map转list,list转map
- 【11】list和字符串之间的转换
- 【三】其他案例分析
【一】Stream的方法介绍
【1】Stream里常用的方法
(1)collect(toList()):通过 Stream 生成一个列表
(2)map:将流中的一个值转换成一个新的值
(3)filter:过滤 Stream 中的元素
(4)flatMap:将多个 Stream 连接成一个 Stream
(5)max:求最大值
(6)min:求最小值
(7)reduce:从一组值中生成一个新的值
【2】collect(toList()) & filter
collect(toList()) 的作用是通过一个 Stream 对象生成 List 对象,案例:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = list.stream().filter((value) -> value > 2).collect(toList());
result.forEach((value) -> System.out.print(value));
上面的代码先创建了一个 List 对象并初始化,然后筛选出大于 2 的值,输出。
filter 方法的作用是过滤 Stream 中的元素,filter 方法是一个高阶函数,接收一个函数接口作为参数,此高阶函数返回一个 boolean 值,返回 true 的元素会保留下来;
collect(toList()) 方法将 filter 操作返回的 Stream 生成一个 List。
【3】map
map 函数的作用是将流中的一个值转换成一个新的值,举个例子,我们要将一个 List 转换成 List ,那么就可以使用 map 方法,示例代码:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<String> result = list.stream().map(value -> String.format("String:%s", value)).collect(toList());
result.forEach(System.out::print);
map 方法将 Integer 元素转换成 String 并使用 collect(toList()) 方法生成一个新的 List。
System.out::print 是 (value) -> System.out.print(value) 的简化版写法。
【4】flatMap
flatMap:将多个 Stream 连接成一个 Stream,这个怎么理解呢,举个栗子:
首先定义一个 List 对象,将这个对象中的每一个 String 都分割成一个字母并生成一个新的 List 对象,代码:
List<String> list = Arrays.asList("abc", "def", "ghi");
List<Character> result = list.stream().flatMap(value -> {
char[] chars = value.toCharArray();
Character[] characters = new Character[chars.length];
for(int i = 0; i < characters.length; i++){
characters[i] = chars[i];
}
return Stream.of(characters);
}).collect(toList());
result.forEach(System.out::println);
上面代码先遍历 list ,通过 flatMap 函数将每个 String 元素都生成一个新的 Stream 并将这些 Stream 连接成一个新的 Stream。
【5】max&min
求最大值最小值
List<Integer> list = Arrays.asList(0, 1, 2, 3);
Comparator<Integer> comparator = (o1, o2) -> o1.compareTo(o2);
System.out.println(list.stream().min(comparator).get());
System.out.println(list.stream().max(comparator).get());
min 和 max 函数需要一个 Comparator 对象为参数作为比对依据。
【6】reduce
从一组值中生成一个新的值,reduce 函数其实用途非常广泛,作用也比较大,我们举一个累加的例子:
List<Integer> list = Arrays.asList(0, 1, 2, 3);
int count = list.stream().reduce(0, (acc, item) -> acc + item).intValue();
System.out.println(count);
reduce 函数的一个参数为循环的初始值,这里计算累加时初始值为 0,acc 代表已经计算的结果,item 表示循环的每个元素。
【二】常用案例总结
【1】准备方法查询数据库获取List结果
用的是Mybatis-plus的mapper,也可以自己自定义一个List集合
@SpringBootTest
public class LambdaTest {
@Autowired
private UserMapper userMapper;
@Test
public void selectList() {
// 通过条件构造器查询一个List集合,如果没有条件,就可以设置null为参数
List<User> list = userMapper.selectList(null);
list.forEach(System.out::println);
}
}
实体类代码为
@Data // 包含以上,除了有参构造
@TableName("user")
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
输出的结果如下
【2】取值
从list的实体类中取出某一个目标值,放进新的list结果中。例如,从List集合的User实体类中取出name,并且放进List里。
代码如下(下面这两种写法都可以的!):
List<String> nameList = list.stream().map(User::getName).collect(Collectors.toList());
List<String> nameList = list.stream().map(it->it.getName()).collect(Collectors.toList());
执行的效果如下:
【3】分组
把List里的实体类,按照实体类中的某个值进行分类存放,结果使用Map接收。例如我们把List中的User按照年龄进行分类存放到不同的List里。
代码如下:
Map<Integer, List<User>> ageMap = list.stream().collect(Collectors.groupingBy(User::getAge));
ageMap.forEach((k,v)->{
System.out.println(k+":\n"+String.join("\n",v.toString()));
});
执行的结果如下:
【4】去重
代码如下:
@Test
public void distinctTield() {
List<String> numList = Arrays.asList("1","2","2","3","3","4","4","5","6","7","8");
List<User> userList = userMapper.selectList(null);
System.out.println(LambdaTest.distinctElements(numList));
System.out.println(LambdaTest.getNoDuplicateElements(numList));
System.out.println(LambdaTest.getDuplicateElements(numList));
System.out.println(LambdaTest.getDuplicateElementsForObject(userList));
System.out.println(LambdaTest.getNoDuplicateElementsForObject(userList));
System.out.println(LambdaTest.getElementsAfterDuplicate(userList));
System.out.println(LambdaTest.getDuplicateObject(userList));
System.out.println(LambdaTest.getNoDuplicateObject(userList));
System.out.println(LambdaTest.distinctObject(userList));
}
//(1)把重复的数据删除,只留下一个
//去重后的集合 [1, 2, 3, 4, 5, 6, 7, 8]
public static <T> List<T> distinctElements(List<T> list) {
return list.stream().distinct().collect(Collectors.toList());
}
//(2)把所有出现重复的数据都删除
//lambda表达式 去除集合重复的值 [1, 5, 6, 7, 8]
public static <T> List<T> getNoDuplicateElements(List<T> list) {
// 获得元素出现频率的 Map,键为元素,值为元素出现的次数
Map<T, Long> map = list.stream().collect(Collectors.groupingBy(p -> p,Collectors.counting()));
System.out.println("getDuplicateElements2: "+map);
return map.entrySet().stream() // Set<Entry>转换为Stream<Entry>
.filter(entry -> entry.getValue() == 1) // 过滤出元素出现次数等于 1 的 entry
.map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
.collect(Collectors.toList()); // 转化为 List
}
//(3)把出现重复的数据查出来
//lambda表达式 查找出重复的集合 [2, 3, 4]
public static <T> List<T> getDuplicateElements(List<T> list) {
return list.stream().collect(Collectors.collectingAndThen(Collectors
.groupingBy(p -> p, Collectors.counting()), map->{
map.values().removeIf(size -> size ==1); // >1 查找不重复的集合;== 1 查找重复的集合
List<T> tempList = new ArrayList<>(map.keySet());
return tempList;
}));
}
//利用set集合
public static <T> Set<T> getDuplicateElements2(List<T> list) {
Set<T> set = new HashSet<>();
Set<T> exist = new HashSet<>();
for (T s : list) {
if (set.contains(s)) {
exist.add(s);
} else {
set.add(s);
}
}
return exist;
}
/**-----------对象List做处理--------------*/
//查找对象中某个原属重复的 属性集合
public static List<String> getDuplicateElementsForObject(List<User> list) {
return list.stream().collect(Collectors.groupingBy(p -> p.getName(),Collectors.counting())).entrySet().stream()// 根据name分类,并且统计每个name出现的次数
.filter(entry -> entry.getValue() > 1) // >1 查找重复的集合;== 查找不重复的集合
.map(entry -> entry.getKey())
.collect(Collectors.toList());
}
//查找对象中某个原属未重复的 属性集合
public static List<String> getNoDuplicateElementsForObject(List<User> list){
Map<String,List<User>> map = list.stream().collect(Collectors.groupingBy(User::getName));
return map.entrySet().stream().filter(entry -> entry.getValue().size() == 1)
.map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
.collect(Collectors.toList()); // 转化为 List
}
//查找对象中某个原属去重后的集合
public static List<String> getElementsAfterDuplicate(List<User> list) {
return list.stream().map(o->o.getName()).distinct().collect(Collectors.toList());
}
//对象中某个原属重复的 对象集合
public static List<List<User>> getDuplicateObject(List<User> list) {
return list.stream().collect(Collectors.groupingBy(User::getName)).entrySet().stream()
.filter(entry -> entry.getValue().size() > 1) // >1 查找重复的集合;== 查找不重复的集合
.map(entry -> entry.getValue())
.collect(Collectors.toList());
}
//对象中某个原属未重复 对象集合
public static List<User> getNoDuplicateObject(List<User> list) {
List<User> cities = new ArrayList<>();
list.stream().collect(Collectors.groupingBy(User::getName)).entrySet().stream()
.filter(entry -> entry.getValue().size() ==1) //>1 查找重复的集合;== 查找不重复的集合;
.map(entry -> entry.getValue())
.forEach(p -> cities.addAll(p));
return cities;
}
//根据对象的某个原属去重后的 对象集合
public static List<User> distinctObject(List<User> list) {
return list.stream().filter(distinctByKey(User::getName)).collect(Collectors.toList());
}
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return object -> seen.putIfAbsent(keyExtractor.apply(object), Boolean.TRUE) == null;
}
【5】排序
代码如下:
@Test
public void sortField() {
List<Integer> list = Arrays.asList(10,1,6,4,8,7,9,3,2,5);
List<User> userList = userMapper.selectList(null);
System.out.println(sort(list));
System.out.println(reversed(list));
System.out.println(sortForObject(userList));
System.out.println(reversedForObject(userList));
System.out.println(sortForObject2(userList));
}
//list排序 正序
public static <T> List<T> sort(List<T> list){
return list.stream().sorted().collect(Collectors.toList());
}
//list排序 倒序
public static List<Integer> reversed(List<Integer> list){
return list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
}
//根据对象某个属性排序 正序
public static List<User> sortForObject(List<User> list){
return list.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
}
//根据对象某个属性排序 倒序
public static List<User> reversedForObject(List<User> list){
return list.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
}
//根据对象两个属性排序 正序
public static List<User> sortForObject2(List<User> list){
return list.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getId)).collect(Collectors.toList());
}
执行效果如下:
【6】list的最值、平均值、求和
代码如下:
@Test
public void getInfo() {
List<Integer> list = Arrays.asList(10,1,6,4,8,7,9,3,2,5);
List<User> userList = userMapper.selectList(null);
calculation1(list);
calculation2(userList);
}
//根据对象某个属性求各自值
///IntSummaryStatistics{count=4, sum=132, min=11, average=33.000000, max=55}
public static IntSummaryStatistics calculation1(List<Integer> list){
IntSummaryStatistics stat = list.stream().collect(Collectors.summarizingInt(p -> p));
System.out.println("max:"+stat.getMax());
System.out.println("min:"+stat.getMin());
System.out.println("sum:"+stat.getSum());
System.out.println("count:"+stat.getCount());
System.out.println("average:"+stat.getAverage());
Integer max = list.stream().reduce(Integer::max).get();//得到最大值
Integer min = list.stream().reduce(Integer::min).get();//得到最小值
System.out.println("max:"+max+";min:"+min);
return stat;
}
//根据对象某个属性求各自值
// sum=397,max=29,min=12,ave=23.352941176470587
public static void calculation2(List<User> list){
System.out.println("sum="+ list.stream().mapToInt(User::getAge).sum());
System.out.println("max="+ list.stream().mapToInt(User::getAge).max().getAsInt());
System.out.println("min="+ list.stream().mapToInt(User::getAge).min().getAsInt());
System.out.println("ave="+ list.stream().mapToInt(User::getAge).average().getAsDouble());
}
代码运行效果如下:
【7】List集合求和
public static void main(String[] args) {
List<BigDecimal> list = new ArrayList<>();
list.add(BigDecimal.valueOf(1.1));
list.add(BigDecimal.valueOf(1.2));
list.add(BigDecimal.valueOf(1.3));
list.add(BigDecimal.valueOf(1.4));
BigDecimal decimal = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println(decimal);
}
【8】过滤
//功能描述 过滤
public static List<City> filter(List<City> list){
return list.stream().filter(a -> a.getTotal()>44).collect(Collectors.toList());
}
【9】map遍历
(1)stream遍历key和value
map.forEach((k, v) -> System.out.println("key:value = " + k + ":" + v));
【10】map转list,list转map
(1)map和list的互相转换
//功能描述 List转map
public static void listToMap(List<User> list){
//用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2
Map<String,User> map = list.stream().collect(Collectors.toMap(User::getName,user -> user, (k1, k2) -> k1));
map.forEach((k,v) -> System.out.println("k=" + k + ",v=" + v));
}
//功能描述 map转list
public static void mapToList(Map<String,User> map){
List<User> list =
map.entrySet().stream().map(key -> key.getValue()).collect(Collectors.toList());
System.out.println(list);
list.forEach(bean -> System.out.println(bean.getName() + "," + bean.getEmail()));
}
(2)map转list
map.entrySet().stream().map(e -> new Person(e.getKey(),e.getValue())).collect(Collectors.toList());
map.keySet().stream().collect(Collectors.toList());
map.values().stream().collect(Collectors.toList());
(3)list转map
Map<Integer, String> result1 = list.stream().collect(
Collectors.toMap(Hosting::getId, Hosting::getName));
Map<Long, User> maps = userList.stream().collect(Collectors.toMap(User::getId,Function.identity()));
//看来还是使用JDK 1.8方便一些。另外,转换成map的时候,可能出现key一样的情况,如果不指定一个覆盖规则,上面的代码是会报错的。转成map的时候,最好使用下面的方式
Map<Long, User> maps = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key2));
【11】list和字符串之间的转换
//功能描述 字符串转list
public static void stringToList(String str){
//不需要处理
//<String> list = Arrays.asList(str.split(","));
//需要处理
List<String> list = Arrays.asList(str.split(",")).stream().map(string -> String.valueOf(string)).collect(Collectors.toList());
list.forEach(string -> System.out.println(string));
}
//功能描述 姓名以逗号拼接
public static void joinStringValueByList(List<User> list){
System.out.println(list.stream().map(User::getName).collect(Collectors.joining(",")));
}
//功能描述 姓名以逗号拼接
public static void joinStringValueByList2(List<String> list){
//方式一
System.out.println(String.join(",", list));
//方式二
System.out.println(list.stream().collect(Collectors.joining(",")));
}