Индекс повторяющегося элемента в connectedHashSet
Я добавляю некоторые значения в LinkedHashSet
и на основе add()
вывод метода т.е. истина / ложь, я выполняю другие операции.
Если Set
содержит дубликат элемента, он возвращает ложь, и в этом случае я хочу знать индекс дубликата элемента в Set
так как мне нужно использовать этот индекс где-то еще. Будучи "связанной" коллекцией, должен быть какой-то способ получить индекс, но я не смог найти ничего подобного в Set
/LinkedHashSet
API.
1 ответ
LinkedHashSet
само по себе явно не индексируется. Если вам требуется индекс, используя Set
для такого применения обычно это признак неправильной абстракции и / или паршивого программирования. LinkedHashSet
только гарантирует вам предсказуемый порядок итераций, а не правильную индексацию элементов. Вы должны использовать List
в таких случаях, поскольку этот интерфейс дает вам гарантию индексации. Однако вы можете вывести индекс, используя несколько методов, например (не рекомендуется, обратите внимание):
а) использовать индексированную итерацию в коллекции (например, с for
цикл), поиск дубликатов и разрыв, когда он найден; это O(N) сложность для получения индекса,
Object o; // this is the object you want to add to collection
if ( !linkedHashSet.add(o) ) {
int index = 0;
for( Object obj : linkedHashSet ) {
if ( obj == o ) // or obj.equals(o), depending on your code's semantics
return index;
index++;
}
}
б) использовать .toArray()
и найти элемент в массиве, например,
Object o; // this is the object you want to add to collection
int index;
if ( !linkedHashSet.add(o) )
index = Arrays.asList(linkedHashSet.toArray()).indexOf(o);
опять же, O(n) сложность получения индекса.
И то, и другое повлекло бы за собой большие потери времени выполнения (второе решение явно хуже с точки зрения эффективности, поскольку оно создает массив каждый раз, когда вы ищите индекс; лучше было бы создать параллельный массив, отражающий множество). В общем, я вижу сломанную абстракцию в вашем примере. Ты говоришь
Мне нужно использовать этот индекс где-то еще
... если это действительно так, используя Set
99% времени неправильно само по себе.
Вы можете, с другой стороны, использовать Map
(HashMap
например), содержащий [index,Object]
(или же [Object,index]
в зависимости от точного варианта использования) пар в нем. Это потребовало бы немного рефакторинга, но это IMO предпочтительный способ сделать это. Это даст вам тот же порядок сложности для большинства операций, что и LinkedHashSet
, но вы получите O(1) для получения индекса по существу бесплатно (Java HashSet
использования HashMap
внутренне в любом случае, так что вы не теряете память, заменяя HashSet
с HashMap
).
Еще лучшим способом было бы использовать класс, явно обрабатывающий целочисленные карты - смотрите HashMap и int в качестве ключа для получения дополнительной информации; tl; dr - http://trove.starlight-systems.com/ имеет TIntObjectHashMap
& TObjectIntHashMap
, давая вам, возможно, лучшую скорость для таких операций возможно.