如何使用特定条件创建聚合java8
我想对以下示例进行聚合: 我有一个如何使用特定条件创建聚合java8,java,java-8,Java,Java 8,我想对以下示例进行聚合: 我有一个实体列表,如下所述: toSort.add(new CsvEntity(...)).. public class CsvEntity { String OCCURRENCES, STATUS, MESSAGE, STACK_TRACE; } 数据: OCCURRENCES, STATUS,MESSAGE,STACK_TRACE 1, FAIL, MESSAGE1, STACK1 1, PASS,
实体列表,如下所述:
toSort.add(new CsvEntity(...))..
public class CsvEntity {
String OCCURRENCES, STATUS, MESSAGE, STACK_TRACE;
}
数据:
OCCURRENCES, STATUS,MESSAGE,STACK_TRACE
1, FAIL, MESSAGE1, STACK1
1, PASS, MESSAGE1, STACK1
1, FAIL, MESSAGE1, STACK1
1, FAIL, MESSAGE2, STACK2 => aggregate MESSAGE & STACK_TRACE)
1, PASS, MESSAGE2, STACK2
1, PASS, MESSAGE3, STACK3
1, PASS, MESSAGE3, STACK3
结果应为(作为数据结构):
我尝试使用:
Map<String, Integer> group = toSort.stream().collect(
Collectors.groupingBy(
CsvEntity::getSTACK_TRACE,
Collectors.groupingBy(CsvEntity::getMESSAGE),
Collectors.summingInt(s -> Integer.parseInt(s.getOCCURRENCES()))
)
);
Map group=toSort.stream().collect(
收集者分组(
CSventy::getSTACK_跟踪,
Collectors.groupingBy(csventy::getMESSAGE),
Collectors.summingit(s->Integer.parseInt(s.getoccurrencess())
)
);
但是这个组只返回堆栈跟踪,而不是整个CSV
是否可能,以及在代码中更改什么?下面是如何分组和聚合数据的示例。希望这有帮助
代码
以下是如何实现上述结果的示例:
这使用了@Boris爬行器的想法,将消息
和堆栈跟踪
属性连接为“分组依据”的值。尽管如此,在这种特定情况下,与其使用groupingBy
收集器,不如使用toMap
收集器
List<CsvEntity> result = new ArrayList<>(source.stream()
.collect(Collectors.toMap(c -> c.getMESSAGE() + c.getSTACK_TRACE(),
v -> new CsvEntity(v.getOCCURRENCES(), v.getSTATUS(), v.getMESSAGE(), v.getSTACK_TRACE()),
(left, right) -> {
left.setOCCURRENCES(Integer.toString(Integer.parseInt(left.getOCCURRENCES())
+ Integer.parseInt(right.getOCCURRENCES())));
return left;
}, LinkedHashMap::new))
.values());
除了我的另一个答案之外,您可以使用groupingBy
收集器,但首先我要覆盖equals
/hashcode
,在CsvEntity
类中,如下所示:
class CsvEntity {
private String OCCURRENCES,STATUS,MESSAGE,STACK_TRACE;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CsvEntity csvEntity = (CsvEntity) o;
return Objects.equals(MESSAGE, csvEntity.MESSAGE) &&
Objects.equals(STACK_TRACE, csvEntity.STACK_TRACE);
}
@Override
public int hashCode() {
return Objects.hash(MESSAGE, STACK_TRACE);
}
public CsvEntity(String OCCURRENCES, String STATUS,
String MESSAGE, String STACK_TRACE) { ... }
...
...
...
}
然后,流管道:
List<CsvEntity> resultSet
= source.stream()
.collect(Collectors.groupingBy(Function.identity(),
LinkedHashMap::new,
Collectors.summingInt(e -> Integer.parseInt(e.getOCCURRENCES()))))
.entrySet()
.stream()
.map(x -> {
CsvEntity c = x.getKey();
return new CsvEntity(Integer.toString(x.getValue()),
c.getSTATUS(), c.getMESSAGE(), c.getSTACK_TRACE());
}).collect(Collectors.toList());
csventy
的成员应该是常量吗?如果没有,请不要用大写字母来命名。当然也有可能。1) 定义正确的分组运算符-您似乎希望按消息和堆栈分组-以便将它们连接在一起进行分组。2) 定义一个适当的下游采集器,它存储消息和堆栈,并有一个计数器,您可以递增计数器,并假定对状态进行逻辑and运算。请您举个例子:)另外,正如@lutzh所说的,使用Java命名约定。变量在camelCase中。为什么public class CsvEntity
而不是public enum CsvEntity
?Hi@VitalyT。。我误解了这个问题。我已将代码更新为stackTrace
Do上的唯一组,我需要通过这些属性实现hashcode/equals吗?公共布尔等于(对象o){if(this==o)返回true;if(o==null | | | getClass()!=o.getClass())返回false;CsvEntity CsvEntity=(CsvEntity)o;返回Objects.equals(getMESSAGE(),CsvEntity.getMESSAGE())和&Objects.equals(getSTACK_TRACE(),CsvEntity.getSTACK_TRACE());}@Override public int hashCode(){return Objects.hash(getMESSAGE(),getSTACK_TRACE());}@VitalyT如果您愿意,您可以,但使用当前的解决方案则不需要。在当前的解决方案中,如果两个对象具有相同的message
和stacktrace
,则它们是相等的,因此c.getMESSAGE()+c.getSTACK_TRACE()
。哇,这样一个优雅的解决方案,很快就会检查出来:),谢谢
List<CsvEntity> result = new ArrayList<>(source.stream()
.collect(Collectors.toMap(c -> c.getMESSAGE() + c.getSTACK_TRACE(),
v -> new CsvEntity(v.getOCCURRENCES(), v.getSTATUS(), v.getMESSAGE(), v.getSTACK_TRACE()),
(left, right) -> {
left.setOCCURRENCES(Integer.toString(Integer.parseInt(left.getOCCURRENCES())
+ Integer.parseInt(right.getOCCURRENCES())));
return left;
}, LinkedHashMap::new))
.values());
[CsvEntity{OCCURRENCES='3', STATUS='FAIL', MESSAGE='MESSAGE1', STACK_TRACE='STACK1'},
CsvEntity{OCCURRENCES='2', STATUS='FAIL', MESSAGE='MESSAGE2', STACK_TRACE='STACK2'},
CsvEntity{OCCURRENCES='2', STATUS='PASS', MESSAGE='MESSAGE3', STACK_TRACE='STACK3'}]
class CsvEntity {
private String OCCURRENCES,STATUS,MESSAGE,STACK_TRACE;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CsvEntity csvEntity = (CsvEntity) o;
return Objects.equals(MESSAGE, csvEntity.MESSAGE) &&
Objects.equals(STACK_TRACE, csvEntity.STACK_TRACE);
}
@Override
public int hashCode() {
return Objects.hash(MESSAGE, STACK_TRACE);
}
public CsvEntity(String OCCURRENCES, String STATUS,
String MESSAGE, String STACK_TRACE) { ... }
...
...
...
}
List<CsvEntity> resultSet
= source.stream()
.collect(Collectors.groupingBy(Function.identity(),
LinkedHashMap::new,
Collectors.summingInt(e -> Integer.parseInt(e.getOCCURRENCES()))))
.entrySet()
.stream()
.map(x -> {
CsvEntity c = x.getKey();
return new CsvEntity(Integer.toString(x.getValue()),
c.getSTATUS(), c.getMESSAGE(), c.getSTACK_TRACE());
}).collect(Collectors.toList());
[CsvEntity{OCCURRENCES='3', STATUS='FAIL', MESSAGE='MESSAGE1', STACK_TRACE='STACK1'},
CsvEntity{OCCURRENCES='2', STATUS='FAIL', MESSAGE='MESSAGE2', STACK_TRACE='STACK2'},
CsvEntity{OCCURRENCES='2', STATUS='PASS', MESSAGE='MESSAGE3', STACK_TRACE='STACK3'}]