I have a JSON with a list of students as below - for each Student, I want to print the hobbies, if no hobby is present show NA using Java 8. I have written the below code which is working but I am having to use 2 maps. Please suggest if this code can be optimized.
JSON
{
"students":[
{
"fullName":"AAAAA",
"standard":10,
"hobbies":[
"programming",
"reading"
]
},
{
}
]
}
JAVA 8
Map<String, List<Student>> studentMap = reportCard.getStudents().stream().collect(Collectors.groupingBy(Student::getFullName));
Map<String, String> studentMap2 = new TreeMap<>();
studentMap.keySet().forEach(key -> Optional.ofNullable(studentMap.get(key).get(0).getHobbies())
.ifPresentOrElse(hobbies -> studentMap2.put(key, hobbies.stream().map(String::trim).collect(Collectors.joining(";"))), () -> studentMap2.put(key, "NA")));
CodePudding user response:
Using Java 8
You can use the collectors.toMap
from java 8 to have the desired output as shown in the code below:
Here,
- I have taken the sample json in the Text Block(feature from jdk15) to have the json in a readable format.(You can have it in the simple string format also)
- I have used
collectors.toMap
in which we will have the key as student Name and for the value i have checked if the hobbies list is not null and should not be empty and then perform the downstream operation of joining all the hobbies of the student otherwise it will have "NA" and i have used merger(a,b) -> a "," b
, it will combine the hobbies of same student with same name if exists andTreeMap::new
will sort the hobbies in natural order.
Code:
public class Test {
public static void main(String[] args) throws JsonProcessingException {
String input = """
{
"students": [
{
"fullName": "AAAAA",
"standard": 10,
"hobbies": [
"programming",
"reading"
]
},
{
"fullName": "BBBB",
"standard": 12,
"hobbies": [
"music",
"reading"
]
},
{
"fullName": "CCCC",
"standard": 12,
"hobbies": [
]
},
{
}
]
}
""";
ObjectMapper mapper = new ObjectMapper();
StudentData data = mapper.readValue(input,StudentData.class);
Map<String,String> output =
data.getStudentList().stream().filter(a -> a.getName()!=null)
.collect(Collectors.toMap(Student::getName,
x -> (x.getHobbies()!=null && !x.getHobbies().isEmpty() ? String.join(",",x.getHobbies()) : "NA")
,(a,b) -> a "," b,TreeMap::new));
System.out.println(output);
}
}
Output::
{AAAAA=programming,reading, BBBB=music,reading, CCCC=NA}
CodePudding user response:
I think you should split getting data and pring it.
public static void main(String... args) {
Root root = new Root();
Map<String, Set<String>> studentHobbies = getStudentHobbies(root);
printStudentHobbies(studentHobbies);
}
private static Map<String, Set<String>> getStudentHobbies(Root root) {
return Optional.ofNullable(root.getStudents()).orElse(List.of()).stream()
.collect(Collectors.toMap(Student::getFullName,
student -> Optional.ofNullable(student.getHobbies())
.orElse(Set.of())));
}
private static void printStudentHobbies(Map<String, Set<String>> studentHobbies) {
studentHobbies.forEach((fullName, hobbies) ->
System.out.format("%s - %s\n",
fullName,
hobbies.isEmpty() ? "NA" : hobbies));
}
Just in case, we have following classes
private static class Root {
private List<Student> students;
}
private static class Student {
private String fullName;
private int standard;
private Set<String> hobbies;
}