List列表运用Java8的stream流按某字段去重

思路

1重写Book类的equals和hashCode方法,以name来判断比较是否相同,然后用stream的distinct方法来去重

代码:

class Book {
    ...
 
    @Override
    public String toString() {
        return String.format("(%s,%s,%s)", id, name, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()));
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Objects.equals(name, book.name);
    }
}
 
List<Book> distinctNameBooks1 = books.stream().distinct().collect(Collectors.toList());
System.out.println(distinctNameBooks1);
总结:

通过重写equals和hashCode方法,按实际需求来比较,可直接使用stream的distinct方法去重,比较方便;
有时对象类不方便或者不能修改,如它已实现好或者是引用的三方包不能修改,该方法不能灵活地按字段来去重。

2通过Collectors.collectingAndThen的Collectors.toCollection,里面用TreeSet在构造函数中指定字段

代码:

List<Book> distinctNameBooks2 = books.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName()))), ArrayList::new));
System.out.println(distinctNameBooks2);
总结:

使用stream流提供的方法,代码很简洁,但不足是虽然实现了去重效果,但list里的顺序变化了,而有的场景需要保持顺序。

3、通过stream的filter方法来去重,定义一个去重方法,参数为Function类型,返回值为Predicate类型

代码:

public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
    Map<Object, Boolean> map = new HashMap<>();
    return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
 
List<Book> distinctNameBooks3 = books.stream().filter(distinctByKey(o -> o.getName())).collect(Collectors.toList());
System.out.println(distinctNameBooks3);
总结:

通过封装定义一个去重方法,配合filter方法可灵活的按字段去重,保持了原列表的顺序,不足之处是内部定义了一个HashMap,有一定内存占用,并且多了一个方法定义。

4、通过stream的filter方法来去重,不定义去重方法,在外面创建HashMap

代码:

Map<Object, Boolean> map = new HashMap<>();
List<Book> distinctNameBooks4 = books.stream().filter(i -> map.putIfAbsent(i.getName(), Boolean.TRUE) == null).collect(Collectors.toList());
System.out.println(distinctNameBooks4);
总结:

仍然是配合filter方法实现去重,没有单独创建方法,临时定义一个HashMap,保持了原列表的顺序,不足之处是有一定内存占用。

PS:暂时没找到stream流原生支持的可按某字段去重并且保持原列表顺序的方法

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java使用Stream去重可以通过使用distinct()方法来实现。具体实现方法如下: ```java List<Integer> list = Arrays.asList(1, 2, 3, 2, 4, 3, 5); List<Integer> distinctList = list.stream().distinct().collect(Collectors.toList()); System.out.println(distinctList); // 输出:[1, 2, 3, 4, 5] ``` 上述代码中,我们首先创建了一个包含重复元素的List集合,然后使用stream()方法将其转换为Stream,接着使用distinct()方法去重,最后使用collect()方法将去重后的元素收集到一个新的List集合中。 另外,如果我们需要根据对象的某个属性进行去重,可以使用自定义的方法来实现。具体实现方法如下: ```java public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) { Map<Object, Boolean> seen = new ConcurrentHashMap<>(); return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; } List<UserAccount> list = new ArrayList<>(); UserAccount a = new UserAccount(); a.setId(57L); UserAccount b = new UserAccount(); b.setId(57L); UserAccount c = new UserAccount(); c.setId(56L); list.add(a); list.add(b); list.add(c); List<UserAccount> distinctList = list.stream().filter(distinctByKey(UserAccount::getId)).collect(Collectors.toList()); System.out.println(distinctList); // 输出:[UserAccount{id=57}, UserAccount{id=56}] ``` 上述代码中,我们首先定义了一个自定义的方法distinctByKey(),该方法接收一个Function类型的参数keyExtractor,用于提取对象的某个属性作为去重的依据。在方法内部,我们使用ConcurrentHashMap来存储已经出现过的属性值,然后使用putIfAbsent()方法判断当前属性值是否已经存在于Map中,如果不存在则将其加入Map中,并返回true,否则返回false。最后,我们使用filter()方法和自定义的方法distinctByKey()来进行去重操作,最终使用collect()方法将去重后的元素收集到一个新的List集合中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值