如何使用 BinaryOperator 对对象流使用 Java reduce() 函数
How to use Java reduce() function on stream of objects with BinaryOperator
combinedResult
是一个 ObjectNode 类型的流,由如下数据组成,例如:
{"id":"id1","version":1,"Success":4,"Exception":6,"Failure":3}
{"id":"id1","version":1,"Success":4,"Exception":6,"Failure":3}
{"id":"id1","version":2,"Exception":1,"Success":2,"Failure":2}
{"id":"id1","version":2,"Exception":1,"Success":2,"Failure":2}
我想得到这样的结果:
{"id":"id1","version":1,"Success":8,"Exception":12,"Failure":6}
{"id":"id1","version":2,"Success":4,"Exception":2,"Failure":4}
我写了下面的 BinaryOperator 函数
BinaryOperator<ObjectNode> func = (o1, o2) -> {
if (o1.get("id").asText().equals(o2.get("id").asText()) &&
o1.get("version").equals(o2.get("version"))) {
ObjectNode o = Jive.newObjectNode();
o.set("id", Jive.newJsonNode(o1.get("id")));
o.set("version", Jive.newJsonNode(o1.get("version")));
o.set("Success", Jive.newJsonNode(o1.get("Success").asInt() + o2.get("Success").asInt()));
o.set("Failure", Jive.newJsonNode(o1.get("Failure").asInt() + o2.get("Failure").asInt()));
o.set("Exception", Jive.newJsonNode(o1.get("Exception").asInt() + o2.get("Exception").asInt()));
return o;
}
return o1;
};
combinedResult.stream().reduce(func)
但是当我尝试这个时,我得到以下结果:
Optional[{"id":"id1","version":1,"Success":8,"Failure":6,"Exception":12}]
我知道这是因为我在 BinaryOperator 中将 return o1
作为默认值,但我不知道如何解决这个问题。
你可以使用reduce方法。
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
您的初始身份是一个空的 HashMap,其键将是您要在其上累积结果的唯一标识符。 (ID + 版本)
public class JavaReduce {
public static void main(String[] args) {
//DataSetup
List<ObjectNode> objectNodeList = List.of(
new ObjectNode("id1", 1, 4, 6, 3),
new ObjectNode("id1", 1, 4, 6, 3),
new ObjectNode("id2", 2, 2, 1, 2),
new ObjectNode("id2", 2, 2, 1, 2));
Map<String, ObjectNode> objectNodeCumulativeMap = objectNodeList.stream()
.reduce(new HashMap<>(), (intermediate, ObjectNode) -> {
String key = ObjectNode.getId().concat(String.valueOf(ObjectNode.getVersion()));
if(!intermediate.containsKey(key)){
intermediate.put(key, ObjectNode);
} else {
ObjectNode objectNode = intermediate.get(key);
objectNode.setSuccess(objectNode.getSuccess() + ObjectNode.getSuccess());
objectNode.setFailure(objectNode.getFailure() + ObjectNode.getFailure());
objectNode.setException(objectNode.getException() + ObjectNode.getException());
}
return intermediate;
}, (cumulative, intermediate) -> {
cumulative.putAll(intermediate);
return cumulative;
});
System.out.println(objectNodeCumulativeMap.values());
}
}
//DTO for data
@Data
@AllArgsConstructor
@NoArgsConstructor
class ObjectNode {
private String id;
private Integer version;
private Integer success;
private Integer exception;
private Integer failure;
}
但是 Sudipta Bhattacharyya 和 Holger 提到的理想方法是使用 collect
下面是解决方案的片段。
public class JavaCollect {
public static void main(String[] args) {
//DataSetup
List<ObjectNode> objectNodeList = List.of(
new ObjectNode("id1", 1, 4, 6, 3),
new ObjectNode("id1", 1, 4, 6, 3),
new ObjectNode("id2", 2, 2, 1, 2),
new ObjectNode("id2", 2, 2, 1, 2));
Map<String, ObjectNode> collect = objectNodeList.stream()
.collect(groupingBy(JavaCollect::uniqueKey, collectingAndThen(toList(), JavaCollect::downstream)));
System.out.println(collect.values());
}
private static ObjectNode downstream(List<ObjectNode> list) {
ObjectNode objectNode = list.stream().findFirst().orElse(new ObjectNode());
objectNode.setSuccess(list.stream().map(ObjectNode::getSuccess).collect(summingInt(Integer::intValue)));
objectNode.setException(list.stream().map(ObjectNode::getException).collect(summingInt(Integer::intValue)));
objectNode.setFailure(list.stream().map(ObjectNode::getFailure).collect(summingInt(Integer::intValue)));
return objectNode;
}
private static String uniqueKey(ObjectNode objectNode) {
return objectNode.getId().concat(objectNode.getVersion().toString());
}
}
combinedResult
是一个 ObjectNode 类型的流,由如下数据组成,例如:
{"id":"id1","version":1,"Success":4,"Exception":6,"Failure":3}
{"id":"id1","version":1,"Success":4,"Exception":6,"Failure":3}
{"id":"id1","version":2,"Exception":1,"Success":2,"Failure":2}
{"id":"id1","version":2,"Exception":1,"Success":2,"Failure":2}
我想得到这样的结果:
{"id":"id1","version":1,"Success":8,"Exception":12,"Failure":6}
{"id":"id1","version":2,"Success":4,"Exception":2,"Failure":4}
我写了下面的 BinaryOperator 函数
BinaryOperator<ObjectNode> func = (o1, o2) -> {
if (o1.get("id").asText().equals(o2.get("id").asText()) &&
o1.get("version").equals(o2.get("version"))) {
ObjectNode o = Jive.newObjectNode();
o.set("id", Jive.newJsonNode(o1.get("id")));
o.set("version", Jive.newJsonNode(o1.get("version")));
o.set("Success", Jive.newJsonNode(o1.get("Success").asInt() + o2.get("Success").asInt()));
o.set("Failure", Jive.newJsonNode(o1.get("Failure").asInt() + o2.get("Failure").asInt()));
o.set("Exception", Jive.newJsonNode(o1.get("Exception").asInt() + o2.get("Exception").asInt()));
return o;
}
return o1;
};
combinedResult.stream().reduce(func)
但是当我尝试这个时,我得到以下结果:
Optional[{"id":"id1","version":1,"Success":8,"Failure":6,"Exception":12}]
我知道这是因为我在 BinaryOperator 中将 return o1
作为默认值,但我不知道如何解决这个问题。
你可以使用reduce方法。
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
您的初始身份是一个空的 HashMap,其键将是您要在其上累积结果的唯一标识符。 (ID + 版本)
public class JavaReduce {
public static void main(String[] args) {
//DataSetup
List<ObjectNode> objectNodeList = List.of(
new ObjectNode("id1", 1, 4, 6, 3),
new ObjectNode("id1", 1, 4, 6, 3),
new ObjectNode("id2", 2, 2, 1, 2),
new ObjectNode("id2", 2, 2, 1, 2));
Map<String, ObjectNode> objectNodeCumulativeMap = objectNodeList.stream()
.reduce(new HashMap<>(), (intermediate, ObjectNode) -> {
String key = ObjectNode.getId().concat(String.valueOf(ObjectNode.getVersion()));
if(!intermediate.containsKey(key)){
intermediate.put(key, ObjectNode);
} else {
ObjectNode objectNode = intermediate.get(key);
objectNode.setSuccess(objectNode.getSuccess() + ObjectNode.getSuccess());
objectNode.setFailure(objectNode.getFailure() + ObjectNode.getFailure());
objectNode.setException(objectNode.getException() + ObjectNode.getException());
}
return intermediate;
}, (cumulative, intermediate) -> {
cumulative.putAll(intermediate);
return cumulative;
});
System.out.println(objectNodeCumulativeMap.values());
}
}
//DTO for data
@Data
@AllArgsConstructor
@NoArgsConstructor
class ObjectNode {
private String id;
private Integer version;
private Integer success;
private Integer exception;
private Integer failure;
}
但是 Sudipta Bhattacharyya 和 Holger 提到的理想方法是使用 collect
下面是解决方案的片段。
public class JavaCollect {
public static void main(String[] args) {
//DataSetup
List<ObjectNode> objectNodeList = List.of(
new ObjectNode("id1", 1, 4, 6, 3),
new ObjectNode("id1", 1, 4, 6, 3),
new ObjectNode("id2", 2, 2, 1, 2),
new ObjectNode("id2", 2, 2, 1, 2));
Map<String, ObjectNode> collect = objectNodeList.stream()
.collect(groupingBy(JavaCollect::uniqueKey, collectingAndThen(toList(), JavaCollect::downstream)));
System.out.println(collect.values());
}
private static ObjectNode downstream(List<ObjectNode> list) {
ObjectNode objectNode = list.stream().findFirst().orElse(new ObjectNode());
objectNode.setSuccess(list.stream().map(ObjectNode::getSuccess).collect(summingInt(Integer::intValue)));
objectNode.setException(list.stream().map(ObjectNode::getException).collect(summingInt(Integer::intValue)));
objectNode.setFailure(list.stream().map(ObjectNode::getFailure).collect(summingInt(Integer::intValue)));
return objectNode;
}
private static String uniqueKey(ObjectNode objectNode) {
return objectNode.getId().concat(objectNode.getVersion().toString());
}
}