2017-10-17 102 views
0

我有一个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检查通过结果遍历所有的指标,如果每个对象除了两个日期的属性相匹配检查完成。

这可能是一个更好的方法,这两种优雅和性能?

回答

1

我不知道你是如何产生List<Metric>。但是,如果您可以维护Map<String, Metric>而不是该列表,则可以尝试以下方法。

所以这图的关键是需要比较这些值的组合。 (除了日期属性。)

键:“{metricName} $ {}类型$ .....”

为此,您可以保持与吸气剂度量对象的另一个属性。当你调用getter时,它将返回密钥。

然后在放入地图之前检查键是否存在。如果它存在,则获取该键的存储的度量标准,然后执行日期比较以查找最新的度量标准对象。如果它是最新的,则用新对象替换地图的存储对象。

PS:对两种情况执行时间比较。所以你会找到最好的方法。

+0

感谢。这看起来不错,我使用一个静态嵌套类来构造关键字(在将键构造为字符串时不必处理字段分隔符),但是只是一个字符串就足够了。 – gansvv

0

在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; 
} 
+0

您正在维护TreeSet以避免重复的权利?那么你怎么知道该套件持有最新的公制?基本上,如何区分逻辑中最新的Metric和重复的Metric? – Neero

+0

谢谢。我会解决我的答案。 – Doleron

0

感谢您的答案。我采用了地图方法,因为它不会产生其他种类和副本。

@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; 
}