zoukankan      html  css  js  c++  java
  • 【java】对list集合进行去重 传统方式 VS Lambda

            说道集合的去重,我们就肯定能想到唯一元素集合set,还有map中的key。那么我们传统的去重的方式肯定是要选择set或者是map来实现了,另外在对实体对象类型进行去重的时候,我们可能会指定实体中的一个字段,这种情况也是属于多数的,那么我们要怎么实现呢?

    一、传统map实现

            首先我们来看map实现,由于list内对象是不固定的,所以我这里写了一个通用的,按照id去重的例子:

    /**
    * 根据属性id去重
    * @param objList 要去重的集合list
    * @param <E> list内容泛型
    * @return 返回去重后的list
    * @throws NoSuchFieldException
    * @throws IllegalAccessException
    */
    public static <E> List<E> removeDuplicateId(List<E> objList) throws NoSuchFieldException, IllegalAccessException {
    List<E> newList = new ArrayList<>();
    HashMap<String, String> map = new HashMap<>();
    for (E t : objList) {
    // 为空则不进行比较(按需确定是否要添加)
    if (org.springframework.util.StringUtils.isEmpty(getFieldValue(t,"id"))) {
    continue;
    }
    String id = String.valueOf(getFieldValue(t,"id"));
    String value = map.get(id);
    if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 说明取到的这个name是第一次取到
    map.put(id, id);
    newList.add(t); //newList就是我们想要的去重之后的结果
    }
    }
    return newList;
    }

         当然这里还加入了一些自定义的配置,如字段为空的时候就舍弃等,可以看出来都是根据map特性,如果在map中找到了值,则不再add。

         如果扩展成根据指定字段去重,则代码修改为把字段的string传入即可:

    public static <E> List<E> removeDuplicateId(List<E> objList,String filedName) throws NoSuchFieldException, IllegalAccessException {

    if (StringUtils.isBlank(filedName)){

    return objList;

    }

    List<E> newList = new ArrayList<>();

    HashMap<String, String> map = new HashMap<>();

    for (E t : objList) {

    // 为空则不进行比较(按需确定是否要添加)

    if (org.springframework.util.StringUtils.isEmpty(getFieldValue(t,filedName))) {

    continue;

    }

    String id = String.valueOf(getFieldValue(t,filedName));

    String value = map.get(id);

    if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 说明取到的这个name是第一次取到

    map.put(id, id);

    newList.add(t); //newList就是我们想要的去重之后的结果

    }

    }

    return newList;

    }

    如果要根据多个字段去重,需要怎样呢?扩展第二个参数为字符数组即可:

    public static <E> List<E> removeDuplicateId(List<E> objList,String... filedNames) throws NoSuchFieldException, IllegalAccessException {

    if (filedNames==null||filedNames.length==0){

    return objList;

    }

    List<E> newList = new ArrayList<>();

    HashMap<String, String> map = new HashMap<>();

    for (E t : objList) {

    String key = "";

    for (int i = 0; i < filedNames.length; i++) {

    key += String.valueOf(getFieldValue(t,filedNames[i]));

    }

    String value = map.get(key);

    if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 说明取到的这个name是第一次取到

    map.put(key, key);

    newList.add(t); //newList就是我们想要的去重之后的结果

    }

    }

    return newList;

    }

    有了map的实现,set的也不难了,只需要把里面判断和添加map的代码修改为set对象即可。

    二、labmda实现

            lambda实现就比较简单了,看一下三连:

    单个字段去重:

    List<Member> memberList= members.stream() .collect(

    Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(member -> member.getName()))), ArrayList::new));

    多个字段去重:

    List<Member> memberList = members.stream() .collect(

    Collectors.collectingAndThen(

    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(member -> member.getName()+"-"+member.getId()))), ArrayList::new));

    还有一个根据某个或者几个字段分组,也可以满足这种需求:

    Map<String,List<Member>> map = members.stream().collect(Collectors.groupingBy(Member::getName));

    三、总结

            相比较来说,使用lambda进行去重,写法比较简单,代码简洁有利于阅读,而传统方式则过于繁琐,需要写专门的util进行处理,但是从另外的角度来讲传统方式比较灵活,可以增加lambda没有的判断,如果需要去重的字段有为null的情况,使用lambda分组或者去重是会报空指针错误的。

  • 相关阅读:
    写了一个Windows服务,通过C#模拟网站用户登录并爬取BUG列表查询有没有新的BUG,并提醒我
    WCF快速上手(二)
    Oracle递归查询
    100多行代码实现6秒完成50万条多线程并发日志文件写入
    C#写日志工具类
    WPF定时刷新UI界面
    HttpUtil工具类
    WPF GridView的列宽度设置为按比例分配
    Visifire图表
    C# BackgroundWorker 的使用、封装
  • 原文地址:https://www.cnblogs.com/yelanggu/p/13456976.html
Copyright © 2011-2022 走看看