Java Stream Issue

I have a problem about writing a java stream by filtering multiple conditions , groupby multiple condition (if possible) and calculating the sum value I store the values as Map<String(pId),List<Person>> Here is my Person class shown below
public class Person{

private String id;
private Statement event; // STATUS1,STATUS2
private LocalDate eventDate;
private Object value;
}
public class Person{

private String id;
private Statement event; // STATUS1,STATUS2
private LocalDate eventDate;
private Object value;
}
Here is the list
ID,Info,Date,Value (All values are stored in Person object defined in the List)

per1, STATUS1, 10-01-2022, 1
per2, STATUS2, 10-01-2022, 2
per3, STATUS3, 10-01-2022, 3
per1 STATUS1, 10-02-2022, 1
per2, STATUS1, 10-03-2022, 1
per3, STATUS2, 10-03-2022, 2
...
...
ID,Info,Date,Value (All values are stored in Person object defined in the List)

per1, STATUS1, 10-01-2022, 1
per2, STATUS2, 10-01-2022, 2
per3, STATUS3, 10-01-2022, 3
per1 STATUS1, 10-02-2022, 1
per2, STATUS1, 10-03-2022, 1
per3, STATUS2, 10-03-2022, 2
...
...
What I want to do is to get this result.
Month | Total Sum | Person Count
1 6 3
2 1 1
3 3 2
Month | Total Sum | Person Count
1 6 3
2 1 1
3 3 2
Here is group dto shown below
public class GroupDto {
private int month;
}
public class GroupDto {
private int month;
}
Here is my dto shown below.
public class DTO {
private int month;
private int totalSum;
private int totalPersons;
}
public class DTO {
private int month;
private int totalSum;
private int totalPersons;
}
Here is the code snippet but I cannot complete it.
List<DTO > result = persons .values().stream()
.flatMap(List::stream)
.filter(person -> person .getInfo() == Value.STATUS1|| person .getInfo() == Value.STATUS2 || person .getInfo() == Value.STATUS3)
.collect(Collectors.groupingBy(
p -> new GroupDto(p.getEventDate().getMonthValue()) // CANNOT COMPLETE
))
.entrySet().stream()
.map(entry -> new DTO(entry.getKey().getMonth(), ....) // CANNOT COMPLETE
.sorted(Comparator.comparing(DTO::getMonth))
.toList();
List<DTO > result = persons .values().stream()
.flatMap(List::stream)
.filter(person -> person .getInfo() == Value.STATUS1|| person .getInfo() == Value.STATUS2 || person .getInfo() == Value.STATUS3)
.collect(Collectors.groupingBy(
p -> new GroupDto(p.getEventDate().getMonthValue()) // CANNOT COMPLETE
))
.entrySet().stream()
.map(entry -> new DTO(entry.getKey().getMonth(), ....) // CANNOT COMPLETE
.sorted(Comparator.comparing(DTO::getMonth))
.toList();
How can I do that?
10 Replies
JavaBot
JavaBot•3y ago
Hey, @direct_x_34! Please remember to /close this post once your question has been answered!
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
direct_x_34
direct_x_34OP•3y ago
Value should be Object not int. I just tested it but it didn't work.
per1, STATUS1, 10-01-2022, 1
per2, STATUS2, 10-01-2022, 2
per3, STATUS3, 10-01-2022, 3
per1, STATUS1, 10-01-2022, 1
per1 STATUS1, 10-02-2022, 1
per2, STATUS1, 10-03-2022, 1
per3, STATUS2, 10-03-2022, 2
per1, STATUS1, 10-01-2022, 1
per2, STATUS2, 10-01-2022, 2
per3, STATUS3, 10-01-2022, 3
per1, STATUS1, 10-01-2022, 1
per1 STATUS1, 10-02-2022, 1
per2, STATUS1, 10-03-2022, 1
per3, STATUS2, 10-03-2022, 2
public class DTO {
private int month;
private BigDecimal totalSum;
private int totalPersons;
}
public class DTO {
private int month;
private BigDecimal totalSum;
private int totalPersons;
}
List<Dto> group = employees.values().stream()
.flatMap(List::stream)
.filter(emp -> emp.getEvent() == Value.STATUS1 || emp.getEvent() == Value.STATUS2
|| emp.getEvent() == Value.STATUS3 )
.map(emp -> new Dto(emp.getEventDate().getMonthValue(), new BigDecimal(emp.getValue().toString()), 1)) // BigDecimal.ONE = BigDecimal.valueOf(1)
.collect(Collectors.toList());

List<Dto> result = new ArrayList<>(group.stream()
.collect(Collectors.toMap(
dto -> Arrays.asList(dto.getMonth()), Function.identity(), Dto::aggregate))
.values()).stream().sorted(Comparator.comparing(Dto::getMonth))
.collect(Collectors.toList());

// Defined in Dto class
public static Dto aggregate(Dtoinitial, Dto next) {
initial.setTotalSalary(initial.getTotalSalary().add(next.getTotalSalary()));
initial.setTotalEmployees(initial.getTotalEmployees() + next.getTotalEmployees());
return initial;
}

result.forEach(System.out::println);

Here is the same result

Dto{month=1, totalSalary=7, totalPersons=4}
Dto{month=2, totalSalary=1, totalPersons=1}
Dto{month=3, totalSalary=3, totalPersons=2}

Normally, total persons in month 1 is 3 but it counts 4 with respect to status.
List<Dto> group = employees.values().stream()
.flatMap(List::stream)
.filter(emp -> emp.getEvent() == Value.STATUS1 || emp.getEvent() == Value.STATUS2
|| emp.getEvent() == Value.STATUS3 )
.map(emp -> new Dto(emp.getEventDate().getMonthValue(), new BigDecimal(emp.getValue().toString()), 1)) // BigDecimal.ONE = BigDecimal.valueOf(1)
.collect(Collectors.toList());

List<Dto> result = new ArrayList<>(group.stream()
.collect(Collectors.toMap(
dto -> Arrays.asList(dto.getMonth()), Function.identity(), Dto::aggregate))
.values()).stream().sorted(Comparator.comparing(Dto::getMonth))
.collect(Collectors.toList());

// Defined in Dto class
public static Dto aggregate(Dtoinitial, Dto next) {
initial.setTotalSalary(initial.getTotalSalary().add(next.getTotalSalary()));
initial.setTotalEmployees(initial.getTotalEmployees() + next.getTotalEmployees());
return initial;
}

result.forEach(System.out::println);

Here is the same result

Dto{month=1, totalSalary=7, totalPersons=4}
Dto{month=2, totalSalary=1, totalPersons=1}
Dto{month=3, totalSalary=3, totalPersons=2}

Normally, total persons in month 1 is 3 but it counts 4 with respect to status.
How can I fix it? @Spoon
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
direct_x_34
direct_x_34OP•3y ago
I'm getting incorrect count totalPerson because I'm not taking into account person id. I'm treating each DTO in your code as representing a distinct Person which is not true How can I do that? I think the way to solve the issue.Firstly I can create an intermediate object maintaining a set of person id to accumulate the Person instances. And then turn these objects into DTO by using the size of their Sets of ids as the person count. However, I have no idea how to implement it for my issue which I mentioned before.
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
direct_x_34
direct_x_34OP•3y ago
Here is the example list shown below.
ID,Info,Date,Value (All values are stored in Person object defined in the List)

per1, STATUS1, 10-01-2022, 1
per2, STATUS2, 10-01-2022, 2
per3, STATUS3, 10-01-2022, 3
per1, STATUS1, 10-01-2022, 1
per1 STATUS1, 10-02-2022, 1
per2, STATUS1, 10-03-2022, 1
per3, STATUS2, 10-03-2022, 2
...
...
ID,Info,Date,Value (All values are stored in Person object defined in the List)

per1, STATUS1, 10-01-2022, 1
per2, STATUS2, 10-01-2022, 2
per3, STATUS3, 10-01-2022, 3
per1, STATUS1, 10-01-2022, 1
per1 STATUS1, 10-02-2022, 1
per2, STATUS1, 10-03-2022, 1
per3, STATUS2, 10-03-2022, 2
...
...
What I want to get this result as you can see below.
Month | Total Sum | Person Count
1 7 3
2 1 1
3 3 2
Month | Total Sum | Person Count
1 7 3
2 1 1
3 3 2
I got this result as you can see. @Spoon I cannot get the right values of total persons @Andrew Hi, I think you can help me fix my issue regarding java stream. I cannot get the right values of total persons
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
direct_x_34
direct_x_34OP•3y ago
@Andrew Who can I ask it?
JavaBot
JavaBot•3y ago
💤 Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived. If your question was not answered yet, feel free to re-open this post or create a new one.
Want results from more Discord servers?
Add your server