I want to group different objects types based on same content of fields incomeCode
, endDate
and codeRef
on both classes. I omitted many fields on both classes that make each object unique for simplicity.
public class Exon {
private Long id;
private IncomeCode incomeCode;
private LocalDate endDate;
String codeRef;
}
public class Sup {
private Long id;
private IncomeCode incomeCode;
private LocalDate startDate;
private LocalDate endDate;
String codeRef;
}
Exons example:
id | incomdeCode | endDate | codeRef |
---|---|---|---|
1 | 45 | 01/01/2021 | 4 |
2 | 21 | 01/01/2022 | 5 |
3 | 33 | 01/01/2023 | 2 |
4 | 45 | 01/01/2021 | 4 |
Sups example:
id | incomdeCode | endDate | codeRef |
---|---|---|---|
1 | 45 | 01/01/2021 | 4 |
2 | 21 | 01/01/2022 | 5 |
3 | 33 | 01/01/2023 | 2 |
Desired result : List : { {exon1, exon4, sup1}, {exon2, sup2}, {exon3, sup3} }
My attempt :
public Map<Object, List<Exon>> getExons() {
Map<Object, List<Exon>> result = getSource1.stream()
.flatMap(lp -> lp.getExons().stream())
.collect(Collectors.groupingBy(e -> new KeyGroup(e.getIncomeCode(), e.getEndDate(), e.getCodeRef())
));
return result;
}
public Map<Object, List<Sup>> getSups() {
Map<Object, List<Sup>> result = getSource2.stream()
.flatMap(lp -> lp.getSups().stream())
.collect(Collectors.groupingBy(e -> new
KeyGroup(e.getIncomeCode(), e.getEndDate(), e.getCodeRef())));
return result;
}
Map<Object, List<Exon>> exonList = getExons();
Map<Object, List<Sup>> supList = getSups();
Map<Object, List<List<?>>> objMap = new HashMap<>();
exonList.forEach((k, v) -> {
if (objMap.containsKey(o)) {
objMap.get(o).add(v);
} else {
List<List<?>> eList = new ArrayList<>();
eList.add(v);
objMap.put(o, eList);
}
});
supList.forEach((o, v) -> {
if (objMap.containsKey(o)) {
objMap.get(o).add(v);
} else {
List<List<?>> eList = new ArrayList<>();
eList.add(v);
objMap.put(o, eList);
}
});
CodePudding user response:
As it has been pointed out in the comments, if you need to mix different type of objects your resulting List
will be a List<List<Object>>
.
To group them by like that, you could use the collect()
terminal operation in conjunction with a Collectors.groupingBy()
which could group the objects with a key built ad-hoc with the desired fields (incomeCode
, endDate
and codeRef
). After building the Map
, you could retrieve its values, i.e. a Collection
with the lists of objects, and give them in input to the Conversion Constructor of a List
implementation.
List<List<Object>> listRes = new ArrayList<>(Stream.concat(listExon.stream(), listSup.stream())
.collect(Collectors.groupingBy(obj -> {
if (obj instanceof Exon) {
Exon exon = (Exon) obj;
return String.format("%s-%s-%s", exon.getIncomeCode(), exon.getEndDate(), exon.getCodeRef());
}
Sup sup = (Sup) obj;
return String.format("%s-%s-%s", sup.getIncomeCode(), sup.getEndDate(), sup.getCodeRef());
})).values());
Here there is also a link to test the code above:
CodePudding user response:
How about something like this. You can make another subclass and group your different class item on this map
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Solution
{
public void sol()
{
List<Exon> exons = new ArrayList<>();
List<Sup> sups = new ArrayList<>();
List<ClassWithNeededFields> list1 = exons.stream()
.map(item -> new ClassWithNeededFields(item.getIncomeCode(), "neededField"))
.collect(Collectors.toList());
List<ClassWithNeededFields> list2 = sups.stream()
.map(item -> new ClassWithNeededFields(item.getIncomeCode(), "neededField"))
.collect(Collectors.toList());
list1.addAll(list2);
Map<IncomeCode, List<ClassWithNeededFields>> map2 = list1.stream()
.map(item -> new ClassWithNeededFields(item.getIncomeCode(), "neededField"))
.collect(Collectors.groupingBy(ClassWithNeededFields::getIncomeCode));
}
public class Exon
{
private IncomeCode incomeCode;
public IncomeCode getIncomeCode()
{
return null;
}
}
public class Sup
{
private IncomeCode incomeCode;
public IncomeCode getIncomeCode()
{
return null;
}
}
public class IncomeCode
{
}
public class ClassWithNeededFields
{
private IncomeCode incomeCode;
private String otherField;
// The other needed fields. ...
public ClassWithNeededFields(IncomeCode incomeCode, String otherField /* The other needed fields. ... */)
{
}
public IncomeCode getIncomeCode()
{
return this.incomeCode;
}
}
}