【问题标题】:Java 8 grouping by, counting and transforming to custom objectJava 8 分组、计数和转换为自定义对象
【发布时间】:2025-12-01 22:10:01
【问题描述】:

我有这个代码:

Map<List<Object>, Long> collector = root.getReports().stream().collect(
    Collectors.groupingBy(r -> Arrays.asList(i.X(), i.Y(), i.Z(), i.A()), Collectors.counting()));

for(Entry<Object, Long> entry : collector.entrySet())
    System.out.println(String.format("%s = %s", entry.getKey(), entry.getValue()));

这基本上产生了这个:

[16292, 141, 6, 100] = 2
[16288, 250, 59, 500] = 14
[16286, 250, 91, 50] = 4
[16287, 250, 91, 60] = 29
[16286, 250, 91, 80] = 10
[16293, 141, 6, 100] = 3
[16282, 079, 116, 50] = 9
...

我需要把这个结果放到一个自定义类中,这个:

@EqualsAndHashCode @ToString
public class CustomReport implements Serializable {
    private static final long serialVersionUID = 2074900904056768029L;

    @Getter @Setter
    private Integer x, y, z;
    
    @Getter @Setter
    private String a;

    @Getter @Setter
    private Long result;
}

有一种方法可以做到这一点,而无需遍历所有列表并手动执行?

【问题讨论】:

  • “手动”是什么意思?您必须编写将Entry&lt;List&lt;Object&gt;, Integer&gt; 映射到CustomReport 的代码。
  • 取决于您所说的“遍历所有列表并手动执行”。您将需要以某种方式循环收集器返回的entrySet,无论是在流中还是在 for 循环中,并且您需要手动分配每个变量。

标签: java collections java-8 java-stream


【解决方案1】:

不确定这是否是您想要的。但是您可以直接获取Map&lt;CustomReport, Long&gt;,而不是先创建Map&lt;List&lt;Object&gt;, Long&gt;,然后再通过它来将这些对象转换为您的目标类。

前提条件是CustomReport应该有equals()[1]和hashCode()[2]实现

那么你可以这样做:

root.getReports().stream().collect(
    Collectors.groupingBy(i -> new CustomReport(i.X(), i.Y(), i.Z(), i.A()), 
        HashMap::new,
        Collectors.counting()));

我假设CustomReport 也有一个兼容的构造函数。如果您必须使用 setter 进行初始化,则可以将分类器的第一个参数替换为:

i -> {
    CustomReport c = new CustomReport();
    c.setX(i.X());
    ...
    return c;
}

【讨论】:

    最近更新 更多