2010-04-15 5 views
5

У меня есть java.util.ArrayList<Item> и объект Item.Подсчет количества экземпляров в ArrayList

Теперь я хочу получить количество раз, которое Item хранится в архиваторе.

Я знаю, что могу сделать arrayList.contains() проверить, но он возвращает true, независимо от того, содержит ли он один или несколько Item s.

Q1. Как я могу найти количество времени, в течение которого элемент хранится в списке?

Q2. Кроме того, если список содержит более одного элемента, то как я могу определить индекс других элементов, потому что arrayList.indexOf(item) возвращает индекс только первого элемента каждый раз?

+0

ли Пункт переопределение равно и хэш-код? Им нужно. –

+0

Почему бы вам не расширить класс ArrayList, чтобы добавить необходимые дополнительные функции? Вот почему OOP существует;) Q1 можно легко сделать, выполнив счетчик для каждого уникального элемента в списке и увеличивая его каждый раз, когда уже добавленный элемент добавлен. –

ответ

5

Это легко сделать вручную.

public int countNumberEqual(ArrayList<Item> itemList, Item itemToCheck) { 
    int count = 0; 
    for (Item i : itemList) { 
     if (i.equals(itemToCheck)) { 
      count++; 
     } 
    } 
    return count; 
} 

Имейте в виду, что если вы не отменяют equals в вашем Item классе, этот метод будет использовать идентификатор объекта (как это реализация Object.equals()).

Редактировать: Что касается вашего второго вопроса (пожалуйста, постарайтесь ограничить посты на один вопрос за штуку), вы можете сделать это и вручную.

public List<Integer> indices(ArrayList<Item> items, Item itemToCheck) { 
    ArrayList<Integer> ret = new ArrayList<Integer>(); 
    for (int i = 0; i < items.size(); i++) { 
     if (items.get(i).equals(itemToCheck)) { 
      ret.add(i); 
     } 
    } 
    return ret; 
} 
+0

Есть ли какой-либо другой более эффективный метод, потому что мой список содержит тысячи элементов, а конкретный элемент можно дублировать не более 4 или 5 раз. Поэтому я считаю, что не стоит сравнивать эти тысячи предметов, чтобы найти эти 4 или 5 дубликатов. Пожалуйста, не предлагайте мне использовать 'Set', потому что есть веская причина не использовать Set в моем случае. –

+1

Подумайте о том, что для подсчета предметов вам понадобится ANYWAY, чтобы пройти весь список, так как вам нужно будет проверить их все, чтобы узнать точное количество. – Jack

+1

Если вы хотите что-то с более низкой временной сложностью, вам не повезло - ничего не зная о содержании вашего списка, вы должны проверить каждую позицию. Одна оптимизация заключается в сравнении «hashCode» вашего элемента с «hashCode» каждого элемента в Списке, но если они равны, вы все равно должны проверять равенство с помощью 'equals()', так как ваша хеш-функция может иметь коллизии. Если вы проверяете только идентификатор объекта, нет необходимости делать это, так как «equals» будет сравнивать адреса памяти или что-то подобное. – danben

22

Вы можете использовать Collections класса:

public static int frequency(Collection<?> c, Object o) 

Возвращает количество элементов в указанной коллекции, равных указанный объект. Более формально возвращает число элементов e в коллекции так, что (o == null? E == null: o.equals (e)).

Если вам нужно подсчитать occurencies длинного списка много раз я предлагаю вам использовать HashMap хранить счетчики и обновлять их при вставке новых элементов в список. Это позволит избежать вычисления каких-либо счетчиков .. но, конечно, у вас не будет индексов.

HashMap<Item, Integer> counters = new HashMap<Item, Integer>(5000); 
ArrayList<Item> items = new ArrayList<Item>(5000); 

void insert(Item newEl) 
{ 
    if (counters.contains(newEl)) 
    counters.put(newEl, counters.get(newEl)+1); 
    else 
    counters.put(newEl, 1); 

    items.add(newEl); 
} 

Окончательного намек: Вы можете использовать другие коллекции рамок (как Apache Collections) и использовать Bag структуру данных, которая описывается как

Определяет коллекцию, которая подсчитывает количество раз объект появляется в коллекция.

Так именно то, что вам нужно ..

+2

wow никогда не знал об этом методе. Javadoc находится здесь: http://java.sun.com/javase/6/docs/api/java/util/Collections.html#frequency%28java.util.Collection,%20java.lang.Объект% 29 –

+0

Ваш первый метод больше подходит для моей потребности. Но есть одна проблема. Если я нашел более одного элемента в списке, то как получить эти другие элементы из списка? –

+2

Если они равны, зачем их искать? Вы уже знаете, что внутри! Или есть поля, которые не входят в сравнение 'equals'? Или вы хотите сделать больше, чем просто извлечь, например, удалить? –

0

Как остальные респонденты уже говорили, если вы твердо привержены хранить ваши вещи в неупорядоченном ArrayList, то подсчет элементов будет принимать O (п) , где n - количество элементов в списке. Здесь, в SO, мы даем советы, но мы не делаем волшебство!

Как я только что намекнул, если список будет искаться намного больше, чем он будет изменен, может иметь смысл его сортировать.Если ваш список отсортирован, вы можете найти свой элемент в O (log n) времени, что намного быстрее; и если у вас есть реализация hashcode, которая хорошо сочетается с вашим equals, все одинаковые элементы будут расположены рядом друг с другом.

Другая возможность - создать и поддерживать две структуры данных параллельно. Вы можете использовать HashMap, содержащий ваши элементы в качестве ключей, и их количество в качестве значений. Вы должны были бы обновить эту вторую структуру каждый раз, когда ваш список изменится, но поиск количества элементов будет o (1).

0

Я могу ошибаться, но мне кажется, как структуры данных, вы на самом деле хотите может быть Multiset (от google-collections/guava), а не List. Он позволяет использовать кратные, в отличие от Set, но на самом деле не заботится о заказе. Учитывая это, у него есть метод int count(Object element), который делает именно то, что вы хотите. И поскольку это не список и имеет реализации, поддерживаемые HashMap, получение счета значительно более эффективно.

0

Спасибо за ваше замечательное предложение. Но этот ниже код действительно очень полезен, поскольку у нас нет какого-либо метода поиска со списком, который может дать количество случаев.

void insert(Item newEl) 
{ 
    if (counters.contains(newEl)) 
    counters.put(newEl, counters.get(newEl)+1); 
    else 
    counters.put(newEl, 1); 

    items.add(newEl); 
} 

Благодаря Джеку. Хорошая публикация.

Спасибо,

Бинод Суман

http://binodsuman.blogspot.com

Смежные вопросы