问题描述
我有两个自定义对象列表都是 List<LogEntry>
。其中一个属性是typeOfException
、date
和stackTrace
,另一个只包含typeOfException
和stackTrace
。我想要做的是根据他们的 typeOfException
和 stackTrace
删除重复的日志条目。我定义唯一堆栈跟踪的方式是,如果第一个“at line”相同,即
[25/05/21 10:28:41:481 BST] - IllegalStateException some text here
at com.google MyClass(Line 50)
[28/05/21 10:28:41:481 BST] - IllegalStateException some more text here
at com.google MyClass(Line 50)
被视为重复但
[25/05/21 10:28:41:481 BST] - IllegalStateException some text here
at com.google MyClass(Line 50)
[28/05/21 10:28:41:481 BST] - IllegalStateException some more text here
at com.google MyClass(Line 50000)
将被视为独一无二的。
我有一个名为 List<LogEntry>
的 logEntries
,其中包含 date,typeOfException
和 stackTrace
。我有另一个名为 List<LogEntry>
的 logEntriestocheckForDupes
,它是一个 LogEntry
对象,但这次只包含 typeOfException
和 stackTrace
行的顶部(注意所有属性是字符串)。
我到目前为止的代码是
HashSet<Object> uniqueStackTraces =new HashSet<>();
logEntryObjectstocheckForDupes.removeIf(c -> !uniqueStackTraces.add(Arrays.asList(c.getTypeOfexception(),c.getStackTrace())));
我认为这是有效的(当我从 887 个异常减少到只有 14 个时,我并不完全相信)。是否有一些方法/逻辑可以找到每个唯一条目的索引。那样的话,我可以只存储一个唯一索引列表并从每个具有唯一索引的对象的 List<LogEntry>
创建一个 logEntries
,而不是创建一个新的 HashSet?
我很困惑,不确定我的代码是否真的按预期工作,因此非常感谢任何建议/输入。问题类似于 (Removing duplicates from the list of objects based on more than one property in java 8) 并且我使用了这里的一些逻辑。
解决方法
分组和聚合:
public static void main(String[] args) {
List<LogEntry> list1 = IntStream.range(0,100).mapToObj(i -> random(true)).collect(toList());
List<LogEntry> list2 = IntStream.range(0,100).mapToObj(i -> random(false)).collect(toList());
// join removing dups,get the last date
Collection<LogEntry> result = Stream.concat(list1.stream(),list2.stream())
.collect(toMap(
// the key (better use a Tuple<> type instead concatenate strings)
x -> x.typeOfException + ":" + x.stackTrace,x -> x,// the max non null date
(a,b) -> a.date == null ? b : b.date == null ? a : a.date < b.date ? b : a))
.values();
result.forEach(e -> System.out.printf("%s,%s,%d%n",e.typeOfException,e.stackTrace,e.date));
}
@AllArgsConstructor
static class LogEntry {
public String typeOfException;
public String stackTrace;
public Integer date;
public static LogEntry random(boolean withDates) {
ThreadLocalRandom rnd = ThreadLocalRandom.current();
return new LogEntry("E" + rnd.nextInt(3),"S" + rnd.nextInt(3),withDates ? rnd.nextInt() : null);
}
}
带输出
E2,S1,1974693605
E1,S0,2085047733
E2,1766963016
E0,S2,2106321704
E0,1752799219
E1,2123681998
E1,1522756354
E0,1578552430
E2,1969494110
如果我们有几个日期为空的出现
List<LogEntry> list1 = IntStream.range(0,4).mapToObj(i -> random(true)).collect(toList());
List<LogEntry> list2 = IntStream.range(0,100).mapToObj(i -> random(false)).collect(toList());
带输出
E2,null
E1,null
E2,null
E0,2123867824
E1,13858484
E2,1347419477
E0,-135848900