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

如何基于谓词创建Java实时子集合?

背景

我有一个接口:

public interface ThingRegistry {

    public Set<Thing> getAllThings();
    public Set<Thing> getAllThingsWithProperty(String property);
}

以及对应的实现类:

public class MemoryThingRegistry implements ThingRegistry {
    private final Set<Thing> things = new HashSet<>();

    public Set<Thing> getAllThings() {
        return Collections.unmodifiableSet(this.things);
    }

    public Set<Thing> getAllThingsWithProperty(final String property) {
        return this.things.stream().filter((thing) -> thing.hasProperty(property)).collect(Collectors.toUnmodifiableSet());
    }
}
问题
  • getAllThings()返回的Set会同步注册表内的变更
  • 但getAllThingsWithProperty()返回的Set无法同步这些变更
需求

能否使用Java标准库或常用第三方库,让getAllThingsWithProperty()返回一个“实时”子Set?即它基于原Set,每次访问时重新应用Predicate过滤?最好能适用于任意Collection(我另有一个用List的Registry接口)。我知道可以自定义Set实现,但希望避免这么做。


解决方案

1. 使用Guava库(推荐)

Guava提供的Sets.filter()(List场景对应Lists.filter())可以生成实时过滤的集合视图,该视图会在每次访问时自动对原集合应用过滤条件,原集合的增删改操作会实时反映到视图中。

修改后的实现代码:

import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.function.Predicate;

public class MemoryThingRegistry implements ThingRegistry {
    private final Set<Thing> things = new HashSet<>();

    @Override
    public Set<Thing> getAllThings() {
        return Collections.unmodifiableSet(things);
    }

    @Override
    public Set<Thing> getAllThingsWithProperty(final String property) {
        Predicate<Thing> propertyPredicate = thing -> thing.hasProperty(property);
        // 生成实时过滤视图后,包装为不可变集合防止外部修改
        return Collections.unmodifiableSet(Sets.filter(things, propertyPredicate));
    }
}

对于List类型的Registry,只需将Sets.filter()替换为Lists.filter()即可,逻辑完全一致。

2. 使用Apache Commons Collections

Apache Commons Collections的FilteredSet(List场景对应FilteredList)也支持创建实时过滤的集合视图,用法如下:

import org.apache.commons.collections4.set.FilteredSet;
import java.util.Collections;
import java.util.function.Predicate;

public class MemoryThingRegistry implements ThingRegistry {
    private final Set<Thing> things = new HashSet<>();

    @Override
    public Set<Thing> getAllThings() {
        return Collections.unmodifiableSet(things);
    }

    @Override
    public Set<Thing> getAllThingsWithProperty(final String property) {
        Predicate<Thing> propertyPredicate = thing -> thing.hasProperty(property);
        // 创建实时过滤的Set视图,再包装为不可变
        return Collections.unmodifiableSet(FilteredSet.filteredSet(things, propertyPredicate::test));
    }
}

3. Java标准库的折中方案

Java标准库本身没有提供直接的实时过滤集合视图,如果不想引入第三方库,只能采用两种折中方式:

  • 保持原实现,每次调用getAllThingsWithProperty()时重新过滤生成新集合,但无法实现“实时同步”
  • 提供返回Stream<Thing>的方法,让调用方自行处理过滤逻辑,但不符合返回Set的需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:07:28