java Lambda表达式集合去重&stream

1.背景

很多时候我们查询出的集合数据有重复,比如查询出产品,有同名的产品,我们需要把同名的产品名称去掉,使用lambda表示式可以优雅的实现

2.stream使用

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<Integer> listNum = Lists.newArrayList(1, 2, 3, 9, 20, 7, 7, 20, 7);
        listNum.forEach(x -> System.out.println(x));
    }

    /**
     * stream
     * 两句话理解Stream:
     * <p>
     * 1.Stream是元素的集合,这点让Stream看起来用些类似Iterator;
     * 2.可以支持顺序和并行的对原Stream进行汇聚的操作;
     * 大家可以把Stream当成一个装饰后的Iterator。原始版本的Iterator,用户只能逐个遍历元素并对其执行某些操作;
     * 包装后的Stream,用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,
     * 具体这些操作如何应用到每个元素上,就给Stream就好了!原先是人告诉计算机一步一步怎么做,
     * 现在是告诉计算机做什么,计算机自己决定怎么做。当然这个“怎么做”还是比较弱的。
     * <p>
     * filter 条件过滤
     * collect 收集结果
     * Collectors.toList() -- 转为集合
     */
    @Test
    public void test02Filter() {
        List<Integer> listNum = Lists.newArrayList(1, 2, 3, 9, 20, 7, 7, 20, 7);
        List<Integer> collect = listNum.stream().filter(x -> x > 10).collect(Collectors.toList());
        System.out.println(collect);
    }

    /**
     * map 对值处理或者转换,如将原来集合中的数据都乘以2
     * <p>
     * mapToInt 是把处理结果转为 int
     */
    @Test
    public void test03Map() {
        List<Integer> listNum = Lists.newArrayList(1, 2, 3);
        List<Integer> 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<Integer> collect1 = listNum.stream().mapToInt(x -> x * 2).collect(() -> new ArrayList(), (list, item) -> list.add(item), (result, list) -> result.addAll(list));
        List<Integer> 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<String> listNum = Lists.newArrayList("zs", "ls", "ww", "zs", "zs", "zs", "ww");
        Map<String, Long> 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<String, List<String>> 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<Integer> 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<Integer> listNum = Lists.newArrayList(10, 2, 3, 9, 20, 7, 7, 20, 7);
        //  List<Integer> 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<Integer> collect = listNum.stream().sorted(Integer::compareTo).collect(Collectors.toList());
        System.out.println(collect);
        // 从大到小
        List<Integer> 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<Integer> 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<Integer> 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> R collect(Supplier<R> supplier,
     * BiConsumer<R, ? super T> accumulator,
     * BiConsumer<R, R> combiner);
     * 先来看看这三个参数的含义:
     * 参数一:Supplier supplier是一个工厂函数,用来生成一个新的容器;
     * 参数二:BiConsumer accumulator也是一个函数,用来把Stream中的元素添加到结果容器中;
     * 参数三:BiConsumer combiner还是一个函数,用来把中间状态的多个结果容器合并成为一个(并发的时候会用到)。看晕了?来段代码!
     * 集合转为map
     */
    @Test
    public void test06() {
        List<Product> list = new ArrayList<>();
        list.add(new Product(1, "手机1"));
        list.add(new Product(2, "手机2"));
        list.add(new Product(3, "手机3"));
        // 根据名称获取产品
        HashMap<String, Product> resultMap = list.stream()
                .collect(
                        HashMap::new,  // 参数一
                        (map, item) -> map.put(item.getName(), item), // 参数二
                        HashMap::putAll); // 参数三
        System.out.println(resultMap);
        // 方式二
        HashMap<String, Product> resultMap2 = list.stream()
                .collect(
                        HashMap::new,  // 参数一
                        (map, item) -> map.put(item.getName(), item), // 参数二
                        (result, map) -> result.putAll(map)); // 参数三
        System.out.println(resultMap2);
        // 方式三
        Map<String, Integer> 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;
    }
}

3.集合去重

 /**
     * 测试
     * 去除重复的产品名称
     */
    @Test
    public void test() {
        Map<String, String> map1 = new HashMap<>();
        map1.put("id", "1");
        map1.put("name", "苹果");

        Map<String, String> map2 = new HashMap<>();
        map2.put("id", "2");
        map2.put("name", "香蕉");

        Map<String, String> map3 = new HashMap<>();
        map3.put("id", "3");
        map3.put("name", "梨子");

        Map<String, String> map4 = new HashMap<>();
        map4.put("id", "4");
        map4.put("name", "香蕉");

        List<Map<String, String>> list = new ArrayList<>();
        list.add(map1);
        list.add(map2);
        list.add(map3);
        list.add(map4);
        // 去重前:[{name=苹果, id=1}, {name=香蕉, id=2}, {name=梨子, id=3}, {name=香蕉, id=4}]
        System.out.println("去重前:" + list);
        ArrayList<Map<String, String>> mapArrayList = list.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(
                                s -> String.valueOf(s.get("name"))))), ArrayList::new));

        // 去重后:[{name=梨子, id=3}, {name=苹果, id=1}, {name=香蕉, id=2}]
        System.out.println("去重后:" + mapArrayList);
    }

3.完美!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值