我有一个ArrayList
,一个Java的Collection类,如下所示:
ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
如您所见,animals
ArrayList
由3个bat
元素和一个owl
元素组成。我想知道Collection框架中是否有任何API返回bat
次出现的次数,或者是否有另一种方法来确定出现次数。
我发现Google的集合Multiset
确实有一个API,可以返回元素的总出现次数。但这只与JDK 1.5兼容。我们的产品目前是JDK 1.6,所以我不能使用它。
答案 0 :(得分:297)
我很确定收藏中的静态频率方法会派上用场:
int occurrences = Collections.frequency(animals, "bat");
无论如何我就是这样做的。我很确定这是jdk 1.6直接上升。
答案 1 :(得分:77)
在Java 8中:
Map<String, Long> counts =
list.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting()));
答案 2 :(得分:22)
这表明,Refer to objects by their interfaces一书中描述的“Effective Java”为何很重要。
如果您编写实现代码并使用ArrayList,比如代码中的50个位置,当您找到一个计算项目的好“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原则:继承,多态,抽象,封装。
答案 3 :(得分:11)
抱歉,没有简单的方法调用可以做到这一点。所有你需要做的就是创建一个地图并用它来计算频率。
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); }
}
答案 4 :(得分:10)
实际上,Collections类有一个静态方法叫做:频率(Collection c,Object o),它返回你要搜索的元素的出现次数,顺便说一句,这将完美地工作为你:
ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
System.out.println("Freq of bat: "+Collections.frequency(animals, "bat"));
答案 5 :(得分:9)
Java中没有本地方法可以帮助您。但是,您可以使用Apache Commons-Collections中的IterableUtils#countMatches()为您完成此操作。
答案 6 :(得分:8)
我想知道,为什么你不能将这个Google的Collection API与JDK 1.6一起使用。这样说吗?我认为你可以,不应该有任何兼容性问题,因为它是为较低版本而构建的。如果为1.6构建并且运行1.5,则情况会有所不同。
我错了吗?
答案 7 :(得分:6)
使用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);
}
输出:{Cat = 2,Goat = 1,Cow = 1,cow = 1,Dog = 1}
您可以注意到“Cow”和cow不被视为相同的字符串,如果您在相同的计数下需要它,请使用.toLowerCase()。请在下面找到相同的代码段。
Map<String, Long> couterMap = duplicateList.stream().collect(Collectors.groupingBy(e -> e.toString().toLowerCase(),Collectors.counting()));
输出:{cat = 2,cow = 2,goat = 1,dog = 1}
答案 8 :(得分:6)
稍微更有效的方法可能是
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();
}
答案 9 :(得分:6)
使用 Streams :
的替代 Java 8 解决方案long count = animals.stream().filter(animal -> "bat".equals(animal)).count();
答案 10 :(得分:5)
你想要的是一个袋子 - 它就像一个套装,但也计算出现次数。不幸的是java Collections框架 - 很棒,因为他们没有袋子impl。为此,必须使用Apache Common Collection link text
答案 11 :(得分:5)
直接从列表中获取对象:
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));
答案 12 :(得分:2)
如果您使用Eclipse Collections,则可以使用Bag
。可以通过调用MutableBag
从RichIterable
的任何实现中返回toBag()
。
MutableList<String> animals = Lists.mutable.with("bat", "owl", "bat", "bat");
MutableBag<String> bag = animals.toBag();
Assert.assertEquals(3, bag.occurrencesOf("bat"));
Assert.assertEquals(1, bag.occurrencesOf("owl"));
EC中的HashBag
实施由MutableObjectIntMap
支持。
注意:我是Eclipse Collections的提交者。
答案 13 :(得分:2)
要实现这一点,可以通过多种方式实现,即:
返回单个元素出现次数的方法:
Collections.frequency(animals, "bat");
Java 流:
过滤
animals.stream().filter("bat"::equals).count();
只是迭代想到列表
public static long manually(Collection<?> c, Object o){
int count = 0;
for(Object e : c)
if(e.equals(o))
count++;
return count;
}
创建频率图的方法:
Map<String, Long> counts =
animals.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Map<String, Long> map = new HashMap<>();
c.forEach(e -> map.merge(e, 1L, Long::sum));
手动
Map<String, Integer> mp = new HashMap<>();
animals.forEach(animal -> mp.compute(animal, (k, v) -> (v == null) ? 1 : v + 1));
包含所有方法的运行示例:
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Frequency {
public static int frequency(Collection<?> c, Object o){
return Collections.frequency(c, o);
}
public static long filter(Collection<?> c, Object o){
return c.stream().filter(o::equals).count();
}
public static long manually(Collection<?> c, Object o){
int count = 0;
for(Object e : c)
if(e.equals(o))
count++;
return count;
}
public static Map<?, Long> mapGroupBy(Collection<?> c){
return c.stream()
.collect(Collectors.groupingBy(Function.identity() , Collectors.counting()));
}
public static Map<Object, Long> mapMerge(Collection<?> c){
Map<Object, Long> map = new HashMap<>();
c.forEach(e -> map.merge(e, 1L, Long::sum));
return map;
}
public static Map<Object, Long> manualMap(Collection<?> c){
Map<Object, Long> map = new HashMap<>();
c.forEach(e -> map.compute(e, (k, v) -> (v == null) ? 1 : v + 1));
return map;
}
public static void main(String[] args){
List<String> animals = new ArrayList<>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
System.out.println(frequency(animals, "bat"));
System.out.println(filter(animals,"bat"));
System.out.println(manually(animals,"bat"));
mapGroupBy(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
mapMerge(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
manualMap(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
}
}
方法名称应该反映这些方法正在做什么,但是,我使用名称来反映正在使用的方法(鉴于在当前上下文中它是好的)。
答案 14 :(得分:2)
List<String> list = Arrays.asList("as", "asda", "asd", "urff", "dfkjds", "hfad", "asd", "qadasd", "as", "asda",
"asd", "urff", "dfkjds", "hfad", "asd", "qadasd" + "as", "asda", "asd", "urff", "dfkjds", "hfad", "asd",
"qadasd", "as", "asda", "asd", "urff", "dfkjds", "hfad", "asd", "qadasd");
方法1:
Set<String> set = new LinkedHashSet<>();
set.addAll(list);
for (String s : set) {
System.out.println(s + " : " + Collections.frequency(list, s));
}
方法2:
int count = 1;
Map<String, Integer> map = new HashMap<>();
Set<String> set1 = new LinkedHashSet<>();
for (String s : list) {
if (!set1.add(s)) {
count = map.get(s) + 1;
}
map.put(s, count);
count = 1;
}
System.out.println(map);
答案 15 :(得分:2)
Java 8 - 另一种方法
String searched = "bat";
long n = IntStream.range(0, animals.size())
.filter(i -> searched.equals(animals.get(i)))
.count();
答案 16 :(得分:1)
将arraylist的元素放在hashMap中以计算频率。
答案 17 :(得分:0)
List<String> lst = new ArrayList<String>();
lst.add("Ram");
lst.add("Ram");
lst.add("Shiv");
lst.add("Boss");
Map<String, Integer> mp = new HashMap<String, Integer>();
for (String string : lst) {
if(mp.keySet().contains(string))
{
mp.put(string, mp.get(string)+1);
}else
{
mp.put(string, 1);
}
}
System.out.println("=mp="+mp);
输出:
=mp= {Ram=2, Boss=1, Shiv=1}
答案 18 :(得分:0)
我不想让这个案例更难以使用两个迭代器 我有一个带LastName的HashMap - &gt;名字。并且我的方法应该删除具有dulicate FirstName的项目。
public static void removeTheFirstNameDuplicates(HashMap<String, String> map)
{
Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
Iterator<Map.Entry<String, String>> iter2 = map.entrySet().iterator();
while(iter.hasNext())
{
Map.Entry<String, String> pair = iter.next();
String name = pair.getValue();
int i = 0;
while(iter2.hasNext())
{
Map.Entry<String, String> nextPair = iter2.next();
if (nextPair.getValue().equals(name))
i++;
}
if (i > 1)
iter.remove();
}
}
答案 19 :(得分:0)
如果您是ForEach DSL的用户,则可以使用Count
查询完成此操作。
Count<String> query = Count.from(list);
for (Count<Foo> each: query) each.yield = "bat".equals(each.element);
int number = query.result();
答案 20 :(得分:0)
Map<String,Integer> hm = new HashMap<String, Integer>();
for(String i : animals) {
Integer j = hm.get(i);
hm.put(i,(j==null ? 1 : j+1));
}
for(Map.Entry<String, Integer> val : hm.entrySet()) {
System.out.println(val.getKey()+" occurs : "+val.getValue()+" times");
}
答案 21 :(得分:0)
package traversal;
import java.util.ArrayList;
import java.util.List;
public class Occurrance {
static int count;
public static void main(String[] args) {
List<String> ls = new ArrayList<String>();
ls.add("aa");
ls.add("aa");
ls.add("bb");
ls.add("cc");
ls.add("dd");
ls.add("ee");
ls.add("ee");
ls.add("aa");
ls.add("aa");
for (int i = 0; i < ls.size(); i++) {
if (ls.get(i) == "aa") {
count = count + 1;
}
}
System.out.println(count);
}
}
输出:4
答案 22 :(得分:0)
这样做是老式的方式并推动自己的方式:
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++);
}
答案 23 :(得分:0)
您可以将 Java 8 的 groupingBy 功能用于您的用例。
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Test {
public static void main(String[] args) {
List<String> animals = new ArrayList<>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
Map<String,Long> occurrenceMap =
animals.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
System.out.println("occurrenceMap:: " + occurrenceMap);
}
}
输出
occurrenceMap:: {bat=3, owl=1}
答案 24 :(得分:0)
Integer[] spam = new Integer[] {1,2,2,3,4};
List<Integer> list=Arrays.asList(spam);
System.out.println(list.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting())));
System.out.println(list.stream().collect(Collectors.groupingBy(Function.identity(),HashMap::new,Collectors.counting())));
输出
{1=1, 2=2, 3=1, 4=1}