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

如何使用Java Stream筛选对象列表中属性求和符合条件的子列表

嘿,这两个关于Java Stream处理子集求和的问题我很熟悉,给你一步步拆解,附上代码示例和说明:

问题1:获取对象属性求和≤阈值的子列表

首先得明确:你要的是连续的子列表还是任意组合的非连续子集?两种场景的实现方式略有不同,我都给你列出来:

场景1:连续子列表

假设我们有一个带数值属性的Item类,先定义示例类:

class Item {
    private int value;
    // 构造器和Getter
    public Item(int value) { this.value = value; }
    public int getValue() { return value; }
}

接下来用Stream生成所有可能的连续子列表,筛选出属性求和≤阈值的:

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class StreamSubListExample {
    public static void main(String[] args) {
        List<Item> items = Arrays.asList(new Item(2), new Item(3), new Item(1), new Item(4));
        int threshold = 5;

        List<List<Item>> validSubLists = IntStream.range(0, items.size())
                .boxed()
                // 对每个起始索引,生成所有可能的结束索引
                .flatMap(start -> IntStream.rangeClosed(start, items.size())
                        .boxed()
                        .map(end -> items.subList(start, end))
                        // 筛选求和≤阈值的子列表,排除空列表
                        .filter(subList -> !subList.isEmpty() 
                                && subList.stream().mapToInt(Item::getValue).sum() <= threshold)
                )
                .collect(Collectors.toList());

        // 打印结果验证
        validSubLists.forEach(sub -> System.out.println(sub.stream().map(Item::getValue).toList()));
    }
}

这段代码的逻辑很直观:用IntStream遍历所有起始位置,再对每个起始位置遍历结束位置,截取子列表后计算属性和,符合条件的就收集起来。

场景2:任意非连续子集

如果需要的是任意组合的子集(不要求连续),可以先通过Stream生成所有可能的子集,再筛选符合条件的:

List<List<Item>> allSubsets = items.stream()
        .reduce(new ArrayList<>(Collections.singletonList(new ArrayList<>())),
                (subsets, item) -> {
                    List<List<Item>> newSubsets = new ArrayList<>(subsets);
                    // 对现有每个子集,添加当前元素生成新子集
                    subsets.forEach(subset -> {
                        List<Item> newSubset = new ArrayList<>(subset);
                        newSubset.add(item);
                        newSubsets.add(newSubset);
                    });
                    return newSubsets;
                },
                (a, b) -> { a.addAll(b); return a; });

// 筛选非空且求和≤阈值的子集
List<List<Item>> validSubsets = allSubsets.stream()
        .filter(subset -> !subset.isEmpty())
        .filter(subset -> subset.stream().mapToInt(Item::getValue).sum() <= threshold)
        .collect(Collectors.toList());

⚠️ 注意:这种方法的时间复杂度是O(2^n),如果列表元素很多的话会有性能问题,适合小数据量场景;大数据量建议用动态规划优化。

问题2:获取QuestionMarks求和等于指定值的子列表

这个问题和问题1本质是一样的,只是筛选条件从"≤阈值"改成"等于目标值",我们直接用Question类来实现:

首先定义Question类:

class Question {
    private String questionId;
    private int questionMarks;
    // 构造器和Getter
    public Question(String questionId, int questionMarks) {
        this.questionId = questionId;
        this.questionMarks = questionMarks;
    }
    public int getQuestionMarks() { return questionMarks; }
    public String getQuestionId() { return questionId; }
}

场景1:连续子列表

List<Question> questions = Arrays.asList(
        new Question("Q1", 2),
        new Question("Q2", 3),
        new Question("Q3", 1),
        new Question("Q4", 4)
);
int targetSum = 5;

List<List<Question>> validContinuousSubLists = IntStream.range(0, questions.size())
        .boxed()
        .flatMap(start -> IntStream.rangeClosed(start, questions.size())
                .boxed()
                .map(end -> questions.subList(start, end))
                .filter(subList -> !subList.isEmpty() 
                        && subList.stream().mapToInt(Question::getQuestionMarks).sum() == targetSum)
        )
        .collect(Collectors.toList());

场景2:任意非连续子集

List<List<Question>> allQuestionSubsets = questions.stream()
        .reduce(new ArrayList<>(Collections.singletonList(new ArrayList<>())),
                (subsets, q) -> {
                    List<List<Question>> newSubsets = new ArrayList<>(subsets);
                    subsets.forEach(subset -> {
                        List<Question> newSubset = new ArrayList<>(subset);
                        newSubset.add(q);
                        newSubsets.add(newSubset);
                    });
                    return newSubsets;
                },
                (a, b) -> { a.addAll(b); return a; });

List<List<Question>> validQuestionSubsets = allQuestionSubsets.stream()
        .filter(subset -> !subset.isEmpty())
        .filter(subset -> subset.stream().mapToInt(Question::getQuestionMarks).sum() == targetSum)
        .collect(Collectors.toList());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:10:42