VitalyT :
I'd like to make aggregation of the following example:
I have a List<CsvEntity> toSort =
of entities as described below:
toSort.add(new CsvEntity(...))..
public class CsvEntity {
String OCCURRENCES, STATUS, MESSAGE, STACK_TRACE;
}
The data:
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
the result should be (as data structure):
OCCURRENCES,STATUS,MESSAGE,STACK_TRACE
3, FAIL, MESSAGE1, STACK1
2, FAIL, MESSAGE2, STACK2
2, PASS, MESSAGE3, STACK3
I tried to use:
Map<String, Integer> group = toSort.stream().collect(
Collectors.groupingBy(
CsvEntity::getSTACK_TRACE,
Collectors.groupingBy(CsvEntity::getMESSAGE),
Collectors.summingInt(s -> Integer.parseInt(s.getOCCURRENCES()))
)
);
but this group returns only the STACK_TRACE not the whole CsvEntity...
Is it possible and what to change in the code?
Ousmane D. :
In addition to my other answer, you could use the groupingBy
collector but first I'd override equals
/hashcode
in the CsvEntity
class as follows:
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) { ... }
...
...
...
}
Then the stream pipeline:
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());
This again yields the following result:
[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'}]