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));