Как поддерживать упорядоченный связанный список и добавлять, удалять элементы в java

Я хочу вести список объектов с именем «ClientStatus», которые не содержат ничего, кроме идентификации клиента (id) и некоторого поля времени, т.е. связанного с этим клиентом. Этот список должен быть отсортирован по этому полю времени в порядке возрастания. Операции, которые я хочу поддержать:

* peek and remove an entry from the beginning 
* Search the list for an entry and if found, remove it
* Add an entry to this list

Я ожидаю, что каждая новая запись будет иметь время >= последней записи в списке, но есть вероятность состояния гонки, когда я могу выйти из строя значений порядка. Поэтому я решил, что итерация по списку с конца будет наиболее эффективным решением с точки зрения времени.

Это DS, которые я использовал:

  • LinkedList и ListIterator as ListIterator позволяют перебирать элементы с конца и добавлять новые записи во время итерации. Но код выглядит грязно:

    Скажем, в моем списке есть значения: 2 3 6 7 9, и я хочу добавить 5

    ListIterator<Integer> it = list.listIterator(list.size());
    
    while (it.hasPrevious()) {
        if (it.previous().intValue() <= 5) {    
            it.next();
            break;
        }
    }
    

    Есть лучший способ сделать это?

  • Я также пытался использовать LinkedList и Dequeue, но итератор по убыванию не позволяет добавлять/удалять записи. Я пытался подсчитать индексы, но затем set(index, value) заменяет существующую запись. Как вставить запись в список?

====================== Редакция 2 ========================== ==

В соответствии с консенсусом я решил использовать SortedSet, я был бы признателен, если бы написанный мной код можно было проверить на предмет технических аспектов согласованности между Comparator и equals.

private static class ClientStatus {
    public long id;
    public long time;

    public ClientStatus(final long id, final long time) {
        this.id = id;
        this.time = time;
    }

    @Override
    public boolean equals(final Object o) {
        if ((o == null) || (getClass() != o.getClass())) {
            return false;
        }
        if (this == o) {
            return true;
        }
        ClientStatus obj = (ClientStatus) o;
        return this.id == obj.id;
    }
}

public static void main(String[] args) {

    SortedSet<ClientStatus> active_client_set = new TreeSet<ClientStatus>(
            new Comparator<ClientStatus>() {
                @Override
                public int compare(final ClientStatus o1, final ClientStatus o2) {
                    if (o1.getClass() != o2.getClass()) {
                        return -1;
                    }

                    if (o1 == o2 || o1.id == o2.id) {
                        return 0;
                    }
                    return (o1.time - o2.time) < 0 ? -1 : +1;
                }
            }
    );
}

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


person user1071840    schedule 17.06.2014    source источник
comment
Нужно ли разрешать повторяющиеся записи?   -  person Brett Okken    schedule 18.06.2014
comment
Я думаю, что SortedSet может быть выходом. Но если вы хотите использовать LinkedList, вы, кажется, на правильном пути, подсчитывая индексы, но используйте метод add, который вставит новую запись в список. См. LinkedList javadoc.   -  person ajb    schedule 18.06.2014


Ответы (2)


Я ожидаю, что каждая новая запись будет иметь время >= последней записи в списке, но есть вероятность состояния гонки, когда я могу выйти из строя значений порядка. Поэтому я решил, что итерация по списку с конца будет наиболее эффективным решением с точки зрения времени.

Если у вас есть возможность параллельного доступа, вы ДОЛЖНЫ синхронизировать итерацию и изменение LinkedList. Вы не просто получите элементы не по порядку, в лучшем случае итерация вызовет исключение ConcurrentModificationException, в худшем случае — неопределенная потеря данных.

person Brett Okken    schedule 17.06.2014

Я думаю, что тип, который вы ищете, - это SortedSet, который может быть реализован TreeSet.

Отсортированный набор хранит все записи в наборе, отсортированные с использованием их compare(...) реализации.

Все элементы в наборе должны реализовывать интерфейс Comparator<T>, чтобы SortedSet работал правильно.

Вы можете предпочесть использовать SortedMap, который работает аналогичным образом. Вы можете установить идентификатор клиента в качестве значения и поле времени в качестве ключа, и карта сохранит сортировку, используя сравнение полей времени.

Вы также говорили об условиях гонки. В javadoc для использования TreeMap обсуждается это и упоминается, что карта должна быть синхронизирована извне с помощью Collections.synchronizedSortedMap(...).

Я не пробовал синхронизированную реализацию, поэтому ничего не могу добавить по этому поводу.

Ознакомьтесь с документами для получения дополнительной информации:

http://docs.oracle.com/javase/7/docs/api/java/util/SortedSet.html http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html

person Tomer A    schedule 17.06.2014