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

Java Collections.frequency()的更高级版本,java,collections,Java,Collections,那么,让我们假设我有以下列表: List<Foo> myList = getListFromSomePlace(); int frequency = Collections.frequency(myList, someFoo); 一种方法是重写Foo类中的equals方法,但我确实希望避免将自定义行为放入Foo类中,特别是因为我可能希望根据Foo类的不同属性获取频率,并且我只能有一个版本的重写equals方法 类似于Collections.sort的函数将允许我传递一个自定义比较器

那么,让我们假设我有以下列表:

List<Foo> myList = getListFromSomePlace();
int frequency = Collections.frequency(myList, someFoo);
一种方法是重写Foo类中的
equals
方法,但我确实希望避免将自定义行为放入Foo类中,特别是因为我可能希望根据Foo类的不同属性获取频率,并且我只能有一个版本的重写
equals
方法

类似于
Collections.sort
的函数将允许我传递一个自定义比较器,该比较器将完全满足我的需要,但Collections.frequency不提供此功能


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

我不认为标准JDK提供了这一点(Java我不认为您可以避免编写自己的方法。如果您不想污染API,请将其设置为私有

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;
}
公共静态整数频率(采集c、TO、比较器补偿){
intfreq=0;
对于(TE:c){
如果(o==null?e==null:comp.compare(o,e)==0){
++频率;
}
}
返回频率;
}

根据您的要求,通过覆盖
equals()
来“装饰”您的
someFoo

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;
    }
});
然后,创建一个子类
ComplexFrequency
,根据需要进行比较:

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
    }
}

“此外,此技术还需要对列表进行两次迭代。一次用于应用映射,另一次用于检查频率。”这是错误的;转换是惰性地完成的,只会在频率实现的循环过程中完成。@LouisWasserman哦,是的,你完全正确;谢谢剩余部分。我选择这个答案作为“正确答案”但是,其他两个答案也给出了有趣的方法。我选择这一个是因为Guava转换允许实现与我所寻找的最相似的实现,特别是因为它不涉及任何
黑客
代码复制
或更多的
样板代码
。然而,这并不意味着它必须是最适合每个人或任何情况的解决方案…@Martin是的,如果使用流API,这基本上是最接近的翻译;
int frequency=myList.Stream().map(Foo::getInternalFoo.filter(myCriteria::equals).count()
。然而,我确实喜欢使用
比较器的答案;这也很好。同意,这不像
频率()
是一种复杂的方法。
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;
}
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;
    }
});
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);
}
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
    }
}
List<Foo> myList = getListFromSomePlace();
Foo someFoo = getSomeFooToGetItsFrequency();

int frequency = Collections.frequency(myList, new FooComparingPropertyA(someFoo));