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



我有一个对象流(测量(,包括一个私有的sensorID属性。我想过滤这个流,所以我只有不同传感器ID的测量。据我所知;独特的";方法会对对象执行此操作,但不会对对象的特定属性执行此操作。此代码通过使用Collections:来完成任务

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 Methode。

@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方法

@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分组的不同测量的列表。

最新更新