Вопрос-ответ

How to count the number of occurrences of an element in a List

Как подсчитать количество вхождений элемента в список

У меня есть ArrayList, класс коллекции Java, следующим образом:

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

Как вы можете видеть, animals ArrayList состоит из 3 bat элементов и одного owl элемента. Мне было интересно, есть ли какой-либо API в Collection Framework, который возвращает количество вхождений bat или есть другой способ определить количество вхождений.

Я обнаружил, что в коллекции Google Multiset есть API, который возвращает общее количество вхождений элемента. Но это совместимо только с JDK 1.5. Наш продукт в настоящее время находится в JDK 1.6, поэтому я не могу его использовать.

Переведено автоматически
Ответ 1

Я почти уверен, что статический частотный метод в коллекциях здесь пригодился бы:

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

Я бы в любом случае поступил именно так. Я почти уверен, что это jdk 1.6 в чистом виде.

Ответ 2

В Java 8:

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

Альтернативное решение для Java 8 с использованием потоков:

long count = animals.stream().filter(animal -> "bat".equals(animal)).count();
Ответ 4

Это показывает, почему важно "ссылаться на объекты по их интерфейсам", как описано в книге "Эффективная Java".

Если вы кодируете реализацию и используете ArrayList, скажем, в 50 местах своего кода, когда вы найдете хорошую реализацию "Списка", которая подсчитывает элементы, вам придется изменить все эти 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 arraylist collections