首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Collections.frequency()的更高级版本

Collections.frequency()的更高级版本
EN

Stack Overflow用户
提问于 2015-02-24 23:03:37
回答 3查看 3.3K关注 0票数 6

那么,让我们想象一下,我有以下列表:

代码语言:javascript
复制
List<Foo> myList = getListFromSomePlace();
int frequency = Collections.frequency(myList, someFoo);

这将计算所有someFoo匹配元素。

但是,如果我有一个更“复杂”的版本:

代码语言:javascript
复制
List<Foo> myList = getListFromSomePlace();
int frequency = /* get number of Elements in the List whose getInternalFoo() match a certain value */

这样做的一种方法是覆盖Foo类中的equals方法,但我确实希望避免将自定义行为放在Foo类中,特别是因为我可能希望根据Foo类的不同属性获得频率,而且只能有一个版本的overriden equals方法。

Collections.sort这样的函数将允许我传递一个自定义比较器,它将完全满足我的需要,但是Collections.frequency没有提供这种功能。

使用Java8,我会使用一个流和一些Lambda表达式来解决这个问题,但是我想看看是否有一个简单的解决方案可以使用Java 7。我正在寻找的东西不是自己编写自定义频率方法,而是使用一些现有的API。有什么事吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-24 23:17:13

我不认为标准的JDK提供这一点(Java 7)。如果您想要一个与Java 7一起工作且不涉及编码的解决方案,您可以使用Guava及其Lists.transform方法。

看起来是这样的:

代码语言:javascript
复制
List<Foo> myList = getListFromSomePlace();
int frequency = Collections.frequency(Lists.transform(myList, new Function<Foo, MyObject>() {
    @Override
    public MyObject apply(Foo input) {
        return input.getInternalFoo();
    }
}), myCriteria); 

如果您仍然认为不值得为此添加第三方库,则仍然可以编写自己的函数接口,而提供将List<T>转换为List<U>的方法的实用程序类提供了要应用的映射。这并不难,而且不会占用那么多代码。

编写自己的实现将允许您在一次传递中完成此操作。

代码语言:javascript
复制
static <T, U> int frequency(Collection<T> coll, Function<? super T, ? extends U> mapper, U criteria) {
    Objects.requireNonNull(coll);
    Objects.requireNonNull(mapper);
    Objects.requireNonNull(criteria);
    int frequency = 0;
    for(T t : coll) {
        if(criteria.equals(mapper.apply(t))) {
            frequency++;
        }
    }
    return frequency;
}
票数 2
EN

Stack Overflow用户

发布于 2015-02-25 00:05:52

我认为你不能避免写你自己的方法。如果你不想污染你的API,就让它成为私有的。

代码语言:javascript
复制
public static <T> int frequency(Collection<T> c, T o, Comparator<T> comp) {
    int freq = 0;
    for(T e : c) {
        if(o == null ? e == null : comp.compare(o, e) == 0) {
            ++freq;
        }
    }
    return freq;
}
票数 6
EN

Stack Overflow用户

发布于 2015-02-25 04:12:59

只需根据您的要求,通过重写someFoo来“装饰”您的equals()

代码语言:javascript
复制
List<Foo> myList = getListFromSomePlace();
final Foo someFoo = getSomeFooToGetItsFrequency();

int frequency = Collections.frequency(myList, new Foo() {
    @Override
    public boolean equals(Object another) {
        if (another == someFoo) {
            return true;
        }
        if ((another == null) || (someFoo == null)) {
            return false;
        }
        if (another.getClass() != someFoo.getClass()) {
            return false;
        }
        Foo anotherFoo = (Foo) another;

        // Compare someFoo to anotherFoo as you wish here

        return comparisonResult;
    }
});

现在,这是因为Collections.frequency()实现检查对象参数是否equals()列表中的每个元素,而不是相反。如果后者为真,则返回的频率总是0

正如您提到的,您“可能希望根据Foo类的不同属性获取频率”,您可以将匿名内部类的equals()方法的第一部分移到一个通用抽象类中:

代码语言:javascript
复制
public abstract class ComplexFrequency<T> {

    private final T self;

    public ComplexFrequency(T self) {
        this.self = self;
    }

    @Override
    public boolean equals(Object another) {
        if (another == this.self) {
            return true;
        }
        if ((another == null) || (this.self == null)) {
            return false;
        }
        if (another.getClass() != this.self.getClass()) {
            return false;
        }

        // Let subclasses compare both objects
        return this.equals(this.self, (T) another);
    }

    protected abstract boolean equals(T self, T another);
}

然后,创建一个ComplexFrequency的子类,根据您的意愿进行比较:

代码语言:javascript
复制
public class FooComparingPropertyA extends ComplexFrequency<Foo> {

    public FooComparingPropertyA(Foo someFoo) {
        super(someFoo);
    }

    @Override
    protected boolean equals(Foo self, Foo another) {
        // check equality based on propertyA
    }
}

最后,使用这个子类“装饰”您的someFoo,并将“修饰”实例传递给Collections.frequency()

代码语言:javascript
复制
List<Foo> myList = getListFromSomePlace();
Foo someFoo = getSomeFooToGetItsFrequency();

int frequency = Collections.frequency(myList, new FooComparingPropertyA(someFoo));
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28708087

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档