使用Java Stream获取json密钥的计数



我有一个json对象,看起来像这个

[{
"startAt": 1617605301292,
"endAt": 1617605317095,
"duration": 15803,
"selection": {
"selected.Speed": "0",
"selected.Low": "65535",
"selected.Fast": "7173",
"selected.medium": "5"
},
"details": {
"phase": [{
"value": "2",
"timestamp": 1617605301316
}]
}
},
{
"startAt": 1617603849697,
"endAt": 1617603966378,
"duration": 116681,
"selection": {
"selected.Speed": "0",
"selected.Low": "65535",
"selected.Fast": "123",
"selected.medium": "5"
},
"details": {
"phase": [{
"value": "2",
"timestamp": 1617603849749
}]
}
}
]

我需要数一下选择了多少次。快速发生了。我正在尝试流,这是我迄今为止写的

List<Map<String, Object>> jsonObj = mapper.readValue(jArr, new TypeReference<List<Map<String, Object>>>(){});

Map<String, Long> counted = jsonObj.stream()
.map(x -> x.get("selection").toString() )
.collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted.toString());

但我正在计算选择对象内的所有键,并且我想要计算特定Json键,即selected.Fast例如selected.Fast:"7173" -> occurred - 5times selected.Fast:"123" -> occurred - 2times

如有任何帮助,我们将不胜感激。

我需要计算选择的次数。快速发生了。

这就是你想要的吗?

List<Map<String, Object>> jsonObj = mapper.readValue(jArr, new TypeReference<List<Map<String, Object>>>(){});

long count = jsonObj.stream()
.map(x -> x.get("selection").toString())
.filter(s -> s.contains("selected.Fast"))
.count()
System.out.println(count);

你能检查一下这是否是你想要的吗?

List<JsonNode> jsonObj = mapper.readValue(jArr, new TypeReference<List<JsonNode>>() {
});
Map<String, Long> counted = jsonObj.stream()
.map(x -> {
String selection = x.get("selection").get("selected.Fast").asText();
return "selected.Fast:" + selection;
}).collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted); //{selected.Fast:123=1, selected.Fast:7173=1}

编辑:不转换为JsonNode

List<Map<String, Object>> jsonObj = mapper.readValue(jArr, new TypeReference<List<Map<String, Object>>>(){});
Map<String, Long> counted = jsonObj.stream()
.map(x -> {
String selection = ((Map<String,Object>)x.get("selection")).get("selected.Fast").toString();
return "selected.Fast:" + selection;
}).collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted);

编辑2:获取所选内容内所有元素计数的解决方案

Map<String, Long> counted = jsonObj.stream().flatMap(x -> {
JsonNode selection = x.get("selection");
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(selection.fields(), 0), false);
})
.map(x -> x.getKey() + ":" + x.getValue()).collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted);

您可以使用jackson库进行正常的反序列化,并创建这样的对象结构:

@Setter
@Getter
@NoArgsConstructor
static class Source {
private long startAt;
private long endAt;
private long duration;
private SourceSelection selection;
private SourceDetails details;
}
@Setter
@Getter
@NoArgsConstructor
static class SourceSelection {
private long speed;
private long low;
private long fast;
private long medium;
}
@Setter
@Getter
@NoArgsConstructor
static class SourceDetails {
private List<SourcePhase> phase;
}
@Setter
@Getter
@NoArgsConstructor
static class SourcePhase {
private int value;
private long timestamp;
}

然后您需要将json反序列化为Source.class对象:

List<Source> sourceList = new ObjectMapper().readValue(
JSON,
new ObjectMapper().getTypeFactory().constructCollectionType(List.class, Source.class)
);

JSON是您的来源json

然后,您可以使用一个标准的流API进行映射、过滤和计数:

long result = sourceList.stream()
.map(Source::getSelection)
.filter(s-> s.getFast() != 0)
.count();

要在具有不确定级别的所有级别的JSON记录中输出指定名称的字段的信息,Java代码将是漫长而复杂的。

您可以使用开源Java包SPL来实现这一点。这很简单,只需一行代码就足够了:

1

最新更新