带有2个列表的Java 8 Stream

时间:2017-01-13 12:10:03

标签: list java-8 java-stream

我想从两个列表构建一个JSON。我需要使用两个列表中的相应元素来创建一个JSON对象。

我的问题可以通过这样的普通循环来解决:

List<Class1> items = baseManager.findObjectsByNamedQuery(Class1.class, "Class1.findAll", new Object[]{});
 for(int i=0 ; i<items.size();i++){
        List<Class2> items2 = baseManager.findObjectsByNamedQuery(Class2.class, "Class2.findByCreatedBy" ,new Object[] {items.get(i).getCreatedBy()});
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        JsonObjectBuilder jpb  = Json.createObjectBuilder()
                .add("createdBy",items.get(i).getCreatedBy())
                .add("phone",items2.get(0).getPhone())             
        groupsBuilder.add(jpb);
    }

是否可以使用Java 8 Stream API解决它?

3 个答案:

答案 0 :(得分:1)

还有一些事情尚不清楚。就像你坚持创建你没有在任何地方使用的SimpleDateFormat实例一样。或者多次调用getCreatedBy()是否有意义。假设没有必要,以下代码是等效的

baseManager.findObjectsByNamedQuery(Class1.class, "Class1.findAll", new Object[]{})
    .stream()
    .map(item -> item.getCreatedBy())
    .map(createdBy -> Json.createObjectBuilder()
        .add("createdBy", createdBy)
        .add("phone", baseManager.findObjectsByNamedQuery(
            Class2.class, "Class2.findByCreatedBy", new Object[] {createdBy})
            .get(0).getPhone())
    )
    .forEach(jpb -> groupsBuilder.add(jpb));

我仍然不清楚是否(或为什么)findObjectsByNamedQuery不是varargs方法。成为一个varargs方法是很自然的,不需要这些明确的new Object[] { … }分配。

答案 1 :(得分:0)

使用纯Java8 Stream API:

public void convertItemsToJSon(List<Item> items) {
    ...
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    Map<Item, List<Class2>> sqlItems = items
            .stream()
            .collect(Collectors.toMap(Function.identity(), (item) -> baseManager.findObjectsByNamedQuery(Class2.class, "Class2.findByCratedBy", new Object[]{item.getCreatedBy()})));

    sqlItems.entrySet()
            .stream()
            .map(sqlItem -> buildJson(sqlItem.getKey(), sqlItem.getValue()))
            .forEach(groupsBuilder::add);
    ...
}

private JsonObjectBuilder buildJson(Item item,  List<Class2> class2Items) {
    return Json.createObjectBuilder().add("createdBy", item.getCreatedBy());
}

StreamEx library

public void convertItemsToJSonStreamEx(List<Item> items) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    ...
    StreamEx.of(items)
            .cross(item -> baseManager.findObjectsByNamedQuery(Class2.class, "Class2.findByCratedBy", new Object[]{item.getCreatedBy()}).stream())
            .mapKeys(item -> Json.createObjectBuilder().add("createdBy", item.getCreatedBy()))
            .mapKeyValue(this::addField)
            .forEach(groupsBuilder::add);
    ...
}

private JsonObjectBuilder addField(JsonObjectBuilder json, Class2 class2) {
    // You logic how to convert class2 to field in JSON
    return json;
}

答案 2 :(得分:0)

感谢您的帮助和解决方案。最有帮助的是Vlad Bochenin的第一个回复代码在这里:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    items.stream().map(item -> {
        List<Class2> items2 = baseManager.findObjectsByNamedQuery(Class2.class, "Class2.findByCreatedBy", new Object[]{item.getCreatedBy()});
        JsonObjectBuilder jpb = Json.createObjectBuilder()
                .add("createdBy", item.getCreatedBy())
                .add("phone", items2.get(0).getPhone())
                return jpb;
    }).forEach(groupsBuilder::add);