为了账号安全,请及时绑定邮箱和手机立即绑定

Java 8按属性区分

Java 8按属性区分

米琪卡哇伊 2019-06-21 14:49:03
Java 8按属性区分在Java 8中,如何使用Stream通过检查每个对象的属性的区别性来实现API?例如,我有一个列表Person对象,并且我想删除同名的人,persons.stream().distinct();将使用默认的等式检查。Person所以我需要类似的东西,persons.stream().distinct(p -> p.getName());不幸的是distinct()方法没有这样的重载。中不修改相等检查。Person类可以简洁地做到这一点吗?
查看完整描述

3 回答

?
largeQ

TA贡献2039条经验 获得超7个赞

考虑distinct成为状态过滤器..下面是一个函数,它返回一个谓词,该谓词维护以前看到的内容的状态,并返回给定元素是否第一次被看到:

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> seen.add(keyExtractor.apply(t));}

然后你可以写:

persons.stream().filter(distinctByKey(Person::getName))

注意,如果流被排序并行运行,这将保留任意元素中的元素,而不是第一个副本中的distinct()的确如此。

(这与我的回答关于这个问题:JavaLambdaStream对任意键的区分()?)


查看完整回答
反对 回复 2019-06-21
?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

另一种办法是把这些人放在地图上,用名字作为钥匙:

persons.collect(toMap(Person::getName, p -> p, (p, q) -> p)).values();

注意,在重复姓名的情况下,被保留的人将是第一个被授权的人。


查看完整回答
反对 回复 2019-06-21
?
翻翻过去那场雪

TA贡献2065条经验 获得超14个赞

您可以将Person对象包装到另一个类中,该类只比较人员的名称。之后,您将打开包装好的对象以再次获得Person流。流操作可能如下所示:

persons.stream()
    .map(Wrapper::new)
    .distinct()
    .map(Wrapper::unwrap)
    ...;

全班Wrapper如下所示:

class Wrapper {
    private final Person person;
    public Wrapper(Person person) {
        this.person = person;
    }
    public Person unwrap() {
        return person;
    }
    public boolean equals(Object other) {
        if (other instanceof Wrapper) {
            return ((Wrapper) other).person.getName().equals(person.getName());
        } else {
            return false;
        }
    }
    public int hashCode() {
        return person.getName().hashCode();
    }}


查看完整回答
反对 回复 2019-06-21
  • 3 回答
  • 0 关注
  • 388 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信