英文:
Incrementing and initializing multiple counters using Java Streams
问题
以下是使用流来初始化计数器并循环遍历集合的代码片段:
// 使用流来初始化计数器并循环遍历集合
int errorOnlyCount = (int) summaryReportItemList.stream()
.map(this::getTermErrorCount)
.filter(map -> map.get("errorCount") > 0 && map.get("warningCount") == 0)
.count();
int warningOnlyCount = (int) summaryReportItemList.stream()
.map(this::getTermErrorCount)
.filter(map -> map.get("errorCount") == 0 && map.get("warningCount") > 0)
.count();
int bothErrorAndWarningCount = (int) summaryReportItemList.stream()
.map(this::getTermErrorCount)
.filter(map -> map.get("errorCount") > 0 && map.get("warningCount") > 0)
.count();
int successfulProcessedCount = (int) summaryReportItemList.stream()
.map(this::getTermErrorCount)
.filter(map -> map.get("errorCount") == 0 && map.get("warningCount") == 0)
.count();
你可以根据这个模式,为每个计数器创建一个类似的流,然后使用 .count()
方法来获取满足条件的元素数量。这个代码片段会执行相同的操作,但是使用了流的方式,更加紧凑和函数式。记得在类中定义 getTermErrorCount
方法,它接收一个 ReportItem
对象并返回一个包含错误和警告计数的映射。
英文:
Please I need help with the use of streams to initialize counters while looping through a collection:
//Method containing the logic to be converted to streams
int errorOnlyCount = 0;
int warningOnlyCount = 0;
int bothErrorAndWarningCount = 0;
int successfulProcessedCount = 0;
for(ReportItem summaryReportItem: summaryReportItemList){
Map<String, Integer> summaryReportItemMap = getTermErrorCount(summaryReportItem);
if(summaryReportItemMap.get("errorCount").intValue() > 0 &&
summaryReportItemMap.get("warningCount").intValue() == 0
){
errorOnlyCount += 1;
}
if(summaryReportItemMap.get("errorCount").intValue() == 0 &&
summaryReportItemMap.get("warningCount").intValue() > 0
){
warningOnlyCount += 1;
}
if(summaryReportItemMap.get("errorCount").intValue() > 0 &&
summaryReportItemMap.get("warningCount").intValue() > 0
){
bothErrorAndWarningCount += 1;
}
if(summaryReportItemMap.get("errorCount").intValue() == 0 &&
summaryReportItemMap.get("warningCount").intValue() == 0
){
successfulProcessedCount += 1;
}
}
//Method called from the logic above
private Map<String, Integer> getTermErrorCount(ReportItem summaryReportItem){
int errorCount = 0;
int warningCount = 0;
if(summaryReportItem.getIsDuplicateItemError())
errorCount += 1;
if(summaryReportItem.getIsDescriptionWarning())
warningCount += 1;
Map<String, Integer> errorWarningCounterMap = new HashMap<>();
errorWarningCounterMap.put("errorCount", errorCount);
errorWarningCounterMap.put("warningCount", warningCount);
return errorWarningCounterMap;
}
//POJO with the string id and booleans variables
public class ReportItem {
private String id;
private boolean isMissingIdError;
public ReportItem id(String id) {
this.id = id;
return this;
}
@Nonnull
@JsonProperty("id")
@JsonInclude(JsonInclude.Include.USE_DEFAULTS)
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public ReportItem isMissingIdError(Boolean isMissingIdError) {
this.isMissingIdError = isMissingIdError;
return this;
}
@Nullable
@JsonProperty("isMissingIdError")
@JsonInclude(JsonInclude.Include.USE_DEFAULTS)
public Boolean getIsMissingIdError() {
return this.isMissingIdError;
}
public void setIsMissingIdError(String id) {
this.isMissingIdError = isMissingIdError;
}
}
I was thinking of creating a stream for each if-block, but then how do I increment and initialize the counters.
Below is my code for the first counter's block.
Stream<ReportItem> errorOnlyCountStream = summaryReportItemList.stream().filter(i -> (getTermErrorCount(i).get("errorCount").intValue() > 0 &&
getTermErrorCount(i).get("warningCount").intValue() == 0));
Please, can someone help out with a snippet for the best approach?
答案1
得分: 2
你实际上可以从一个流中很好地完成所有这些操作。
Map<Boolean, Map<Boolean, Long>> results =
summaryReportItemList.stream()
.map(ThisClass::getTermErrorCount)
.collect(
Collectors.partitioningBy(
map -> map.get("errorCount") > 0,
Collectors.partitioningBy(
map -> map.get("warningCount") > 0,
Collectors.counting())));
int errorOnlyCount = results.get(true).get(false).intValue();
int warningOnlyCount = results.get(false).get(true).intValue();
int bothErrorAndWarningCount = results.get(true).get(true).intValue();
int successfullyProcessedCount = results.get(false).get(false).intValue();
从这段代码的特定结构来看,似乎你可以完全消除映射转换,并直接在 getIsDuplicateItemError
和 getIsDescriptionWarning
上进行分区,但这与你已经编写的代码最为相似。
英文:
You can actually do this all reasonably well from one stream.
Map<Boolean, Map<Boolean, Long>> results =
summaryReportItemList.stream()
.map(ThisClass::getTermErrorCount)
.collect(
Collectors.partitioningBy(
map -> map.get("errorCount") > 0,
Collectors.partitioningBy(
map -> map.get("warningCount") > 0,
Collectors.counting())));
int errorOnlyCount = results.get(true).get(false).intValue();
int warningOnlyCount = results.get(false).get(true).intValue();
int bothErrorAndWarningCount = results.get(true).get(true).intValue();
int successfullyProcessedCount = results.get(false).get(false).intValue();
From the particular structure of this code, it looks like you could eliminate the map conversion entirely and partition directly on getIsDuplicateItemError
and getIsDescriptionWarning
, but this is most similar to the code you've already written.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论