所以,让我们假设我有以下列表:
List<Foo> myList = getListFromSomePlace();
int frequency = Collections.frequency(myList, someFoo);
这会计算所有someFoo
个匹配元素。
但是,如果我有一个更“复杂”的版本:
List<Foo> myList = getListFromSomePlace();
int frequency = /* get number of Elements in the List whose getInternalFoo() match a certain value */
这样做的一种方法是覆盖Foo类中的equals
方法,但我真的想避免在Foo类中放置自定义行为,特别是因为我可能想要根据不同的频率获取频率来自Foo类的属性,我只能有一个版本的覆盖equals
方法。
像Collections.sort
这样的函数可以让我传递一个自定义Comparator,它将完全符合我的需要,但Collections.frequency不提供这个功能。
使用Java8,我会使用一个流和一些Lambda表达式来解决这个问题,但我想看看是否有一个可以与Java 7一起使用的简单解决方案。我正在寻找一些不涉及编码的东西我自己的自定义频率方法,但使用一些现有的API。有东西吗?
答案 0 :(得分:6)
我认为你不能避免编写自己的方法。如果您不想污染您的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;
}
答案 1 :(得分:3)
装饰&#39;根据您的要求覆盖someFoo
来equals()
:
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()
方法的第一部分移动到通用抽象类:
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
的子类,可以根据需要进行比较:
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
}
}
最后,&#39;装饰&#39;您的someFoo
使用此子类并通过“装饰”#39;实例到Collections.frequency()
:
List<Foo> myList = getListFromSomePlace();
Foo someFoo = getSomeFooToGetItsFrequency();
int frequency = Collections.frequency(myList, new FooComparingPropertyA(someFoo));
答案 2 :(得分:2)
我不认为标准的JDK提供了这个(Java&lt; = 7)。如果您想要一个适用于Java 7并且不涉及编码的解决方案,您可以使用Guava及其Lists.transform
方法。
它看起来像这样:
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);
如果您仍然认为不值得为此添加第三方库,您仍然可以编写自己的Function接口,以及提供将List<T>
转换为{的方法的实用程序类。 {1}}提供了要应用的映射。它不是很难,也不会占用太多代码。
编写自己的实现将允许您一次性完成此操作。
List<U>