1

我想对java中的元素列表实现一个过滤器方法,这样我就可以根据我的过滤器去掉列表中的一些元素。而且,最重要的是,我希望将界面设计得尽可能简单。

这是我的实现:我创建了一个名为 EasierList 的类,在该类中,我添加了一个方法,其签名和实现如下所示:

public IEasierList<T> filter(ISelection<T> filter) {
    List<T> result = new ArrayList<T>();
    for(T item : mInternalList) {
        if(filter.accept(item)) {
            result.add(item);
        }
    }

    mInternalList = result;
    return new EasierList<T>(this);
}

至于 ISelection 界面,还是比较简单的:

public boolean accept(T obj);

所以,你可以看出,使用这个类的用户需要编写一些这样的代码来使用过滤器:

aEasierList.filter(new ISelection<T>() {
@Override
public boolean accept(T obj) {
        // some test
    return false;
}
});

我想知道是否有更好的方法来做到这一点,我的意思是让界面更容易使用?

提前致谢!

4

2 回答 2

5

两点:

首先,您不必重新发明轮子,您可以使用已经支持过滤转换集合和可迭代对象的Guava 。当然,这些方法是静态的,但您可以将它们用于标准或接口。ListCollectionIterable

其次,由于 Java 还不支持 lambda 表达式(计划用于 Java 8),冗长的匿名类是实现函数对象的唯一方法(如果您不想创建完整的命名类)。但是,您可以通过不就地实现匿名类,而是将其存储在静态字段中来帮助自己:

private static final Predicate<String> startsWithS = new Predicate<String>() {
    @Override public boolean apply(String string) {
        return string.startsWith("S");
    }
}

然后像这样使用它:

Collection<String> strings = ...
Collection<String> filtered = Collections2.filter(strings, startsWithS);

编辑:

应该提到更重要的事情:这些filtertransform方法不会创建独立于原始集合的新集合。他们创建的是一个“视图”,从技术上讲,它是一个代理对象,它指向原始集合,并在迭代、查询等期间懒惰地应用给定的Predicate或其元素。Function

这有时很方便,但您必须记住,为了获得一个独立于原始集合(当然不是深度)的新集合,您需要将它传递给新集合的构造函数(或工厂)收藏。

List<String> filteredList =
    new ArrayList<>(Collections2.filter(strings, startsWithS));

顺便说一句,这可能是一个使用静态导入来filter稍微减少冗长的方法的好时机。

于 2012-04-18T00:13:11.500 回答
3

我认为这是您在本机 Java 中可以做到的最好的事情,而无需求助于支持闭包的替代 JVM 语言(Groovy、Scala)。

Commons Collections 实现了基本相同的模式——查看CollectionUtils.filter和的文档Predicate。唯一的缺点是它不支持泛型。

http://commons.apache.org/collections/apidocs/org/apache/commons/collections/CollectionUtils.html

因此,如果您要走这条路,您不妨使用已经编写和测试过的东西。

C# 也通过 LINQ 和扩展方法很好地解决了这种模式,这使得类似于上述filter方法的东西看起来像是属于Collection自己的。

于 2012-04-18T00:16:06.263 回答