Использование HashSet.contains()

#java #set

#java #установить

Вопрос:

У меня есть класс с 3 атрибутами. Один из атрибутов используется в качестве уникального ключа, поэтому я использую этот единственный ключ в своем методе equals and hashcode .

Теперь, когда набор собран, во время поиска у меня есть только первичный ключ (уникальный ключ), и мне придется создать фиктивный объект с уникальным ключом и установить два других значения равными 0 (значения по умолчанию), а затем я говорю

 Chapter myObject = new Chapter(uniqueKey,0,0);
hashSet.contains(myObject); // This will work.
  

Правильно ли это использование для поиска по Hashset? Есть ли какой-либо другой лучший способ, потому что я не любитель устанавливать фиктивные значения для объекта.

Ответ №1:

Один из способов сделать это менее подробным — определить Chapter() конструктор, который принимает uniqueKey аргумент и заполняет остальные, а затем использовать:

 hashSet.contains(new Chapter(uniqueKey));
  

Поскольку вы в любом случае выбрасываете объект.

Однако, поскольку у вас есть a uniqueKey , который, я полагаю, уникален для каждого экземпляра a Chapter , рассматривали ли вы возможность использования a HashMap вместо этого? Тогда вы могли бы просто использовать uniqueKey в качестве ключей, и вам просто нужно было бы проверить, присутствует ли ключ (например: используя HashMap.containsKey() ) или нет:

 hashMap.containsKey(uniqueKey);
  

С помощью HashMap вы также можете просто получить нужный объект с помощью .get() :

 Chapter c = hashMap.get(uniqueKey);
  

Это даст вам Chapter объект, если предоставленный uniqueKey сопоставляется с объектом, или null если нет.

Ответ №2:

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

Пример

 public class Foo {
  public static class Key {
    private final String s;
    private final int i;

    public Key(String s, int i) {
      this.s = s;
      this.i = i;
    }

    // TODO: Implement equals / hashCode.
  }

  private final Key key;
  private final double d;

  public class Foo(String s, int i, double d) {
    this(new Key(s, i), d);
  }

  public class Foo(Key key, double d) {
    this.key = key;
    this.d = d;
  }

  public Key getKey() { return key; }      

  // TODO: Implement equals / hashCode to delegate to Key.
}
  

Затем объекты создаются и добавляются на карту следующим образом:

 Foo foo1 = new Foo("Hello", 5, 10.0);
Foo foo2 = new Foo("Goodbye", 10, 20.0);

Map<Foo.Key, Foo> foosByKey = new HashMap<Foo.Key, Foo>();

foosByKey.put(foo1.getKey(), foo1);
foosByKey.put(foo2.getKey(), foo2);
  

… и к карте можно запросить, просто создав экземпляр ключа:

 if (foosByKey.contains(new Foo.Key("Hello", 5))) {
  System.err.println("BOOM!");
}
  

Ответ №3:

Если вам нужен поиск, возможно, вам лучше использовать HashMap вместо HashSet. Затем вы можете использовать свой первичный ключ в качестве ключа на карте, а объект в качестве значения, тогда вы можете сделать

 MyObject o = map.get(myKey);
  

Ответ №4:

Ваш подход кажется немного обходным. Почему бы просто не сохранить набор ключей? Или, если вам нужен доступ к объекту через ключ, тогда вам следует использовать HashMap , а не HashSet .