将元素列表的列表转换为映射&lt; K,列表<v>&gt;

时间:2018-02-14 07:36:15

标签: java list java-8 java-stream

我有以下结构。

Request {
    List<Param> paramList;
    Date startDate;
    Date endDate;
}

Param {
    String paramId;
    List<DataParam> dataParams; 
}

DataParam {
    String dataId;
    List<String> values;
}

CustomRequest {
    List<NewDataParam> newDataParam;
    Date startDate;
    Date endDate;
}

NewDataParam {
 String paramId;
 String dataId;
----
}

使用paramList迭代请求,我想制作paramId的地图并生成Map<String, List<CustomRequest>>之类的请求。

使用以下代码,我得到Map<String, List<List<CustomRequest>>>。有人可以建议如何获得Map<String, List<CustomRequest>>

request.paramList().stream()
    .collect(Collectors.groupingBy(Param::getParamId, 
        Collectors.mapping(i -> i.dataParams().stream()
           .map(r -> customBuildMethod(i.dataParamId(), r, request)).collect(Collectors.toList()), Collectors.toList())));

private CustomRequest customBuildMethod(String paramId ...) {
    CustomRequest customRequest = new CustomRequest();
    //mapping
    return customRequest;
}

2 个答案:

答案 0 :(得分:5)

如果您可以使用Java 9,则可以使用Collectors.flatMapping实现目标:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>slideToggle demo</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>

<body>

  <button>Toggle</button>
  <p>
    This is the paragraph to end all paragraphs. You should feel <em>lucky</em> to have seen such a paragraph in your life. Congratulations!
  </p>

</body>

</html>

在Java 8中,您可以执行以下操作:

request.paramList()
       .stream()
       .collect(Collectors.groupingBy(Param::getParamId, 
                                      Collectors.flatMapping(i -> i.dataParams().stream().map(r -> customBuildMethod(i.dataParamId(), r, request))), 
                                                            Collectors.toList())));

答案 1 :(得分:4)

而不是Collectors.mapping()您可以使用Collectors.collectingAndThen()在终结器功能中的哪个位置,您可以使用数据参数列表来执行flatMap。这样的事情:

Map<String, List<CustomRequest>> map = params.stream()
        .collect(Collectors.groupingBy(
                Param::getParamId, Collectors.collectingAndThen(Collectors.toList(), it -> it.stream()
                        .flatMap(i -> i.getDataParams().stream())
                        .map(r -> new CustomRequest(Arrays.asList(new NewDataParam()), new Date(), new Date()))
                        .collect(Collectors.toList())
                ))
        );

System.out.println(map);

我用于测试的完整示例:

import java.util.*;
import java.util.stream.Collectors;

public class ListOfListsToMapOfStringAndListExample {

    public static void main(String[] args) {

        final List<Param> params = Arrays.asList(
                new Param("1", Arrays.asList(new DataParam("2", Arrays.asList("a", "b")))),
                new Param("3", Arrays.asList(new DataParam("4", Arrays.asList("c", "d")))),
                new Param("5", Arrays.asList(new DataParam("6", Arrays.asList("e", "f"))))
        );

        Map<String, List<CustomRequest>> map = params.stream()
                .collect(Collectors.groupingBy(
                        Param::getParamId, Collectors.collectingAndThen(Collectors.toList(), it -> it.stream()
                                .flatMap(i -> i.getDataParams().stream())
                                .map(r -> new CustomRequest(Arrays.asList(new NewDataParam()), new Date(), new Date()))
                                .collect(Collectors.toList())
                        ))
                );

        System.out.println(map);
    }


    static class Request {
        List<Param> paramList;
        Date startDate;
        Date endDate;

        public Request(List<Param> paramList, Date startDate, Date endDate) {
            this.paramList = paramList;
            this.startDate = startDate;
            this.endDate = endDate;
        }
    }

    static class Param {
        String paramId;
        List<DataParam> dataParams;

        public Param(String paramId, List<DataParam> dataParams) {
            this.paramId = paramId;
            this.dataParams = dataParams;
        }

        public String getParamId() {
            return paramId;
        }

        public List<DataParam> getDataParams() {
            return dataParams;
        }
    }

    static class DataParam {
        String dataId;
        List<String> values;

        public DataParam(String dataId, List<String> values) {
            this.dataId = dataId;
            this.values = values;
        }

        public String getDataId() {
            return dataId;
        }

        public List<String> getValues() {
            return values;
        }
    }

    static class CustomRequest {
        List<NewDataParam> newDataParam;
        Date startDate;
        Date endDate;

        public CustomRequest(List<NewDataParam> newDataParam, Date startDate, Date endDate) {
            this.newDataParam = newDataParam;
            this.startDate = startDate;
            this.endDate = endDate;
        }

        public List<NewDataParam> getNewDataParam() {
            return newDataParam;
        }

        public Date getStartDate() {
            return startDate;
        }

        public Date getEndDate() {
            return endDate;
        }

        @Override
        public String toString() {
            return "CustomRequest{" +
                    "newDataParam=" + newDataParam +
                    ", startDate=" + startDate +
                    ", endDate=" + endDate +
                    '}';
        }
    }

    static class NewDataParam {

        @Override
        public String toString() {
            return "NewDataParam{}";
        }
    }
}

输出:

{1=[CustomRequest{newDataParam=[NewDataParam{}], startDate=Wed Feb 14 09:03:21 CET 2018, endDate=Wed Feb 14 09:03:21 CET 2018}], 3=[CustomRequest{newDataParam=[NewDataParam{}], startDate=Wed Feb 14 09:03:21 CET 2018, endDate=Wed Feb 14 09:03:21 CET 2018}], 5=[CustomRequest{newDataParam=[NewDataParam{}], startDate=Wed Feb 14 09:03:21 CET 2018, endDate=Wed Feb 14 09:03:21 CET 2018}]}

更新

如果将param.paramId传递给customBuildMethod,您甚至可以摆脱flatMap()上的param.dataParams并将您的初始参数对象映射到CustomRequest。类似的东西:

Map<String, List<CustomRequest>> map = params.stream()
        .collect(Collectors.groupingBy(
                Param::getParamId, Collectors.collectingAndThen(Collectors.toList(), it -> it.stream()
                        .map(param -> customBuildMethod(param.paramId, param.dataParams))
                        .collect(Collectors.toList())
                ))
        );

在此示例中,我将param.paramIdparam.dataParams传递给此辅助方法,该方法创建CustomRequest个对象。它可以使用数据参数列表来创建新数据参数对象的新列表:

private static CustomRequest customBuildMethod(String paramId, List<DataParam> params) {
    return new CustomRequest(
            params.stream().map(dataParam -> new NewDataParam()).collect(Collectors.toList()),
            new Date(),
            new Date()
    );
}

或者更直接地根据您的代码:

Map<String, List<CustomRequest>> map = params.stream()
        .collect(Collectors.groupingBy(
                Param::getParamId, Collectors.collectingAndThen(Collectors.toList(), it -> it.stream()
                        .map(param -> customBuildMethod(param.paramId, r, request))
                        .collect(Collectors.toList())
                ))
        );