18

I have a class like this

ObjectA
id 
type

where id is unique but the type can be duplicate so if I have a list of ObjectA like this

(id, type) = (1, "A") , (2, "B"), (3, "C"), (4, "A")

then I want Map<type, List<id>> where map is

< "A",[1,4],
  "B",[2],
  "C",[3] >

It is working with Java 7 but can't find a way to do it in Java 8. In Java 8 I can create key, value pair but not able to create a list if a type is same.

2
  • 1
    which code is working with java 7? Commented Feb 12, 2018 at 13:25
  • Please post the code causing the problem? Commented Feb 12, 2018 at 13:25

6 Answers 6

24
yourTypes.stream()
         .collect(Collectors.groupingBy(
               ObjectA::getType,
               Collectors.mapping(
                    ObjectA::getId, Collectors.toList()
)))
Sign up to request clarification or add additional context in comments.

Comments

21

Employee list to map

List<Employee> list = new ArrayList<>();
            list.add(new Employee(1, "John",80000));
            list.add(new Employee(2, "Jack", 90000));
            list.add(new Employee(3, "Ricky", 120000));


            // key = id, value - name
            Map<Integer, String> result1 = list.stream().collect(
                    Collectors.toMap(Employee::getId, Employee::getName));

2 Comments

What if I want to give a constant value instead of Employee::getName?
Map<Integer, String> result1 = list.stream().collect( Collectors.toMap(Employee::getId, "constant value here like this")); @ArunGowda
7

Though you got some nice answer. I would like to share another way of doing same. It's when you have to tackle really complex conversions to map.

class Student {
    private String name;
    private Integer id;
//getters / setters / constructors
}

            Map<String, List<Integer>> map = Arrays.asList(
            new Student("Jack", 2),
            new Student("Jack", 2),
            new Student("Moira", 4)
    )
            .stream()
            .collect(
                    Collectors.toMap(
                            Student::getName,
                            student -> {
                                List list = new ArrayList<Integer>();
                                list.add(student.getId());
                                return list;
                            },
                            (s, a) -> {
                                s.add(a.get(0));
                                return s;
                            }
                    )
            );

Notice how complex you could play with value and return the new value accordingly.

toMap parameters are respectively keyMapper function, valueMapper function and merger respectively.

Cheers!

Comments

4

A way to do it without streams:

Map<String, List<Integer>> map = new HashMap<>();
list.forEach(object -> 
    map.computeIfAbsent(object.getType(), k -> new ArrayList<>())
        .add(object.getId()));

This uses Iterable.forEach and Map.computeIfAbsent to iterate the list and group its elements (here named object) by its type attribute, creating a new ArrayList if there was no entry for that type in the map yet. Then, the id of the object is added to the list.

3 Comments

without streams is going to be your nick soon... :)
I disagree! I found computeIfAbsent wonderful when it was beyond streams to tackle some scenario.
Perfect! that is exctly what i was looking for, even without stream is a great answer, thannk you
3
List<Employee> list = new ArrayList<>();
list.add(new Employee(1, "John",80000));
list.add(new Employee(2, "Jack", 90000));
list.add(new Employee(3, "Ricky", 120000));

// key = id, value - name
Map<Integer, String> result = list.stream().collect(
Collectors.toMap(Employee::getId, Employee::getName));

If you want to give a constant value instead of name:
// key = id, value - "ABC"
Map<Integer, String> result = list.stream().collect(
Collectors.toMap(Employee::getId, emp-> "ABC"));

1 Comment

Please provide a detailed explanation to your answer, in order for the next user to understand your answer better.
0

List to Map object

employeeList.stream().collect(Collectors.groupingBy(Employee::getName, Collectors.toList())) .forEach((key,value)->System.out.println("key : "+key+" , value : "+value));

output:

key: Name : value : List of employee Object

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.