将 POJO 转换为 Java 8 中的树结构,以在层次结构中表示数据
Convert a POJO to Tree structure in Java 8 for representation of data in hierarchical structure
我在 postgresql 中有一个由 Hibernate Projection 编辑的 List<CropDetailDto>
return 本地查询。
我想以 分层/树 格式表示它以将其作为响应发送。
我在 List<CropDetailDto>
上使用了多个嵌套 Collectors.groupingBy
public Map<String, Map<String, Map<String, List<CropDetailDto>>>> findCropDetails() {
List<CropDetailDto> cropdetails = cropRepository.getCropDetails();
return cropdetails.stream().collect(Collectors.groupingBy(CropDetailDto::getCropName, Collectors.groupingBy(
v -> v.getVarietyName() == null ? "undefined" : v.getVarietyName(),
Collectors.groupingBy(m -> m.getSubVarietyName() == null ? "undefined" : m.getSubVarietyName()))));
}
我以某种方式能够以这种格式表示数据。
{
"Tomato": {
"Red Tomato": {
"Red Tomato 1 quality": [
{
"cropName": "Tomato",
"varietyName": "Red Tomato",
"subVarietyName": "Red Tomato 1 quality",
"varietyId": 1002,
"cropId": 1,
"subVarietyId": 1003 //cropDetailDto is again represented
//at the leaf level
}
],
"Red Tomato 2 quality": [
{
"cropName": "Tomato",
"varietyName": "Red Tomato",
"subVarietyName": "Red Tomato 2 quality",
"varietyId": 1002,
"cropId": 1,
"subVarietyId": 1004
}
]
}
},
"Brinjal": {
"undefined": {
"undefined": [
{
"cropName": "Brinjal",
"varietyName": null,
"subVarietyName": null,
"varietyId": null,
"cropId": 8,
"subVarietyId": null
}
]
}
}
}
但是,此表示将 undefined
作为键,因为它为空键抛出了 NPE。
我想以更简洁的格式表示相同的数据。
像这样:
{
"Tomato": {
"Red Tomato": [
"Red Tomato 1 quality",
"Red Tomato 2 quality"
]
},
"Brinjal": {}
}
即
如果有一个空键,我希望它移动到下一个条目。
我最近开始使用java8,我正在寻找一种简洁的方法来实现上述结构。
CropDetailDto:
public interface CropDetailDto {
Long getCropId();
String getCropName();
Long getVarietyId();
String getVarietyName();
Long getSubVarietyId();
String getSubVarietyName();
}
生成的 return 类型也可以是简单的 HashMap<String, Object>
。
此外,如果使用 Java 8 个功能 无法实现此目的,请提供一种无需 [=46] 即可实现的方法=]java8。
提前致谢。
你可以用Collectors.mapping()
代替最后的Collectors.groupingBy()
:
public Map<String, Map<String, List<String>>> findCropDetails() {
List<CropDetailDto> cropdetails = cropRepository.getCropDetails();
return cropdetails.stream().collect(Collectors.groupingBy(CropDetailDto::getCropName,
Collectors.groupingBy(v -> v.getVarietyName() == null ? "undefined" : v.getVarietyName(),
Collectors.mapping(m -> m.getSubVarietyName() == null ? "undefined" : m.getSubVarietyName(),
Collectors.toList()))));
}
这将return以下地图:
{
"Tomato": {
"Red Tomato": [
"Red Tomato 1 quality",
"Red Tomato 2 quality"
]
},
"Brinjal": {
"undefined": [
"undefined"
]
}
}
要从结果中删除 null
值,您可以使用 Collectors.filtering()
并稍微修改上面的代码:
public Map<String, Map<String, List<String>>> findCropDetails() {
List<CropDetailDto> cropdetails = cropRepository.getCropDetails();
return cropdetails.stream().collect(Collectors.groupingBy(CropDetailDto::getCropName,
Collectors.filtering(v -> v.getVarietyName() != null, Collectors.groupingBy(CropDetailDto::getVarietyName,
Collectors.filtering(m -> m.getSubVarietyName() != null, Collectors.mapping(CropDetailDto::getSubVarietyName,
Collectors.toList()))))));
}
使用这个最终结果将如下所示:
{
"Tomato": {
"Red Tomato": [
"Red Tomato 1 quality",
"Red Tomato 2 quality"
]
},
"Brinjal": {}
}
我在 postgresql 中有一个由 Hibernate Projection 编辑的 List<CropDetailDto>
return 本地查询。
我想以 分层/树 格式表示它以将其作为响应发送。
我在 List<CropDetailDto>
Collectors.groupingBy
public Map<String, Map<String, Map<String, List<CropDetailDto>>>> findCropDetails() {
List<CropDetailDto> cropdetails = cropRepository.getCropDetails();
return cropdetails.stream().collect(Collectors.groupingBy(CropDetailDto::getCropName, Collectors.groupingBy(
v -> v.getVarietyName() == null ? "undefined" : v.getVarietyName(),
Collectors.groupingBy(m -> m.getSubVarietyName() == null ? "undefined" : m.getSubVarietyName()))));
}
我以某种方式能够以这种格式表示数据。
{
"Tomato": {
"Red Tomato": {
"Red Tomato 1 quality": [
{
"cropName": "Tomato",
"varietyName": "Red Tomato",
"subVarietyName": "Red Tomato 1 quality",
"varietyId": 1002,
"cropId": 1,
"subVarietyId": 1003 //cropDetailDto is again represented
//at the leaf level
}
],
"Red Tomato 2 quality": [
{
"cropName": "Tomato",
"varietyName": "Red Tomato",
"subVarietyName": "Red Tomato 2 quality",
"varietyId": 1002,
"cropId": 1,
"subVarietyId": 1004
}
]
}
},
"Brinjal": {
"undefined": {
"undefined": [
{
"cropName": "Brinjal",
"varietyName": null,
"subVarietyName": null,
"varietyId": null,
"cropId": 8,
"subVarietyId": null
}
]
}
}
}
但是,此表示将 undefined
作为键,因为它为空键抛出了 NPE。
我想以更简洁的格式表示相同的数据。
像这样:
{
"Tomato": {
"Red Tomato": [
"Red Tomato 1 quality",
"Red Tomato 2 quality"
]
},
"Brinjal": {}
}
即 如果有一个空键,我希望它移动到下一个条目。
我最近开始使用java8,我正在寻找一种简洁的方法来实现上述结构。
CropDetailDto:
public interface CropDetailDto {
Long getCropId();
String getCropName();
Long getVarietyId();
String getVarietyName();
Long getSubVarietyId();
String getSubVarietyName();
}
生成的 return 类型也可以是简单的 HashMap<String, Object>
。
此外,如果使用 Java 8 个功能 无法实现此目的,请提供一种无需 [=46] 即可实现的方法=]java8。
提前致谢。
你可以用Collectors.mapping()
代替最后的Collectors.groupingBy()
:
public Map<String, Map<String, List<String>>> findCropDetails() {
List<CropDetailDto> cropdetails = cropRepository.getCropDetails();
return cropdetails.stream().collect(Collectors.groupingBy(CropDetailDto::getCropName,
Collectors.groupingBy(v -> v.getVarietyName() == null ? "undefined" : v.getVarietyName(),
Collectors.mapping(m -> m.getSubVarietyName() == null ? "undefined" : m.getSubVarietyName(),
Collectors.toList()))));
}
这将return以下地图:
{
"Tomato": {
"Red Tomato": [
"Red Tomato 1 quality",
"Red Tomato 2 quality"
]
},
"Brinjal": {
"undefined": [
"undefined"
]
}
}
要从结果中删除 null
值,您可以使用 Collectors.filtering()
并稍微修改上面的代码:
public Map<String, Map<String, List<String>>> findCropDetails() {
List<CropDetailDto> cropdetails = cropRepository.getCropDetails();
return cropdetails.stream().collect(Collectors.groupingBy(CropDetailDto::getCropName,
Collectors.filtering(v -> v.getVarietyName() != null, Collectors.groupingBy(CropDetailDto::getVarietyName,
Collectors.filtering(m -> m.getSubVarietyName() != null, Collectors.mapping(CropDetailDto::getSubVarietyName,
Collectors.toList()))))));
}
使用这个最终结果将如下所示:
{
"Tomato": {
"Red Tomato": [
"Red Tomato 1 quality",
"Red Tomato 2 quality"
]
},
"Brinjal": {}
}