Как преобразовать список в объект на основе некоторых условий с помощью collect?

#java-8 #java-stream #collectors

Вопрос:

Я хочу знать, есть ли способ в методе .toCollect потоков преобразовать список в объект в соответствии с некоторыми условиями. Вот мой код. Класс запроса:

 @Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ERequest {
    private String id;
    private String cId;
    private int pid;
    private String ind;
}
 

Класс ответов:

 @Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ExpectedResponse {
    private String data1;
    private String data2;
    private String data3;
    
}
 

Метод

 public ExpectedResponse getPref(List<ERequest> request) {
        ExpectedResponse expectedResponse = ExpectedResponse.builder().build();

        Predicate<ERequest> isE = p -> (p.getCId().equals("ab")) amp;amp; (p.getPid() == 1);
        Predicate<ERequest> isS = p -> (p.getCId().equals("cd")) amp;amp; (p.getPid() == 2);
        Predicate<ERequest> isP = p -> (p.getCId().equals("ef")) amp;amp; (p.getPid() == 4);

        List<ERequest> res = request.stream()
                .filter(isE.or(isS).or(isP))
                .collect(Collectors.toList());

        for (ERequest r : res) {
            if (r.getCId().equals("ab")) {
                expectedResponse.setData1(r.getInd());
            }
            if (r.getCId().equals("cd")) {
                expectedResponse.setData2(r.getInd());
            }
            if (r.getCId().equals("ef")) {
                expectedResponse.setData3(r.getInd());
            }
        }
        return expectedResponse;
    }
 

Я получаю действительный/требуемый список в res, но мне все равно нужно использовать цикл for, чтобы просмотреть этот список и извлечь данные в соответствии с несколькими условиями, а затем заполнить ожидаемый ответ. Как я могу напрямую преобразовать запрос в ожидаемый ответ ?

Комментарии:

1. public ExpectedResponse getPref(List<ERequest> request) { ExpectedResponse expectedResponse = ExpectedResponse.builder().build(); for(ERequest r: request) { switch(r.getPid()) { case 1: if (r.getCId().equals("ab")) expectedResponse.setData1(r.getInd()); break; case 2: if (r.getCId().equals("cd")) expectedResponse.setData2(r.getInd()); break; case 4: if (r.getCId().equals("ef")) expectedResponse.setData3(r.getInd()); } } return expectedResponse; }

Ответ №1:

Вы можете выполнять все операции во время первой итерации, используя фильтр для фильтрации записей и уменьшения, это просто подход с использованием reduce метода, но я не проверял, так как у меня нет образцов данных

  ExpectedResponse expectedResponse = requests.stream().filter(req->(req.getCId().equals("ab")) amp;amp; (req.getPid() == 1) ||
            (req.getCId().equals("cd")) amp;amp; (req.getPid() == 2) ||
            (req.getCId().equals("ef")) amp;amp; (req.getPid() == 4))
            .reduce(ExpectedResponse.builder().build(),(response, request)->{
                if (request.getCId().equals("ab")) {
                    response.setData1(request.getInd());
                }
                if (request.getCId().equals("cd")) {
                    response.setData2(request.getInd());
                }
                if (request.getCId().equals("ef")) {
                    response.setData3(request.getInd());
                }
                return response;
            },(finalRes,finalReq)->finalRes);