当前位置: 首页 > 知识库问答 >
问题:

如何分组到数组映射中?

葛威
2023-03-14

流上的groupingBy操作是否可以生成一个映射,其中值是数组而不是列表或其他集合类型?

例如:我有一个类Thing。事物有所有者,所以Thing有一个getOwnerId方法。在一个事物流中,我想按所有者ID对事物进行分组,以便具有相同所有者ID的事物最终在一个数组中。换句话说,我想要一个像下面这样的映射,其中键是所有者ID,值是属于该所有者的事物数组。

    Map<String, Thing[]> mapOfArrays;

在我的例子中,因为我需要将映射值传递给一个需要数组的库方法,所以收集到一个< code >映射中是最方便的

将整个流收集到一个数组中很容易(甚至不需要显式收集器):

    Thing[] arrayOfThings = Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
            .toArray(Thing[]::new);

[属于所有者1,属于所有者2,属于所有者1]

通过所有者ID进行摸索也很容易。例如,要分组到列表中:

    Map<String, List<Thing>> mapOfLists = Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
            .collect(Collectors.groupingBy(Thing::getOwnerId));

{owner1=[屬於 owner1, 屬於 owner1], owner2=[屬於 owner2]}

只有这个例子给了我一个列表图。有2-arg和3-arg groupingBy方法可以提供其他集合类型(如集合)的映射。我想,如果我可以将收集到数组中的收集器(类似于上面第一个代码片段中收集到数组中的收集器)传递给two-arg Collectors

为了一个完整的示例,以下是我在上面片段中使用的类:

public class Thing {

    private String ownerId;

    public Thing(String ownerId) {
        this.ownerId = ownerId;
    }

    public String getOwnerId() {
        return ownerId;
    }

    @Override
    public String toString() {
        return "Belongs to " + ownerId;
    }

}

共有3个答案

法子昂
2023-03-14

可能很明显,但您可以通过以下方式完成:

Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
            .collect(Collectors.toMap(
                    Thing::getOwnerId,
                    x -> new Thing[]{x},
                    (left, right) -> {
                        Thing[] newA = new Thing[left.length + right.length];
                        System.arraycopy(left, 0, newA, 0, left.length);
                        System.arraycopy(right, 0, newA, left.length, right.length);
                        return newA;
                    }
            ))
詹弘毅
2023-03-14

您可以先分组,然后使用后续的toMap:

Map<String, Thing[]> result = source.stream()
                .collect(groupingBy(Thing::getOwnerId))
                .entrySet()
                .stream()
                .collect(toMap(Map.Entry::getKey,
                        e -> e.getValue().toArray(new Thing[0])));
百里疏珂
2023-03-14
匿名用户

使用Thomas Pliakas的这个答案中的收集器:

    Map<String, Thing[]> mapOfArrays = Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
            .collect(Collectors.groupingBy(Thing::getOwnerId,
                    Collectors.collectingAndThen(Collectors.toList(),
                            tl -> tl.toArray(new Thing[0]))));

想法是首先收集到一个列表中(这是一个明显的想法,因为数组有固定的大小),然后在返回到collector分组之前转换为一个数组。< code >收集然后可以通过其所谓的整理器来完成。

打印结果以供检查:

    mapOfArrays.forEach((k, v) -> System.out.println(k + '=' + Arrays.toString(v)));
owner1=[Belongs to owner1, Belongs to owner1]
owner2=[Belongs to owner2]

编辑:感谢Aomine的链接:使用< code>new Thing[0]作为< code>toArray的参数是受古人智慧阵列的启发。似乎在英特尔CPU上使用< code>new Thing[0]比使用< code>new Thing[tl.size()]要快。我很惊讶。

 类似资料:
  • 我试图将请求体从邮递员映射到spring boot实体,

  • 问题 你有一个对象数组,想把这些对象映射到另一个数组中,就像 Ruby 的映射一样。 解决方案 使用 map() 和匿名函数,但不要忘了还有列表推导。 electric_mayhem = [ { name: "Doctor Teeth", instrument: "piano" }, { name: "Janice", instrument: "lead g

  • 我正在尝试将我的对象[]数组映射并过滤到int[]数组。如果对象是int,效果很好,但如果不是int,则抛出强制转换异常。我想知道我是否可以在lambda表达式中附加一个try/catch?这是我的代码: 或者更好的方法是试着抓住整个街区?

  • 我有一个需要过滤的对象。 我需要输入“数据”,只有“isEnabled”为真的值的ID。

  • 问题内容: 我将Spring JPA与Hibernate和Postgres一起使用 在实体中,我尝试使用List和integer [] 在数据库中,我有一列类型: 有什么JPA使用方式吗? 问题答案: JPA无法直接将数组持久化到单独的表或数据库数组(例如,映射到的数组)。因此,您有两种方法: 1)用于将该列另存为BLOB或CLOB 2)使用而不是数组

  • 问题内容: 我有两个数组,一个带有url,一个带有内容。他们看起来像这样: 如何同时映射两个数组,并在新创建的元素中使用它们的值? 我需要使用我的reactplayer的url值和内容的值作为播放器下方的文本。 所以它应该看起来像这样: 这可能吗?更好的设置方法是什么? 问题答案: 使用的第二个参数(即当前元素的索引),可以访问第二个数组的正确元素。 如果您的项目中有其中一种库,那么这是该库中各种