list对象根据一个或多个字段去重

797 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第十三天,点击查看活动详情


最近敲代码的时候遇到需要根据list对象中某两个字段去重并将去重后的对象返回,发现了几种去重的方式,可以根据自己的需要来使用

  1. 使用Stream.distinct()进行列表去重,使用一个字段或者多个字段去重
//根据id字段去重
List<DataModel> dataList = datas.stream().map(DataModel::getId).distinct().collect(Collectors.toList());

//根据id和name字段去重
List<DataModel> dataList = datas.stream()
                .map(t -> t.getId() + t.getName())
                .distinct().collect(Collectors.toList());
  1. distinctByKey,使用一个字段或者多个字段去重
//根据id字段去重
List<DataModel> dataList = datas.stream().filter(distinctByKey(DataModel::getId)).collect(Collectors.toList());

//根据id和name字段去重
List<DataModel> dataList = datas.stream().filter(distinctByKey(t -> t.getId() + t.getName())).collect(Collectors.toList());

//通过map的putIfAbsent方式去重
//putIfAbsent : 如果所指定的 key 已经在 HashMap 中存在,返回和这个 key 值对应的 value, 如果所指定的 key 不在 HashMap 中存在,则返回 null。
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> function) {
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(function.apply(t), Boolean.TRUE) == null;
}
  1. TreeSet 去重,该方法只能进行一个字段的去重
//通过id字段去重,并且返回数据按照id的asicc码升序排列
private static List<DataModel> distinct(List<DataModel> orderList) {
    Set<DataModel> set = new TreeSet<DataModel>(new Comparator<DataModel>() {
        public int compare(DataModel a, DataModel b) {
            return a.getId().compareTo(b.getId());
        }
    });
    return null;
}
  1. Map去重,使用一个字段或者多个字段去重
//将想要去重的字段作为key,对象作为Value,以此获得去重后的对象数据
Map<Integer, DataModel> entityMap= datas.stream().collect(Collectors.toMap(t -> t.getId() + t.getName(), Function.identity());

使用此方式会出现 java.lang.IllegalStateException: Duplicate key 异常,出现这个异常的原因是Map的key重复了,解决该异常的方式为:

//加入(entity1,entity2) -> entity1) 该代码代表如果出现重复的key,则用最新的数据作为值
Map<Integer, DataModel> entityMap= datas.stream().collect(Collectors.toMap(t -> t.getId() + t.getName(), Function.identity(), (entity1,entity2) -> entity2));