如何使用Java 8 Streams对对象属性进行分组并映射到另一个对象? [英] How to groupBy object properties and map to another object using Java 8 Streams?

查看:196
本文介绍了如何使用Java 8 Streams对对象属性进行分组并映射到另一个对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一组碰碰车,它们的侧面有大小,颜色和标识(汽车代码").

Suppose I have a group of bumper cars, which have a size, a color and an identifier ("car code") on their sides.

class BumperCar {
    int size;
    String color;
    String carCode;
}

现在,我需要将碰碰车映射到DistGroup对象的List,每个对象都包含属性sizecolor和汽车代码的List.

Now I need to map the bumper cars to a List of DistGroup objects, which each contains the properties size, color and a List of car codes.

class DistGroup {
    int size;
    Color color;
    List<String> carCodes;

    void addCarCodes(List<String> carCodes) {
        this.carCodes.addAll(carCodes);
    }
}

例如,

[
    BumperCar(size=3, color=yellow, carCode=Q4M),
    BumperCar(size=3, color=yellow, carCode=T5A),
    BumperCar(size=3, color=red, carCode=6NR)
]

应导致:

[
    DistGroup(size=3, color=yellow, carCodes=[ Q4M, T5A ]),
    DistGroup(size=3, color=red, carCodes=[ 6NR ])
]

我尝试了以下操作,实际上可以完成我想要的操作.但是问题在于,它实现了即时结果(生成为Map),而且我还认为可以一次完成(也许使用mappingcollectingAndThenreducing之类的方法),从而使结果更加优雅代码.

I tried the following, which actually does what I want it to do. But the problem is that it materializes the immediate result (into a Map) and I also think that it can be done at once (perhaps using mapping or collectingAndThen or reducing or something), resulting in more elegant code.

List<BumperCar> bumperCars = ...
Map<SizeColorCombination, List<BumperCar>> map = bumperCars.stream()
    .collect(groupingBy(t -> new SizeColorCombination(t.getSize(), t.getColor())));

List<DistGroup> distGroups = map.entrySet().stream()
    .map(t -> {
        DistGroup d = new DistGroup(t.getKey().getSize(), t.getKey().getColor());
        d.addCarCodes(t.getValue().stream()
            .map(BumperCar::getCarCode)
            .collect(toList()));
        return d;
    })
    .collect(toList());

如何在不使用变量的情况下立即获得期望的结果?

How can I get the desired result without using a variable for an immediate result?

编辑:如何在不实现即时结果的情况下获得期望的结果?我只是在寻找一种不会实现立即结果的方法,至少不会在表面上实现.这意味着我不想使用这样的东西:

How can I get the desired result without materializing the immediate result? I am merely looking for a way which does not materialize the immediate result, at least not on the surface. That means that I prefer not to use something like this:

something.stream()
    .collect(...) // Materializing
    .stream()
    .collect(...); // Materializing second time

当然,如果可能的话.

请注意,为简洁起见,我省略了getter和构造函数.您可能还假定equalshashCode方法已正确实现.另请注意,我正在使用SizeColorCombination用作分组依据密钥.此类显然包含属性sizecolor.也可以使用类似TuplePair的类,或表示两个任意值的组合的任何其他类.
编辑:还请注意,可以使用ol's skool for loop代替课程,但这不在此问题的范围内.

Note that I omitted getters and constructors for brevity. You may also assume that equals and hashCode methods are properly implemented. Also note that I'm using the SizeColorCombination which I use as group-by key. This class obviously contains the properties size and color. Classes like Tuple or Pair or any other class representing a combination of two arbitrary values may also be used.
Edit: Also note that an ol' skool for loop can be used instead of course, but that is not in the scope of this question.

推荐答案

如果我们假设DistGroup具有基于sizecolorhashCode/equals,则可以这样:

If we assume that DistGroup has hashCode/equals based on size and color, you could do it like this:

bumperCars
    .stream()
    .map(x -> {
        List<String> list = new ArrayList<>();
        list.add(x.getCarCode());
        return new SimpleEntry<>(x, list);
    })
    .map(x -> new DistGroup(x.getKey().getSize(), x.getKey().getColor(), x.getValue()))
    .collect(Collectors.toMap(
        Function.identity(),
        Function.identity(),
        (left, right) -> {
            left.getCarCodes().addAll(right.getCarCodes());
            return left;
        }))
    .values(); // Collection<DistGroup>

这篇关于如何使用Java 8 Streams对对象属性进行分组并映射到另一个对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆