Получение ссылки на дубликат в наборе - PullRequest
3 голосов
/ 08 февраля 2012

У меня есть объект Set, и я использую этот набор, чтобы гарантировать, что при добавлении к нему элемента, который уже существует в наборе, он не добавляется. Это простая часть, просто используйте Set.add(); Но после того, как это сделано, мне нужна ссылка на объект в наборе.

Что я по сути имею в виду, так это наличие .add(), которое не возвращает логическое значение, но фактический объект, который вы пытались добавить (если он не был добавлен, тот, что в наборе). Уже есть реализация Set, которая делает это, или я должен написать свою собственную?

В данный момент я использовал Set.add(), и если он возвращает false, я использую итератор для поиска в наборе. Хотя это работает, я нахожу это уродливым. Особенно при использовании реализации HashSet, которая должна иметь возможность быстрее находить объект с помощью хеш-кодов. Есть идеи?

РЕДАКТИРОВАТЬ: Wow, много ответов в относительно короткое время, спасибо. Итак, я пытаюсь создать определенную структуру данных, которая загружает данные из некоторого места и создает объекты из него. Эти данные могут содержать дубликаты, и это не было бы проблемой, если бы я использовал набор и просто нуждался в этом одном наборе, но структура данных должна добавить ссылки на эти уникальные объекты к другим объектам в структуре данных, поэтому мне нужны ссылки на (уникальные) объекты в наборе. Кроме того, я не могу просто не загружать данные, которые уже содержатся в наборе, потому что с ним связано больше (уникальных) данных, которые также добавляются вместе со ссылкой на те данные, которые уже содержались в наборе. , В целях иллюстрации (поскольку приведенное выше объяснение далеко не ясно), я приведу пример здесь:

Данные:

foo     bar
1       3
1       4
2       5

Структура данных:

Set<Foo> totalFooSet  
Set<Bar> totalBarSet

Foo:

sometype data
Set<Bar> barSet  

Бар:

sometype data
Set<Foo> fooSet

Это похоже на отношение многих ко многим.

Я не уверен, есть ли здесь какой-то серьезный недостаток дизайна, я просмотрел его с другими людьми, и мы не можем понять, как сделать это по-другому. Мне нравится идея использования HashMap, поэтому я создам подкласс и добавлю к нему функцию addAndReturn ().

Ответы [ 5 ]

5 голосов
/ 08 февраля 2012

(Как говорит @AlexR, я предполагаю, что вы хотите ссылку на предыдущий объект, равный тому, который вы пытаетесь добавить сейчас)

Вместо использования Set, попробуйте использовать HashMap с тем же объектом, что и ключ и значение. Тогда вы можете сделать следующее:

Foo objectToAdd = //obtained the normal way
Map<Foo,Foo> psuedoSet = //this is stored somewhere

Foo result = psuedoSet.get(objectToAdd);
if (result == null) {
    pseudoSet.put(objectToAdd, objectToAdd);
    result = objectToAdd;
}
return result;
4 голосов
/ 08 февраля 2012

Аналогичен ответу Шона (который я проголосовал), но, возможно, более пригоден для повторного использования.

public class HashMapBackedSet<T> extends HashMap<T,T>{
    public T add( T toAdd ){
        T existing = get( toAdd );
        if( existing != null ){
            return existing;
        }
        put( toAdd, toAdd );
        return toAdd;
    }
}
3 голосов
/ 08 февраля 2012

Если я вас правильно понимаю, если элемент, который вы только что пытались добавить, уже содержится в наборе, вам нужен экземпляр, который уже находится в наборе (который равен добавленному, ноне обязательно идентичный )?

Такое поведение обеспечивается интернерами из Google Guava библиотеки:

Interner<Object> interner = Interners.newStrongInterner();
Object objectInSet = interner.intern(otherObject);

К сожалению, интернеры не предоставляют никаких других методов, таких как итерации по содержащимся в них значениям, поэтому использование их в качестве замены набора может оказаться невозможным для вас.

Другим вариантом будет HashMap<T, T>, где вы храните отображениеот каждого объекта к себе.Затем вы можете легко получить ссылку на уже содержащийся объект, вызвав get().Если вы не возражаете, что объект всегда переопределяется, просто вызовите put(), который возвращает именно тот объект, который вы хотите (ранее сохраненный объект).

0 голосов
/ 08 февраля 2012

Набор не может содержать повторяющиеся записи.Цель набора не состоит в том, чтобы сделать это.Насколько я понимаю, вы хотите получить ссылку на предыдущий объект, идентичный тому, который вы пытаетесь добавить сейчас.Вам не нужно повторять набор, чтобы найти этот объект.Просто пользователь oldObject = set.get(newObject).

Эта операция выполняется так же быстро, как получение элемента массива по индексу.

0 голосов
/ 08 февраля 2012

Обернуть ваш набор в класс, который возвращает объект при вызове add?

...