Java 如何计算List中某个元素出现的次数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/505928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to count the number of occurrences of an element in a List
提问by MM.
I have an ArrayList
, a Collection class of Java, as follows:
我有一个ArrayList
,Java的Collection类,如下:
ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
As you can see, the animals
ArrayList
consists of 3 bat
elements and one owl
element. I was wondering if there is any API in the Collection framework that returns the number of bat
occurrences or if there is another way to determine the number of occurrences.
如您所见,animals
ArrayList
由 3 个bat
元素和 1 个owl
元素组成。我想知道 Collection 框架中是否有任何 API 可以返回出现次数,bat
或者是否有另一种方法来确定出现次数。
I found that Google's Collection Multiset
does have an API that returns the total number of occurrences of an element. But that is compatible only with JDK 1.5. Our product is currently in JDK 1.6, so I cannot use it.
我发现 Google 的 CollectionMultiset
确实有一个 API,可以返回元素出现的总次数。但这仅与 JDK 1.5 兼容。我们的产品目前在 JDK 1.6 中,所以我无法使用它。
回答by Kevin
There is no native method in Java to do that for you. However, you can use IterableUtils#countMatches()from Apache Commons-Collections to do it for you.
Java 中没有本机方法可以为您做到这一点。但是,您可以使用Apache Commons-Collections 中的IterableUtils#countMatches()来为您完成。
回答by Ray Hidayat
Sorry there's no simple method call that can do it. All you'd need to do though is create a map and count frequency with it.
抱歉,没有简单的方法调用可以做到这一点。您需要做的就是创建一个地图并用它计算频率。
HashMap<String,int> frequencymap = new HashMap<String,int>();
foreach(String a in animals) {
if(frequencymap.containsKey(a)) {
frequencymap.put(a, frequencymap.get(a)+1);
}
else{ frequencymap.put(a, 1); }
}
回答by mP.
What you want is a Bag - which is like a set but also counts the number of occurances. Unfortunately the java Collections framework - great as they are dont have a Bag impl. For that one must use the Apache Common Collection link text
你想要的是一个包——它就像一个集合,但也会计算出现的次数。不幸的是,java Collections 框架很棒,因为它们没有 Bag impl。为此,必须使用 Apache Common Collection链接文本
回答by Mark Renouf
So do it the old fashioned way and roll your own:
所以用老式的方式来做,然后自己动手:
Map<String, Integer> instances = new HashMap<String, Integer>();
void add(String name) {
Integer value = instances.get(name);
if (value == null) {
value = new Integer(0);
instances.put(name, value);
}
instances.put(name, value++);
}
回答by Adeel Ansari
I wonder, why you can't use that Google's Collection API with JDK 1.6. Does it say so? I think you can, there should not be any compatibility issues, as it is built for a lower version. The case would have been different if that were built for 1.6 and you are running 1.5.
我想知道,为什么您不能在 JDK 1.6 中使用 Google 的 Collection API。它是这样说的吗?我认为可以,应该没有任何兼容性问题,因为它是为较低版本构建的。如果它是为 1.6 构建的,而您正在运行 1.5,则情况会有所不同。
Am I wrong somewhere?
我有什么地方错了吗?
回答by Shamik
Put the elements of the arraylist in the hashMap to count the frequency.
将arraylist 的元素放入hashMap 中计算频率。
回答by Peter Lawrey
A slightly more efficient approach might be
一个稍微更有效的方法可能是
Map<String, AtomicInteger> instances = new HashMap<String, AtomicInteger>();
void add(String name) {
AtomicInteger value = instances.get(name);
if (value == null)
instances.put(name, new AtomicInteger(1));
else
value.incrementAndGet();
}
回答by OscarRyz
This shows, why it is important to "Refer to objects by their interfaces" as described in Effective Javabook.
这说明了为什么像Effective Java一书中描述的那样“通过接口引用对象”很重要。
If you code to the implementation and use ArrayList in let's say, 50 places in your code, when you find a good "List" implementation that count the items, you will have to change all those 50 places, and probably you'll have to break your code ( if it is only used by you there is not a big deal, but if it is used by someone else uses, you'll break their code too)
如果您对实现进行编码并在代码中的 50 个位置使用 ArrayList,当您找到一个很好的“列表”实现来计算项目时,您将不得不更改所有这 50 个位置,并且可能您必须破坏你的代码(如果它只被你使用,那没什么大不了的,但如果它被其他人使用,你也会破坏他们的代码)
By programming to the interface you can let those 50 places unchanged and replace the implementation from ArrayList to "CountItemsList" (for instance ) or some other class.
通过对接口编程,您可以让这 50 个位置保持不变,并将实现从 ArrayList 替换为“CountItemsList”(例如)或其他一些类。
Below is a very basic sample on how this could be written. This is only a sample, a production ready List would be muchmore complicated.
下面是一个关于如何编写它的非常基本的示例。这仅仅是一个样品,生产准备的清单将是很多更复杂。
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 principles applied here: inheritance, polymorphism, abstraction, encapsulation.
这里应用的面向对象原则:继承、多态、抽象、封装。
回答by akuhn
If you are a user of my ForEach DSL, it can be done with a Count
query.
如果您是我的ForEach DSL 的用户,则可以通过Count
查询来完成。
Count<String> query = Count.from(list);
for (Count<Foo> each: query) each.yield = "bat".equals(each.element);
int number = query.result();
回答by Lars Andren
I'm pretty sure the static frequency-method in Collections would come in handy here:
我很确定集合中的静态频率方法在这里会派上用场:
int occurrences = Collections.frequency(animals, "bat");
That's how I'd do it anyway. I'm pretty sure this is jdk 1.6 straight up.
反正我就是这样做的。我很确定这是 jdk 1.6 直接。