Java 8中需要映射的对象列表

16

我有一个类似这样的类

ObjectA
id 
type

其中id是唯一的,但type可以重复,因此如果我有像这样的ObjectA列表

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

那么我想要一个 Map<type, List<id>>,其中map是

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

它可以在Java 7中工作,但无法在Java 8中实现。在Java 8中,我可以创建键值对,但如果类型相同,则无法创建列表。


哪些代码适用于Java 7? - Govind Singh
请发布导致问题的代码? - daniu
6个回答

20
yourTypes.stream()
         .collect(Collectors.groupingBy(
               ObjectA::getType,
               Collectors.mapping(
                    ObjectA::getId, Collectors.toList()
)))

工作得很好,谢谢。 - Mugeesh Husain

16
员工列表转换为映射
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));

如果我想提供一个常量值代替 Employee::getName,该怎么办? - Arun Gowda
Map<Integer, String> result1 = list.stream().collect( Collectors.toMap(Employee::getId, "这里放常量值,就像这样")); - jarvo69

6

虽然你已经得到了一些不错的答案,但我想分享另一种做法。当你需要处理非常复杂的映射转换时,可以采用这种方式。

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;
                            }
                    )
            );

请注意,您可以使用不同的值进行复杂操作,并相应地返回新值。

toMap参数分别是keyMapper函数、valueMapper函数和merger函数。

干杯!


4
一种不使用流的方法:
```html

不使用流的方法:

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

这里使用 Iterable.forEachMap.computeIfAbsent 遍历 list 并根据其 type 属性将其元素(此处命名为 object)分组,如果地图中尚未存在该类型的条目,则创建一个新的 ArrayList。然后,将对象的 id 添加到列表中。


2
without streams” 很快就是你的昵称了… :) - Eugene
1
我不同意!当流无法处理某些情况时,我发现computeIfAbsent非常棒。 - Vinay Prajapati
1
太好了!这正是我在寻找的,即使没有流也是一个很好的答案,谢谢你。 - Thiesen

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"));

请提供详细的解释以便下一个用户更好地理解您的答案。 - Elydasian

0

将List转换为Map对象

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

输出:

key:姓名:value:员工对象列表


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接