How make aggregation java8 with specific condition

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'}]

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=82497&siteId=1