微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在不使用集合的情况下为可根据属性区分的不同对象过滤 java 流

如何解决在不使用集合的情况下为可根据属性区分的不同对象过滤 java 流

我有一个对象流(测量),包括一个私有的 sensorID 属性。我想过滤这个流,所以我只有不同传感器 ID 的测量。据我了解,“distinct”方法会对对象执行此操作,但不会对对象的特定属性执行此操作。此代码通过使用集合来完成这项工作:

    public static <T> Predicate<T> distinctByKey(Function<? super T,?> keyExtractor) {
        Map<Object,Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t),Boolean.TRUE) == null;
    }

可以这样使用

stream.filter(distinctByKey((Measurement p) -> p.getSensorId()))

对于测量类

public class Measurement {
    private final int sensorId;
    //more stuff
    
    public Measurement(int sensorId) {
        this.sensorId = sensorId;
        //more stuff
    }

    public int getSensorId() {
        return sensorId;
    }
}

我正在寻找的是一种在不使用集合或至少使用不可变数据类型的情况下做同样事情的方法。有什么想法吗?

解决方法

@Deadpool 在他的评论中建议的解决方案很简单。 只需覆盖对象的 equals 方法即可。

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Measurement other = (Measurement) obj;
        return Objects.equals(sensorID,other.sensorID);
    }

但你也必须像这样覆盖 hashCode Methode

    @Override
    public int hashCode() {
        return Objects.hash(sensorID);
    }

这就是为什么它一开始不起作用。

,

一种可能的替代方法是使用集合来映射,如下例所示:

Collection<Measurement> measurementsById = stream.
        .collect(Collectors.toMap(Measurement::getSensorId,Function.identity(),(measurement1,measurement2) -> measurement1))
        .values()

这样做,您将流元素收集到以 sensorId 为键的映射中。由于映射只能有一个键的值,因此您只需为每个键选择第一个流对象。

然后,给定结果图,通过调用 values() 方法,您可以获得按 sensorId 分组的不同测量值的列表。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。