Java:平面列表<;地图<;字符串,对象>&燃气轮机;到分层列表<;地图<;字符串,对象>&燃气轮机;
这个问题似乎相当复杂,所以我在这里发布这个问题,寻找任何可能的解决方法 我有地图清单。我还需要一个地图列表,但要确保地图被转换成某种层次结构 原始数据:(列表) 此地图列表将转换为以下地图列表:(列表) 作为一个幼稚的解决方案,我试图手动处理它们(真的很无聊),所以我正在寻找任何高效、干净的方法,使用流或任何其他可能的方法来处理它们 更新 简单的解决方案如下所示Java:平面列表<;地图<;字符串,对象>&燃气轮机;到分层列表<;地图<;字符串,对象>&燃气轮机;,java,jackson,gson,java-stream,linkedhashmap,Java,Jackson,Gson,Java Stream,Linkedhashmap,这个问题似乎相当复杂,所以我在这里发布这个问题,寻找任何可能的解决方法 我有地图清单。我还需要一个地图列表,但要确保地图被转换成某种层次结构 原始数据:(列表) 此地图列表将转换为以下地图列表:(列表) 作为一个幼稚的解决方案,我试图手动处理它们(真的很无聊),所以我正在寻找任何高效、干净的方法,使用流或任何其他可能的方法来处理它们 更新 简单的解决方案如下所示 public List<Map<String, Object>> transformResultSet(Lis
public List<Map<String, Object>> transformResultSet(List<Map<String, Object>> flatDataList) {
List<Map<String, Object>> hierarchicalDataList = new ArrayList<Map<String, Object>>();
Map<String, List<Map<String, Object>>> studentIdToStudentDataListMap = new LinkedHashMap<>();
for (Map<Integer, Object> flatData : flatDataList) {
if (studentIdToStudentDataListMap.get(flatData.get("student_id")) == null) {
studentIdToStudentDataListMap.put(Integer.valueOf(flatData.get("student_id").toString()), new ArrayList<Map<String, Object>>());
}
studentIdToStudentDataListMap.get(Integer.valueOf(flatData.get("student_id").toString())).add(flatData);
}
for (Map.Entry<Integer, List<Map<String, Object>>> studentFlatDataList : studentIdToStudentDataListMap.entrySet()) {
Map<String, Object> studentHierarchicalDataMap = new LinkedHashMap<String, Object>();
Map<String, Object> studentFlatDataMap = studentFlatDataList.getValue().get(0);
studentHierarchicalDataMap.put("studentId", studentFlatDataMap.get("studentId"));
studentHierarchicalDataMap.put("name", studentFlatDataMap.get("name"));
List<Map<String, Object>> academicsList = new ArrayList<Map<String, Object>>();
for (Map<String, Object> studentDetailAcademic : studentFlatDataList.getValue()) {
Map<String, Object> academic = new LinkedHashMap<String, Object>();
academic.put("subjectId", studentDetailAcademic.get("subjectId"));
academic.put("marks", studentDetailAcademic.get("marks"));
academicsList.add(academic);
}
studentHierarchicalDataMap.put("academics", academicsList);
Map<String, Object> address = new LinkedHashMap<String, Object>();
address.put("street", studentFlatDataMap.get("street"));
address.put("state", studentFlatDataMap.get("state"));
studentHierarchicalDataMap.put("address", address);
hierarchicalDataList.add(studentHierarchicalDataMap);
}
return hierarchicalDataList;
}
公共列表transformResultSet(列表flatDataList){
List HierarchycalDataList=新建ArrayList();
Map studentTostudentDataListMap=新建LinkedHashMap();
用于(地图平面数据:平面数据列表){
if(studentdtostudentdatalistmap.get(flatData.get(“学生id”))==null){
studentToStudentDataListMap.put(Integer.valueOf(flatData.get(“student_id”).toString()),new ArrayList());
}
StudentToStudentDataListMap.get(Integer.valueOf(flatData.get(“学生id”).toString()).add(flatData);
}
对于(Map.Entry studentFlatDataList:studentDTStudentDataListMap.entrySet()){
Map studentHierarchicalDataMap=新建LinkedHashMap();
Map studentFlatDataMap=studentFlatDataList.getValue().get(0);
studentHierarchicalDataMap.put(“studentId”,studentFlatDataMap.get(“studentId”);
studentHierarchicalDataMap.put(“name”),studentFlatDataMap.get(“name”);
List academicsList=新建ArrayList();
对于(映射studentDetailAcademic:studentFlatDataList.getValue()){
Map academic=新建LinkedHashMap();
academic.put(“subjectId”),studentDetailAcademic.get(“subjectId”);
学术性。输入(“分数”),学生详细信息学术性。获取(“分数”);
学术列表。添加(学术);
}
studentHierarchicalDataMap.put(“学术界”,学术列表);
映射地址=新LinkedHashMap();
地址.put(“street”,studentFlatDataMap.get(“street”);
address.put(“state”,studentFlatDataMap.get(“state”);
studentHierarchicalDataMap.put(“地址”,address);
添加(studentHierarchicalDataMap);
}
返回层次数据表;
}
从json示例中,您似乎有列表
而不是列表
。
所以,只是给你一个想法创建两个对象,比如StudentDto
和MarkDto
假设输入对象是Student
和StudentDto
的成员为List
:
Map<String, List<Student>> map = list.stream().collect(groupingBy(Student::studentId));
Map<String, StudentDto> dtoMap = new HashMap<>();
for(Map.Entry<String, List<Student>> entry : map.entrySet()) {
StudentDto stud = new StudentDto();
//assign other studentDto properties
for(Student std : entry.getValue()) {
MarkDto mark = new MarkDto();
mark.setSubjectId(std.getStudentid());
mark.setMark(entry.getMark()));
stud.add(mark);
}
dtoMap.put(String.valueOf(stud.getId()), stud);
}
return dtoMap.stream().collect(Collectors.toList()); // or return the map itself
Map Map=list.stream().collect(groupingBy(Student::studentId));
Map dtoMap=newhashmap();
对于(Map.Entry:Map.entrySet()){
StudentDto stud=新StudentDto();
//将其他学生分配到属性
对于(学生标准:entry.getValue()){
MarkDto mark=新的MarkDto();
mark.setsubject(std.getStudentid());
mark.setMark(entry.getMark());
螺柱.添加(标记);
}
dtoMap.put(String.valueOf(stud.getId()),stud);
}
返回dtoMap.stream().collect(Collectors.toList());//或者返回地图本身
您可以通过以下几个步骤拆分算法:
subjectId
,标记
到新的地图
街道
,州
提取到新的地址
地图
列表
包裹地图
studentId
合并数据。当发生冲突时,我们需要合并列表
1.
和2.
除了键名之外是相同的。我们可以将其提取到一个新类中,以避免重复方法引用:
class ExtractKeysToMap implements Function<Map<String, Object>, Map<String, Object>> {
private final List<String> keys;
private final String newKey;
ExtractKeysToMap(String newKey, List<String> keys) {
this.newKey = Objects.requireNonNull(newKey);
this.keys = Objects.requireNonNull(keys);
}
@Override
public Map<String, Object> apply(Map<String, Object> map) {
Map<String, Object> academics = new HashMap<>();
keys.forEach(key -> {
Object value = map.remove(key);
if (value != null) academics.put(key, value);
});
map.put(newKey, academics);
return map;
}
}
似乎您需要按学生分组,同时还要更改json结构 更高级别,您可以这样做(稍后我们将看到详细信息): 以及
mergeHierarchicalStudents
方法:
Map<String, Object> mergeHierarchicalStudents(
Map<String, Object> oldSt, Map<String, Object> newSt) {
// We only need to merge the subjects
List<Map<String, Object>> oldAcademics =
(List<Map<String, Object>>) oldSt.get("academics");
List<Map<String, Object>> newAcademics =
(List<Map<String, Object>>) newSt.get("academics");
oldAcademcis.addAll(newAcademics);
return oldS;
}
提供“幼稚的解决方案”以及迄今为止您尝试了什么。我们不知道您想要实现的对象结构。您确定要使用
列表
作为输出而不是结构对象吗?仅仅因为解决方案“无聊”并不一定意味着它不好。您的帖子不太清楚这是一个问题还是关于如何使用无聊的实现。你应该展示无聊的工作原理。如果有帮助,您可以基于字段studentId
在map
上使用groupingBy
。试着把它弄清楚一点看看类似的问题:,你只需要实现不同的合并功能。@Aman:问题更新为解决方案有多无聊:像一个可伸缩的解决方案。
class ExtractKeysToMap implements Function<Map<String, Object>, Map<String, Object>> {
private final List<String> keys;
private final String newKey;
ExtractKeysToMap(String newKey, List<String> keys) {
this.newKey = Objects.requireNonNull(newKey);
this.keys = Objects.requireNonNull(keys);
}
@Override
public Map<String, Object> apply(Map<String, Object> map) {
Map<String, Object> academics = new HashMap<>();
keys.forEach(key -> {
Object value = map.remove(key);
if (value != null) academics.put(key, value);
});
map.put(newKey, academics);
return map;
}
}
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./src/main/resources/test.json");
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
CollectionType jsonType = mapper.getTypeFactory().constructCollectionType(List.class, Map.class);
List<Map<String, Object>> response = mapper.readValue(jsonFile, jsonType);
final String academicsKey = "academics";
Collection<Map<String, Object>> result = response
.stream()
.map(new ExtractKeysToMap(academicsKey, Arrays.asList("subjectId", "marks")))
.map(new ExtractKeysToMap("address", Arrays.asList("street", "state")))
.peek(map -> map.computeIfPresent(academicsKey, (k, v) -> new LinkedList<>(Collections.singletonList(v))))
.collect(Collectors.toMap(
map -> map.get("studentId"),
map -> map,
(map0, map1) -> {
((List<Object>) map0.get(academicsKey)).addAll((List<Object>) map1.get(academicsKey));
return map0;
}))
.values();
mapper.writeValue(System.out, result);
}
}
[ {
"studentId" : 101,
"name" : "John",
"academics" : [ {
"subjectId" : 2001,
"marks" : 85
}, {
"subjectId" : 2002,
"marks" : 75
} ],
"address" : {
"street" : "Bakers Street",
"state" : "LA"
}
}, {
"studentId" : 102,
"name" : "Shae",
"academics" : [ {
"subjectId" : 3001,
"marks" : 96
} ],
"address" : {
"street" : "Howards",
"state" : "NYC"
}
} ]
Map<Integer, Map<String, Object>> grouped = flatDataList.stream()
.collect(Collectors.toMap(
s -> (Integer) s.get("studentId"),
s -> transformToHierarchicalStudent(s),
(oldS, newS) -> mergeHierarchicalStudents(oldS, newS)));
Map<String, Object> transformToHierarchicalStudent(Map<String, Object> flat) {
Map<String, Object> student = new LinkedHashMap<>();
student.put("studentId", flat.get("studentId"));
student.put("name", flat.get("name"));
Map<String, Object> address = new LinkedHashMap<>();
address.put("street", flat.get("street"));
address.put("state", flat.get("state"));
student.put("address", address);
List<Map<String, Object>> academics = new ArrayList<>();
Map<String, Object> subject = new LinkedHashMap<>();
subject.put("subjectId", flat.get("subjectId"));
subject.put("marks", flat.get("marks"));
academics.add(subject);
student.put("academics", academics);
return student;
}
Map<String, Object> mergeHierarchicalStudents(
Map<String, Object> oldSt, Map<String, Object> newSt) {
// We only need to merge the subjects
List<Map<String, Object>> oldAcademics =
(List<Map<String, Object>>) oldSt.get("academics");
List<Map<String, Object>> newAcademics =
(List<Map<String, Object>>) newSt.get("academics");
oldAcademcis.addAll(newAcademics);
return oldS;
}
List<Map<String, Object>> hierarchicalStudents = new ArrayList<>(grouped.values());