删除基于几个对象属性从列表
我有一个List集合,其中每个指标包含一些特性,如重复:metricName,命名空间,车队,类型,组件,firstSeenTime,lastSeenTime等有此列表中重复这样的除了firstSeenTime和lastSeenTime之外,所有属性都是相同的。我正在寻找一种优雅的方式来过滤这个列表,并且只有在存在这样的重复时才返回带有最近lastSeenTime的度量标准。删除基于几个对象属性从列表
东西比这更好:
private List<Metric> processResults(List<Metric metrics) {
List<Metric> results = new ArrayList<>();
for (Metric incomingMetric: metrics) {
// We need to implement "contains" below so that only properties
// other than the two dates are checked.
if (results.contains(incomingMetric) {
int index = results.indexOf(incomingMetric);
Metric existing = results.get(index);
if (incomingMetric.getLastSeen().after(existing.getLastSeen())) {
results.set(index, metricName);
} else {
// do nothing, metric in results is already the latest
}
} else {
// add incomingMetric to results for the first time
results.add(incomingMetric);
}
}
return results;
}
的results.contains检查通过结果遍历所有的指标,如果每个对象除了两个日期的属性相匹配检查完成。
这可能是一个更好的方法,这两种优雅和性能?
我不知道你是如何产生List<Metric>
。但是,如果您可以维护Map<String, Metric>
而不是该列表,则可以尝试以下方法。
所以这图的关键是需要比较这些值的组合。 (除了日期属性。)
键:“{metricName} $ {}类型$ .....”
为此,您可以保持与吸气剂度量对象的另一个属性。当你调用getter时,它将返回密钥。
然后在放入地图之前检查键是否存在。如果它存在,则获取该键的存储的度量标准,然后执行日期比较以查找最新的度量标准对象。如果它是最新的,则用新对象替换地图的存储对象。
PS:对两种情况执行时间比较。所以你会找到最好的方法。
在java中最优雅的方式来比较的东西是Comparator接口。
public List<Metric> removeDuplicates(List<Metric> metrics) {
List<Metric> copy = new ArrayList<>(metrics);
//first sort the metrics list from most recent to older
Collections.sort(copy, new SortComparator());
Set<Metric> set = new TreeSet<Metric>(new Comparator<Metric>() {
@Override
public int compare(Metric o1, Metric o2) {
int result = 0;
// compare the two metrics given your rules
return result;
}
});
for(Metric metric : copy) {
set.add(metric);
}
List<Metric> result = Arrays.asList(set.toArray());
return result;
}
class SortComparator implements Comparator<Metric> {
@Override
public int compare(Metric o1, Metric o2) {
int result = 0;
if(o2.getLastSeenTime() != null && o1.getLastSeenTime() != null) {
result = o2.getLastSeenTime().compareTo(o1.getLastSeenTime());
}
return result;
}
}
强这种方法的是,你可以写一个系列的比较器,并提供一个Factory在运行时选择比较您的指标,并删除或不实例最好的办法:你应该使用类似删除重复作为运行条件中的副本:
public void removeDuplicates(List<Metric> metrics, Comparator<Metric> comparator) {
List<Metric> copy = new ArrayList<>(metrics);
Collections.sort(copy, new SortComparator());
Set<Metric> set = new TreeSet<Metric>(comparator);
for(Metric metric : copy) {
set.add(metric);
}
List<Object> result = Arrays.asList(set.toArray());
return result;
}
感谢您的答案。我采用了地图方法,因为它不会产生其他种类和副本。
@VisibleForTesting
Set<Metric> removeDuplicates(List<Metric> metrics) {
Map<RawMetric, Metric> metricsMap = new HashMap<>();
for (Metric metric : metrics) {
RawMetric rawMetric = RawMetric.builder()
.metricName(metric.getName())
.metricType(metricName.getMetricType())
... // and more
.build();
// pick the latest updated metric (based on lastSeen date)
BiFunction<RawMetric, Metric, Metric> biFunction =
(k, v) -> Metric.builder()
.name(k.getMetricName())
.metricType(k.getMetricType())
... // and more
.lastSeen(v.getLastSeen().after(
metricName.getLastSeen()) ? v.getLastSeen() :
metricName.getLastSeen())
.firstSeen(v.getFirstSeen())
.build();
metricsMap.putIfAbsent(rawMetric, metric);
metricsMap.computeIfPresent(rawMetric, biFunction);
}
return ImmutableSet.copyOf(metricsMap.values());
}
@Value
@Builder
static class RawMetricName {
private String metricName;
private String metricType;
private String ad;
private String project;
private String fleet;
private String host;
private int granularity;
}
感谢。这看起来不错,我使用一个静态嵌套类来构造关键字(在将键构造为字符串时不必处理字段分隔符),但是只是一个字符串就足够了。 – gansvv