我有一个数组列表,一个Java的集合类,如下所示:
ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
如您所见,animals数组列表由3个bat元素和1个owl元素组成。我想知道在Collection框架中是否有返回蝙蝠出现次数的API,或者是否有另一种方法来确定出现次数。
我发现谷歌的集合Multiset确实有一个API,返回一个元素的总出现次数。但是这只与JDK 1.5兼容。我们的产品目前是JDK 1.6,所以我不能使用它。
这说明了为什么像《Effective Java》一书中描述的那样“通过接口引用对象”是很重要的。
如果你对实现进行编码,并在代码中的50个地方使用ArrayList,当你找到一个好的“List”实现来计数项目时,你将不得不改变所有这50个地方,可能你将不得不破坏你的代码(如果它只被你使用,这不是一个大问题,但如果它被其他人使用,你也会破坏他们的代码)
通过对接口编程,您可以让这50个位置保持不变,并将实现从ArrayList替换为“CountItemsList”(例如)或其他一些类。
下面是一个关于如何编写这些代码的非常基本的示例。这只是一个样品,一个生产就绪的清单将更加复杂。
import java.util.*;
public class CountItemsList<E> extends ArrayList<E> {
// This is private. It is not visible from outside.
private Map<E,Integer> count = new HashMap<E,Integer>();
// There are several entry points to this class
// this is just to show one of them.
public boolean add( E element ) {
if( !count.containsKey( element ) ){
count.put( element, 1 );
} else {
count.put( element, count.get( element ) + 1 );
}
return super.add( element );
}
// This method belongs to CountItemList interface ( or class )
// to used you have to cast.
public int getCount( E element ) {
if( ! count.containsKey( element ) ) {
return 0;
}
return count.get( element );
}
public static void main( String [] args ) {
List<String> animals = new CountItemsList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
System.out.println( (( CountItemsList<String> )animals).getCount( "bat" ));
}
}
这里应用的OO原则:继承、多态、抽象、封装。
使用Java 8特性在数组中查找字符串值的简单方法。
public void checkDuplicateOccurance() {
List<String> duplicateList = new ArrayList<String>();
duplicateList.add("Cat");
duplicateList.add("Dog");
duplicateList.add("Cat");
duplicateList.add("cow");
duplicateList.add("Cow");
duplicateList.add("Goat");
Map<String, Long> couterMap = duplicateList.stream().collect(Collectors.groupingBy(e -> e.toString(),Collectors.counting()));
System.out.println(couterMap);
}
输出:{猫=2,山羊=1,牛=1,牛=1,狗=1}
你可以注意到“Cow”和“Cow”不被认为是相同的字符串,如果你需要它在相同的计数下,使用. tolowercase()。请在下面找到相同的片段。
Map<String, Long> couterMap = duplicateList.stream().collect(Collectors.groupingBy(e -> e.toString().toLowerCase(),Collectors.counting()));
输出:{猫=2,牛=2,山羊=1,狗=1}
直接从列表中获取对象的出现次数:
int noOfOccurs = Collections.frequency(animals, "bat");
要在列表中获取Object集合的出现情况,重写Object类中的equals方法如下:
@Override
public boolean equals(Object o){
Animals e;
if(!(o instanceof Animals)){
return false;
}else{
e=(Animals)o;
if(this.type==e.type()){
return true;
}
}
return false;
}
Animals(int type){
this.type = type;
}
调用Collections.frequency为:
int noOfOccurs = Collections.frequency(animals, new Animals(1));