如何计算List中元素的出现次数

问题

我有一个ArrayList,一个Java的Collection类,如下所示:

ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");

如你所见,animals``ArrayList包含3bat个元素和一个owl元素。我想知道Collection框架中是否有任何API返回数量为2656537184的出现次数,或者是否有另一种方法来确定出现次数。

我发现Google的CollectionMultiset有一个API,可以返回元素的总出现次数。但这只与JDK 1.5兼容。我们的产品目前是JDK 1.6,所以我不能使用它。


#1 热门回答(276 赞)

我很确定Collections中的静态频率方法会派上用场:

int occurrences = Collections.frequency(animals, "bat");

无论如何我就是这样做的。我很确定这是jdk 1.6直线上升。


#2 热门回答(59 赞)

在Java 8中:

Map<String, Long> counts =
    list.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting()));

#3 热门回答(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原则:继承,多态,抽象,封装。