Java 8:groupingBy与关联对象的属性? [循环推断]

时间:2014-11-29 00:39:03

标签: java intellij-idea java-8

这就是Test的样子:

@Test
    public void testFunctional() 
    {
        final Member member = new Member("email", "memberExternalId", "clientId", "clientSecret");
        final Category foodCategory = new Category("Groceries", "Food");
        final Category utilityCategory = new Category("Internet", "utility");

        final List<Transaction> transactions = new ArrayList<>();
        {
            transactions.add(new Transaction("food1", new BigDecimal("10.00"), true, LocalDateTime.now(), member, foodCategory));
            transactions.add(new Transaction("food2", new BigDecimal("20.00"), true, LocalDateTime.now(), member, foodCategory));
        }
        {
            transactions.add(new Transaction("utility1", new BigDecimal("100.00"), true, LocalDateTime.now(), member, utilityCategory));
            transactions.add(new Transaction("utility2", new BigDecimal("200.00"), true, LocalDateTime.now(), member, utilityCategory));
        }

        final Map<String, List<BigDecimal>> groupByCategory = transactions.stream().collect(Collectors.groupingBy(Category::getGroupName));
    }

Category看起来像这样:

public class Category 
{
    @Id
    private String id;

    @Column(nullable = false)
    private String name;

    @Column(name = "group_name", nullable = false)
    private String groupName;

    @Column(name = "created_at")
    private LocalDateTime createdAt;
...
}

当我这样做时:

final Map<String, List<BigDecimal>> groupByCategory = transactions.stream().collect(Collectors.groupingBy(Category::getGroupName));

IntelliJ抱怨Cyclic Inference

我是第一次尝试这个Java 8功能而不确定是什么导致了这一点。

enter image description here

2 个答案:

答案 0 :(得分:5)

您的输入是List<Transaction>,您可以从中创建Stream<Transaction>。 当您将此Stream收集到Map时,您应该提供一个收集器,将每个Transaction映射到应在其下分组的密钥。

您希望TransactionGroupName Category的{​​{1}}进行分组。由于Transaction不是Category::getGroupName的方法,因此您无法在此处使用方法参考。相反,您可以使用lambda表达式:

Transaction

另请注意,此分组会生成final Map<String, List<Transaction>> groupByCategory = transactions.stream() .collect(Collectors.groupingBy(t -> t.getCategory().getGroupName())); ,而非Map<String, List<Transaction>>

答案 1 :(得分:3)

如果您想获得按类别分组的金额,那么您可以将groupingBy收藏家与mapping收藏家合并:

    Map<String, List<BigDecimal>> amountsByCategory = transactions.stream()
            .collect(Collectors.groupingBy(t -> t.getCategory().getGroupName(),
                     Collectors.mapping(Transaction::getAmount, 
                     Collectors.toList())));

还可以使用Collectors.reducing获得每组的总金额:

    Map<String, BigDecimal> totalAmountByCategory = transactions.stream()
            .collect(Collectors.groupingBy(t -> t.getCategory().getGroupName(),
                     Collectors.mapping(Transaction::getAmount, 
                     Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));