I have two lists and I wanted to know how I do the merging between them in Java, but with the grouping of equal items, the media of an attribute and adding an item from a new list according to id
my lists
List<NotasMateria> notasMaterias = repository.findAll(Sort.by("dataNota").descending());
List<Materia> materias = materiaRepository.findAll();
how are you now
list1
{
"idMateria": 9,
"idUsuario": 7,
"materia": "PT",
},
{
"idMateria": 7,
"idUsuario": 7,
"materia": "IN"
},
{
"idMateria": 4,
"idUsuario": 7,
"materia": "YU"
}
List2
{
"idNotaMateria": 5,
"idMateria": 7,
"idUsuario": 7,
"notaMateria": 8.0,
"tipoNota": "winx"
},
{
"idNotaMateria": 2,
"idMateria": 11,
"idUsuario": 7,
"notaMateria": 2.0,
"tipoNota": "winx"
},
{
"idNotaMateria": 4,
"idMateria": 11,
"idUsuario": 7,
"notaMateria": 2.0,
"tipoNota": "Net"
}
Result
{
"idNotaMateria": 2,
"idMateria": 11,
"idUsuario": 7,
"notaMateria": 5.0, (avarege with notaMateria)
"tipoNota": "winx", (gruoping to tipoNota)
"materia": "IN" (add camp condition list2.idMateria =list1.idMateria)
},
{
"idNotaMateria": 4,
"idMateria": 7,
"idUsuario": 7,
"notaMateria": 2.0, (avarege with notaMateria)
"tipoNota":"Net", (gruoping to tipoNota)
"materia": "PT" (add camp condition list2.idMateria =list1.idMateria)
}
Several classes may need to be implemented here to represent intermediate key, value, and final result.
Let's assume that initial objects are described as the following (using Lombok):
@Data
@AllArgsConstructor
class NotasMateria {
private int idUsuario;
private int idMateria;
private int idNotaMateria;
private double notaMateria;
private String tipoNota;
}
@Data
class Materia {
private int idUsuario;
private int idMateria;
private String materia;
}
Then list of Materia
should be converted into a map with the key made of the int
fields:
Map<List<Integer>, String> mapMateria = materias.stream()
.collect(Collectors.toMap(
m -> Arrays.asList(m.getIdUsuario(), m.getIdMateria()),
Materia::getMateria,
(m1, m2) -> m1 // resolve conflicts in case of any duplicates
));
Then the list of Result
merging average notaMateria
and minimal idNotaMateria
may be built using Collectors.collectingAndThen
:
List<Result> result = notasMaterias.stream()
.filter(nm -> mapMateria.containsKey(
Arrays.asList(nm.getIdUsuario(), nm.getIdMateria())
))
.collect(Collectors.groupingBy(
nm -> new KeyResult(nm.getIdUsuario(), nm.getIdMateria(), nm.getTipoNota()),
Collectors.collectingAndThen(
Collectors.toList(),
list -> {
double avgNotaMateria = list.stream()
.mapToDouble(NotasMateria::getNotaMateria)
.average().getAsDouble();
int minIdNotaMateria = list.stream()
.mapToInt(NotasMateria::getIdNotaMateria).min().getAsInt();
return new ValueResult(avgNotaMateria, minIdNotaMateria);
}
)
)) // intermediate Map<KeyResult, ValueResult>
.entrySet().stream()
.map(e -> new Result(
e.getKey(),
e.getValue(),
mapMateria.get(Arrays.asList(
e.getKey().getIdUsuario(),
e.getKey().getIdMateria()
))
))
.collect(Collectors.toList());
where the intermediate DTOs may look as follows:
@Data
@AllArgsConstructor
class KeyResult {
private int idUsuario;
private int idMateria;
private String tipoNota;
}
@Data
@AllArgsConstructor
class ValueResult {
private double avgNotaMateria;
private int minIdNotaMateria;
}
@Data
class Result extends NotasMateria {
private String materia;
public Result(KeyResult key, ValueResult value, String materia) {
super(
key.getIdUsuario(), key.getIdMateria(),
value.getAvgNotaMateria(), value.getMinIdNotaMateria(),
key.getTipoNota()
);
this.materia = materia;
}
}
Note : this code has not been compiled and tested, so it may contain typos/minor errors.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.