简体   繁体   中英

Java perform filter and group and perform media with 2 list

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM