我有两个自定义对象列表都是 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) 并且我使用了这里的一些逻辑。
答案 0 :(得分:0)
分组和聚合:
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, S0, 1766963016
E0, S2, 2106321704
E0, S1, 1752799219
E1, S2, 2123681998
E1, S1, 1522756354
E0, S0, 1578552430
E2, S2, 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, S1, null
E1, S0, null
E2, S0, null
E0, S2, 2123867824
E1, S2, null
E0, S1, 13858484
E2, S2, null
E1, S1, 1347419477
E0, S0, -135848900