Как посчитать количество вхождений элемента в список - PullRequest
155 голосов
/ 03 февраля 2009

У меня есть 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, который возвращает количество bat вхождений или есть другой способ определить количество вхождений.

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

Ответы [ 21 ]

300 голосов
/ 17 марта 2010

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

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

Вот так я и сделаю. Я уверен, что это JDK 1.6.

79 голосов
/ 29 ноября 2014

В Java 8:

Map<String, Long> counts =
    list.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting()));
22 голосов
/ 04 февраля 2009

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

Если вы кодируете реализацию и используете 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" ));
    }
}

Применяемые здесь ОО-принципы: наследование, полиморфизм, абстракция, инкапсуляция.

11 голосов
/ 03 февраля 2009

Извините, нет простого вызова метода, который может это сделать. Все, что вам нужно сделать, это создать карту и рассчитывать частоту с ней.

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); }
}
10 голосов
/ 14 февраля 2015

На самом деле, в классе Collections есть статический метод, который называется: частота (Коллекция c, Объект 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"));
9 голосов
/ 03 февраля 2009

В Java нет нативного метода сделать это за вас. Однако вы можете использовать IterableUtils # countMatches () из Apache Commons-Collections, чтобы сделать это за вас.

8 голосов
/ 03 февраля 2009

Интересно, почему вы не можете использовать этот API Google Collection с JDK 1.6. Так ли это? Я думаю, что вы можете, не должно быть никаких проблем с совместимостью, поскольку он построен для более низкой версии. Случай был бы другим, если бы он был построен для 1.6, а вы используете 1.5.

Я где-то ошибаюсь?

6 голосов
/ 04 февраля 2016

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

long count = animals.stream().filter(animal -> "bat".equals(animal)).count();
6 голосов
/ 14 ноября 2017

Простой способ найти вхождение строкового значения в массив с использованием функций 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}

Вы можете заметить, что «Корова» и «корова» не считаются одной и той же строкой. Если вам требуется ее с тем же количеством, используйте .toLowerCase (). Пожалуйста, найдите фрагмент ниже для того же.

Map<String, Long> couterMap = duplicateList.stream().collect(Collectors.groupingBy(e -> e.toString().toLowerCase(),Collectors.counting()));

Выход: {кошка = 2, корова = 2, коза = 1, собака = 1}

6 голосов
/ 04 февраля 2009

Немного более эффективный подход может быть

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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...