2016-11-17 1 views
0

Итак, я работаю с объектами 4000, для которых мне нужно сопоставить идентификаторы объектов объектам.Отображение Java, несколько ключевых столкновений, обходные пути

private HashMap<Foo, Bar> fooBar; 

Дело в том, что около 34, 35 раз есть ключевые столкновения, в которых два элемента будут иметь один и тот же ключ. Что я могу сделать по этому поводу? Я не хочу, чтобы сделать

private HashMap<Foo, List<Bar>> fooBar; 

Поскольку список не будет использоваться 99% времени, и у меня есть некоторые ограничения ресурсов. Каков стандартный способ обойти это?

+0

Если ключ является идентификатором объекта, как может быть несколько объектов с одним и тем же ключом/идентификатором? Идентификаторы уникальны, поэтому, если они имеют одинаковый идентификатор, они * являются * одним и тем же объектом. – Andreas

+0

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

+0

Таким образом, идентификатор не является истинным идентификатором, поскольку он не * идентифицирует * объект, а это означает, что вы должны перестать называть его идентификатором, поскольку это вводит в заблуждение. – Andreas

ответ

0

Я думаю, что вы можете использовать дваHashMap бывший HashMap < Foo, Bar> используется для хранения 99% без key collisions и последней HashMap < Foo, List<Bar>> используется для хранения оставать 1%, а когда нужно выберите объект с помощью ID выберите все эти два HashMap.


Надеюсь, это может вам помочь.

+0

Но как бы я работал с поиском, например ID: 0 делает столкновение, где обычно он возвращает BAR теперь возвращает LIST

+0

, тогда вам нужно пройти по списку и получить нужный вам объект. –

+0

Это должно сработать, спасибо. –

0

Существует реализация нескольких карт в apache commons lang. Если вам действительно нужно сделать карту, это может быть полезно. Вы также можете найти другой ключ, который на самом деле будет уникальным.

+0

Вы случайно знаете производительность Multi-map vs Hash-map? Я подумал об этом, но не смог найти хороших тестов –

+0

Нет, но я бы подумал, что это не все, что отличается от карты со списком. – erehwon

1

У вас есть несколько вариантов:

  1. Использование Map<Foo, List<Bar>>. Вы упоминаете ограничения ресурсов, но, серьезно, если 4000 List объектов слишком много, то вам нужно сменить свое оборудование :-)

  2. Используйте одну из общедоступных реализаций Multi-map. Многие из них используют некоторый вариант отображаемого значения, являющийся списком, поэтому это в основном простой способ достижения первого варианта.

  3. Измените свою реализацию Bar на поддержку композитного материала. Это может быть очень эффективным, потому что некомпозитный подкласс может просто вернуться сам. Но это путает дизайн класса с детализацией реализации (предполагая, что бары не являются естественным композитом).

  4. Добавить новый класс, который поддерживает один или несколько объектов Bar и сопоставляет их с этим классом.

Например:

interface Bars { 
    public Stream<Bar> getBars(); 
    public Bars addBars(Bars bars); 
} 

class SingleBar implements Bars { 
    private final Bar bar; 

    public SingleBar(Bar bar) { 
     this.bar = bar; 
    } 

    public Stream<Bar> getBars() { 
     return Stream.of(bar); 
    } 

    public Bars addBars(Bars bars) { 
     return new MultiBar().addBars(this); 
    } 
} 

class MultiBar implements Bars { 
    private final List<Bar> barList = new ArrayList<>(); 

    public Stream<Bar> getBars() { 
     return barList.stream(); 
    } 

    public Bars addBars(Bars bars) { 
     bars.getBars().forEach(barList::add); 
     return this; 
    } 
} 

Map<Foo, Bars> map = new HashMap<>(); 
map.merge(foo, new SingleBar(bar), Bars::addBars); 
map.get(foo).getBars().forEach(...); 

Чтобы быть честным, что кажется, как много работы, чтобы избежать списка и, вероятно, не является какой-либо более эффективным. Я бы пошел с вариантами 1 или 2.