【问题标题】:java stream List<Object[]> to Map<Object, List<Object[]>>java 流 List<Object[]> 到 Map<Object, List<Object[]>>
【发布时间】:2017-11-28 03:00:31
【问题描述】:

我有List&lt;Object[]&gt;inner join MySQL查询,我需要创建一个ma​​pid和值object强>。

下面的代码有效,但如何使用 Streams 做到最好?

Map<Object, List<Object[]>> convert(List<Object[]> objects) {
    Map<Object, List<Object[]>> objectListMap = objects.stream()
        .collect(Collectors.toMap(obj -> obj[0], obj -> {
            List<Object[]> list = new ArrayList<>();
            list.add(obj);
            return list;
        }, (obj1, obj2) -> {
            obj1.addAll(obj2);
            return obj1;
        }));
    return objectListMap;
}


Object[] objects structure:
objects[0] = person id
...
objects[10] = event id
...
objects[15] = event name

这个查询找到了所有访问过该事件的人,但是objects数组中从0到10的索引可能是一样的,11-15总是变化的。

我想合并所有具有相同 id (objects[0]) 的对象列表。

next 中的每个值 地图 > 转换为 POJO:

PersonWithEvent converToEntity(List<Object[]> objects) {
Optional< PersonWithEvent > personWithEvent =                     
objects.stream()
.findFirst().map(obj -> {
    PersonWithEvent p = new PersonWithEvent();
    p.setId((Integer) obj[0]);
    ...
    return p;
});
personWithEvent.ifPresent(p -> {
    List<PersonEvent> personEvents = objects.stream()
            .map(obj -> {
                PersonEvent pe = new PersonEvent();
                pe.setName((String) obj[2]);
                ...
                return pe;
            })
            .collect(Collectors.toList());
    p.setPersonEvents(personEvents);
 });
 return personWithEvent.get();

 是否可以为一个流做到这一点?

【问题讨论】:

  • 你能解释一下想要的结构吗?从您的代码中分辨出来并不容易。你打算如何转换List&lt;Object[]&gt;?地图的键和值是什么? merge 函数应该做什么?
  • 我是否更正了每个Object[] 数组在索引0 处都有一个id 并且您想将此id 映射到其余的整个数组,例如objects[0] =&gt; objects。此外,您还想合并所有具有相同 id (objects[0]) 的对象列表。
  • 是的,我想合并所有具有相同 id (objects[0]) 的对象列表。

标签: java stream java-stream


【解决方案1】:

您似乎需要在数组Object 的索引零处按元素分组

Collectors.groupingBy 按键分组

Map<Object, List<Object[]>> map = objects.stream()
    .collect(Collectors.groupingBy(o -> o[0]));

带有空检查和空检查

Map<Object, List<Object[]>> map = objects.stream()
    .filter(o -> o != null && o.length != 0)
    .collect(Collectors.groupingBy(o -> o[0]));

例子

List<Object[]> objects = new ArrayList<>();
objects.add(new Object[] { 0, 1, 2, 3, 4, 5 });
objects.add(new Object[] { 1, 1, 2, 3, 4, 5 });
objects.add(new Object[] { 2, 1, 2, 3, 4, 5 });
objects.add(new Object[] { 0, 6, 7, 8, 9 });

Map<Object, List<Object[]>> map = objects.stream()
    .collect(Collectors.groupingBy(o -> o[0]));

System.out.println(map);

输出是这样的

{
    0 = [[Ljava.lang.Object;@378bf509,
            [Ljava.lang.Object;@5fd0d5ae],
    1 = [[Ljava.lang.Object;@2d98a335],
    2 = [[Ljava.lang.Object;@16b98e56]
}

您可以看到0 有两个List&lt;Object[]&gt; 值,按以下方式分组

【讨论】:

  • Collectors#groupingBy 实际上是一种不错且干净的方法。以前从未使用过它,但它似乎值得学习。
  • 您可以考虑使用过滤器.filter(Objects::nonNull) 来删除null 值。以防万一你不知道那个方法。
  • @Zabuza 是的,但我们也需要在这里过滤空数组
  • @alex 如果它回答了你的问题,请投票并接受这个答案
【解决方案2】:

我会让整个过程更加明确和干净。使用具有大量 cmets 和良好变量名的混合样式。

这对于阅读、理解和维护代码应该很有帮助。

Map<Object, List<Object[]>> convert(List<Object[]> entities) {
    Map<Object, List<Object[]>> idToEntitesWithSameId = new HashMap<>();

    entities.forEach(entity -> {
        // Create an entry for each entity,
        // merge with entities of same id
        Object id = entity[0];

        // Get current value or empty list
        List<Object[]> entitiesWithId = idToEntitesWithSameId
            .computeIfAbsent(id, ArrayList::new);

        // Add own entity, merge with other
        // entities of same id
        Arrays.stream(entity).forEach(entitiesWithId::add);
    });

    return idToEntitesWithSameId;
}

【讨论】:

    猜你喜欢
    • 2018-09-22
    • 1970-01-01
    • 2021-04-29
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    相关资源
    最近更新 更多