I have 2 classes:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FirstDTO {
private Long id;
@Builder.Default
private List<SecondDTO> secondDTOs = Lists.newArrayList();
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SecondDTO {
private Long id;
private String code;
}
My controller returns List of FirstDTO:
ResponseEntity<List<FirstDTO>> add(List<MySampleDTO> dtoList);
The controller can get a List what will produces multiple FirstDTO as response. In FirstDTO I include the id
of it and a List<SecondDTO>
. The problem is that it can happen that the data will be redundant:
[
{
"id": 1,
"secondDTO": [
{
"id": 200,
"code": "MY_200_TEST_CODE"
}
]
},
{
"id": 1,
"secondDTO": [
{
"id": 200,
"code": "MY_200_TEST_CODE"
},
{
"id": 300,
"code": "MY_300_TEST_CODE"
}
]
}
]
As you can see the second object of the json would be enough as response because it contains the first object. So I would like to use java 8 streams (or any other method) that will transform the list I showed earlier, to this:
[
{
"id": 1,
"secondDTO": [
{
"id": 200,
"code": "MY_200_TEST_CODE"
},
{
"id": 300,
"code": "MY_300_TEST_CODE"
}
]
}
]
So basically I need a method that groups FirstDTOs based on it's id
and then save only FirstDTO with given id
that has the longest list of SecondDTOs
Thanks in advance.
CodePudding user response:
This is what you're looking for
Map<Long, Optional<Class1>> mapFiltered = list.stream()
.collect(Collectors.groupingBy(x -> x.getId(),
Collectors.maxBy(Comparator.comparingInt(x -> x.getList().size()))));
Here, I've also added a simple main test
public class Main {
public static void main(String[] args) {
ArrayList<Class2> test1List = new ArrayList<>();
test1List.add(new Class2(1000L));
test1List.add(new Class2(2000L));
test1List.add(new Class2(3000L));
Class1 test1 = new Class1(100L, test1List);
ArrayList<Class2> test2List = new ArrayList<>();
test2List.add(new Class2(1000L));
Class1 test2 = new Class1(100L, test2List);
ArrayList<Class2> test3List = new ArrayList<>();
test3List.add(new Class2(10000L));
test3List.add(new Class2(20000L));
test3List.add(new Class2(30000L));
Class1 test3 = new Class1(200L, test3List);
ArrayList<Class2> test4List = new ArrayList<>();
test4List.add(new Class2(10000L));
test4List.add(new Class2(20000L));
Class1 test4 = new Class1(200L, test4List);
ArrayList<Class2> test5List = new ArrayList<>();
test5List.add(new Class2(10000L));
Class1 test5 = new Class1(200L, test5List);
Class1 test6 = new Class1(300L, new ArrayList<>());
List<Class1> list = new ArrayList<>();
list.add(test1);
list.add(test2);
list.add(test3);
list.add(test4);
list.add(test5);
list.add(test6);
for (Class1 c1 : list) {
System.out.println(c1);
}
Map<Long, Optional<Class1>> mapFiltered = list.stream()
.collect(Collectors.groupingBy(x -> x.getId(),
Collectors.maxBy(Comparator.comparingInt(x -> x.getList().size()))));
System.out.println("---------------- RESULT ----------------");
for (Long id : mapFiltered.keySet()) {
if (mapFiltered.get(id).isPresent()) {
System.out.println(mapFiltered.get(id).get());
}
}
}
}
class Class1 {
private Long id;
private List<Class2> list;
public Class1(Long id, List<Class2> list) {
this.id = id;
this.list = list;
if (this.list == null) {
this.list = new ArrayList<>();
}
}
public Long getId() {
return id;
}
public List<Class2> getList() {
return list;
}
@Override
public String toString() {
StringBuilder str = new StringBuilder();
str.append(id);
str.append(" => [");
for (Class2 c2 : list) {
str.append(c2.toString());
str.append(" ");
}
if (list.size() > 0) {
str.deleteCharAt(str.length() - 1);
}
str.append("]");
return str.toString();
}
}
class Class2 {
private Long id;
public Class2(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
@Override
public String toString() {
return String.valueOf(id);
}
}