我有一个对象流(测量(,包括一个私有的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
分组的不同测量的列表。