5

I have a list of data like the one given below:

List<Data> data = new ArrayList<Data>(); data.add(new Data("d1", "option1")); data.add(new Data("d2", "option1")); data.add(new Data("d1", "option2")); data.add(new Data("d3", "option1")); data.add(new Data("d3", "option2")); data.add(new Data("d3", "option3")); 

The structure looks like this:

class Data { private String name; private String option; private List<String> options = new ArrayList<>(); public Data(String name, String option) { this.name = name; this.option = option; } public void addOption(String option) { options.add(option); } } 

How to group the items to a new array based on the name with its options,

[ "d1": { "name": "d1", "options": ["option1", "option2"] }, "d2": { "name": "d2", "options": ["option1"] }, "d3": { "name": "d3", "options": ["option1", "option2", "option3"] } ] 
3
  • To clarify: Do you want the output as a JSON-String? Or a way to get all option fields in the options field of a new instance of Data? For the latter I would already recommend to change something because it's weird to have both a list of options and a single String option in your class if they both basically mean the same. Commented May 30, 2018 at 6:22
  • 2
    You can't instantiate List; it's an interface. Why does Data have both a single option and a list of options? You never call addOption. Also, you can't group them to an array. Do you mean a Map? Commented May 30, 2018 at 6:26
  • No JSON, just for brevity I have given the object structure like that. Commented May 30, 2018 at 6:52

4 Answers 4

4

You can use a Collectors.toMap collector:

Map<String,Data> grouped = data.stream() .collect(Collectors.toMap(Data::getName, d -> new Data(d.getName(),d.getOption()), (d1,d2) -> {d1.addOptions(d2.getOptions()); return d1;}); 

This will require changing the Data constructor to add the passed option to the options List as well as adding an addOptions method that receives a list of options and adds all of them to the options List of the current instance.

Sign up to request clarification or add additional context in comments.

1 Comment

This approach looks convenient for me, I get collection of type "Data" as values from the result map, than of type List<String>.
3

Try this out,

final Map<String, List<String>> optionsByName = dataList.stream().collect( Collectors.groupingBy(Data::getName, Collectors.mapping(Data::getOption, Collectors.toList()))); 

I would suggest you to use this map as a source to create the DTO you need, without cluttering your code to get the exact result you want.

Comments

2

You can use a simple grouping collector on the stream:

Map<String, List<String>> optionMap = data.stream() .collect(Collectors.groupingBy(Data::getName, Collectors.mapping(Data::getOption, Collectors.toList()))); 

When tested with your test list, the above produces this output:

{d1=[option1, option2], d2=[option1], d3=[option1, option2, option3]} 

The above seems like a better, type-safe alternative to your desired map. Additionally, it avoids unnecessary duplication.

Your final map can nonetheless be computed based on the above:

Map<String, Map<String, Object>> m = new HashMap<>(); optionMap.entrySet().forEach(entry -> { Map<String, Object> map = new HashMap<>(); map.put("name", entry.getKey()); map.put("options", entry.getValue()); m.put(entry.getKey(), map); }); 

The m map above looks like:

{d1={name=d1, options=[option1, option2]}, d2={name=d2, options=[option1]}, d3={name=d3, options=[option1, option2, option3]}} 

This is what you need, but it seems that it contains duplicated data, and it's less type-safe than the simple map in the previous result.

Comments

0
 public class Test2 { static List<Employee> getAllEmployees() { List<Employee> employeeList = new ArrayList<Employee>(); Employee e1= new Employee("sudhansu",46,135000.00,"JAVA"); Employee e2= new Employee("Himanshu",26,135000.00,"JAVA"); Employee e3= new Employee("Pabitra",53,135000.00,"ORACLE"); Employee e4= new Employee("Rajan",36,135000.00,"Hibernate"); Employee e5= new Employee("Raman",36,135000.00,"JAVA"); Employee e6= new Employee("Sambhu",26,135000.00,"MYSQL"); Employee e7= new Employee("Sagar",37,135000.00,"ORACLE"); Employee e8= new Employee("Ranjeet",26,135000.00,".NET"); Employee e9= new Employee("Chitra",46,135000.00,".NET"); Employee e10= new Employee("Minu",28,135000.00,".NET"); employeeList.add(e1); employeeList.add(e2); employeeList.add(e3); employeeList.add(e4); employeeList.add(e5); employeeList.add(e6); employeeList.add(e7); employeeList.add(e8); employeeList.add(e9); employeeList.add(e10); return employeeList; } public static void main(String[] args) { // TODO Auto-generated method stub List<Employee> empList= getAllEmployees(); Map<String, List<String>> map1=empList.stream().collect(Collectors.groupingBy(e->e.getSkills(),LinkedHashMap::new, Collectors.mapping(Employee::getName,Collectors.toList()))); System.out.println("employee map"+map1); } } 

2 Comments

same.....almost
Explanation? Notes?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.