2015-05-13 1 views
9

Я хочу сохранить значение на основе ключа, состоящего из множества элементов. Что-то вроде приведенного ниже примера. Конечно, я знаю, что мой псевдо-пример не будет работать, поскольку хэш объекта, вероятно, будет его адресом, который будет уникальным для каждого нового экземпляра, независимо от его содержимого.Как использовать набор элементов в качестве ключевых в java-картах?

// in this pseudo-example this is my SET http://algs4.cs.princeton.edu/35applications/SET.java.html 
    // but the idea is that values are unique 
    HashMap<SET<Integer>, String> map = new HashMap<>(); 
    SET a = new SET(); 
    a.add(1); 
    a.add(2); 
    a.add(5); 

    SET b = new SET(); 
    b.add(5); 
    b.add(1); 
    b.add(2); 

    map.put(a, "w00t"); 

    System.out.println(map.get(b)); // I would want to get "w00t" because my key is the same set of elements 

Конечно, я могу просто сортировать и сцепить значения SET в виде строки с разделителями и использовать его в HashMap<String, String> структуре, но это просто не чувствует себя хорошо. Я совершенно новичок в программировании на Java, поэтому может быть очевидное решение, которое мне не хватает.

+0

Вы должны изучить 'keySet()'. Также это 'Set', а не' SET' –

+0

. Думаю, здесь есть большая проблема, если вы хотите использовать коллекции для этой работы. Все они изменяемы. Что делать, если вы добавляете наборы (2,3) и (1,2,3), но потом вы решили удалить {1} со второго набора? Лучше создайте для этого отдельный неизменный объект, иначе это будет тревожным. – pnadczuk

+0

Я понимаю это, но в моем случае я не буду изменять объекты, как только я их сохраню. В идеале я хотел бы иметь неизменяемый объект, который я инициализирую из другого итерабельного, но нет никого, что я могу найти :( – ddinchev

ответ

7

Если вы используете вместо пользовательского SET (я предполагаю, что это пользовательский класс), он будет работать нормально, так как HashSet переопределениях hashCode и equals (точнее, HashSet расширяет AbstractSet который переопределяет эти методы), поэтому он может служить ключом в HashMap.

Однако, если вы измените набор, который служит в качестве ключа на вашей карте, вы не сможете найти этот ключ на карте позже. Это риск, которым вы сталкиваетесь при использовании изменяемых объектов в качестве ключей в HashMap.

HashMap<HashSet<Integer>, String> map = new HashMap<HashSet<Integer>, String>(); 
HashSet<Integer> a = new HashSet<Integer>(); 
a.add(1); 
a.add(2); 
a.add(5); 

HashSet<Integer> b = new HashSet<Integer>(); 
b.add(5); 
b.add(1); 
b.add(2); 

map.put(a, "w00t"); 

System.out.println(map.get(b)); 

Этот выход w00t.

+0

Я просмотрел его Он не переопределяет, он просто наследует. – ddinchev

+1

@ddinchev Это нормально работает. Попробуйте и убедитесь сами. – gdejohn

+2

@ddinchev Да, я был неточен, AbstractSet делает переопределение. – Eran

0

Создайте класс коллекции и переопределите hashcode() таким образом, чтобы тот же хэш-код возвращался для разных экземпляров коллекции с тем же содержимым. Вы можете просто переопределить метод в классе, полученном из вашей нужной коллекции. Вам также нужно переопределить равные (Object o).

+0

JDK набор реализаций уже делает это для вас. – gdejohn

+0

Как насчет двух экземпляров OrderedSet с другим компаратором? – Traubenfuchs

+0

Все еще работает. Если вы проверите документы для ['TreeSet'] (https://docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html), вы увидите, что он наследует свой [' equals () '] (https://docs.oracle.com/javase/8/docs/api/java/util/AbstractSet.html#equals-java.lang.Object-) и [' hashCode() '] (https: //docs.oracle.com/javase/8/docs/api/java/util/AbstractSet.html#hashCode--) реализации из 'AbstractSet'. «Интерфейс Set устанавливает дополнительные условия, помимо тех, которые унаследованы от интерфейса Collection, от контрактов всех конструкторов и контрактов методов add, equals и hashCode». – gdejohn

-2

Вы не добавили set b на свою карту. Сначала добавьте оба набора, а затем попытайтесь получить значение, связанное с ключом b.

+2

Это точка OP - оба набора имеют одинаковые элементы и должны быть идентичными, но объект, добавленный с 'a', как ключ, не может быть получен с помощью' b'. Это происходит потому, что он не переопределял 'hashCode' или' equals' в своей реализации пользовательского набора. –

-1

Это зависит от вас от реализации класса SET. Вы можете либо расширить класс java.util.HashSet, либо реализовать методы equals() и hashCode() в вашем классе SET. Любое решение будет работать.

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