You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java Streams按类型分组求和并计算类型间差值

Java Stream: Group by Type, Sum Quantities, Calculate Difference

Got it, let's break down how to solve this problem using Java Streams. You want to group your Sample objects by SampleTypeId, sum up the quantities for ADD and SUBTRACT types within each group, then compute the difference (I’m assuming that’s total ADD minus total SUBTRACT—adjust if needed!).

First, let’s define a simple Sample class to work with (I’ll include the enum for SampleType too):

class Sample {
    private int sampleId;
    private int sampleTypeId;
    private int sampleQuantity;
    private SampleType sampleType;

    // Constructor, getters, and toString (omitted for brevity)
    public enum SampleType { ADD, SUBTRACT }

    // Example constructor for testing
    public Sample(int sampleId, int sampleTypeId, int sampleQuantity, SampleType sampleType) {
        this.sampleId = sampleId;
        this.sampleTypeId = sampleTypeId;
        this.sampleQuantity = sampleQuantity;
        this.sampleType = sampleType;
    }

    // Getters
    public int getSampleTypeId() { return sampleTypeId; }
    public int getSampleQuantity() { return sampleQuantity; }
    public SampleType getSampleType() { return sampleType; }
}

Option 1: Concise One-Step Solution (Most Efficient)

This approach combines grouping and difference calculation into a single Stream operation. Instead of first summing each type separately, we treat SUBTRACT quantities as negative values and sum everything up directly:

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class SampleProcessor {
    public static void main(String[] args) {
        List<Sample> samples = List.of(
            new Sample(1, 1, 5, Sample.SampleType.ADD),
            new Sample(2, 1, 15, Sample.SampleType.ADD),
            new Sample(3, 1, 25, Sample.SampleType.ADD),
            new Sample(4, 1, 5, Sample.SampleType.SUBTRACT),
            new Sample(5, 1, 25, Sample.SampleType.SUBTRACT),
            new Sample(6, 2, 10, Sample.SampleType.ADD),
            new Sample(7, 2, 3, Sample.SampleType.SUBTRACT)
        );

        // Group by SampleTypeId, calculate ADD - SUBTRACT difference in one step
        Map<Integer, Integer> typeIdToDifference = samples.stream()
            .collect(Collectors.groupingBy(
                Sample::getSampleTypeId,
                Collectors.summingInt(sample -> 
                    sample.getSampleType() == Sample.SampleType.ADD 
                        ? sample.getSampleQuantity() 
                        : -sample.getSampleQuantity()
                )
            ));

        // Output the results
        typeIdToDifference.forEach((id, diff) -> 
            System.out.printf("SampleTypeId %d: Net Difference = %d%n", id, diff)
        );
    }
}

Output:

SampleTypeId 1: Net Difference = 15
SampleTypeId 2: Net Difference = 7

How it works:

  • For each Sample, we map its quantity to a positive value if it’s ADD, or a negative value if it’s SUBTRACT.
  • The summingInt collector then adds all these values together for each SampleTypeId group. The result is exactly (Total ADD) - (Total SUBTRACT).
  • This is the most efficient method because it only requires one pass through the Stream.

Option 2: Explicit Two-Step Approach (More Transparent)

If you prefer to first see the individual sums for ADD and SUBTRACT before calculating the difference, use this nested grouping approach:

// Step 1: Group by SampleTypeId, then by SampleType, summing quantities
Map<Integer, Map<Sample.SampleType, Integer>> typeIdToTypeSums = samples.stream()
    .collect(Collectors.groupingBy(
        Sample::getSampleTypeId,
        Collectors.groupingBy(
            Sample::getSampleType,
            Collectors.summingInt(Sample::getSampleQuantity)
        )
    ));

// Step 2: Calculate the difference for each SampleTypeId
Map<Integer, Integer> typeIdToDifference = typeIdToTypeSums.entrySet().stream()
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        entry -> {
            int addTotal = entry.getValue().getOrDefault(Sample.SampleType.ADD, 0);
            int subtractTotal = entry.getValue().getOrDefault(Sample.SampleType.SUBTRACT, 0);
            return addTotal - subtractTotal;
        }
    ));

How it works:

  • First, we create a nested map: SampleTypeId → SampleType → Total Quantity.
  • Then, we iterate over this nested map, using getOrDefault to handle cases where a group might not have any ADD or SUBTRACT entries (defaulting to 0 if missing).
  • This approach is more readable if you need to inspect the individual sums later, but it requires two passes through the data.

Handling Other Sample Types

If your SampleType enum has additional values you want to ignore, adjust the mapping function in Option 1 like this:

Collectors.summingInt(sample -> {
    if (sample.getSampleType() == Sample.SampleType.ADD) {
        return sample.getSampleQuantity();
    } else if (sample.getSampleType() == Sample.SampleType.SUBTRACT) {
        return -sample.getSampleQuantity();
    } else {
        return 0; // Ignore other types entirely
    }
})

内容的提问来源于stack exchange,提问作者user1778855

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:41:11