Java: получение элемента из HashSet

Надеюсь, кто-то может объяснить, почему я не могу извлечь элемент из HashSet.

Рассмотрим мой HashSet, содержащий список MyHashObjects с правильными методами hashCode() и equals().

То, что я надеялся сделать, это построить сам MyHashObject и установить соответствующие свойства хэш-кода для определенных значений. Я могу запросить HashSet, чтобы увидеть, есть ли в нем "эквивалентные" объекты с помощью метода contains(). Поэтому, даже если contains() возвращает true для 2 объектов, они могут быть не == true.

Почему не существует метода get(), аналогичного тому, как работает contains()?

Заинтересованы в понимании мышления, лежащего в основе этого решения API.

Ответы

Ответ 1

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

Если вы хотите использовать итератор над элементами, просто используйте Set.iterator().

Похоже, то, что вы пытаетесь сделать, это обозначить канонический элемент для класса эквивалентности элементов. Вы можете использовать Map<MyObject,MyObject> для этого. См. этот вопрос SO или этот для обсуждения.

Если вы действительно решили найти элемент, который .equals() ваш исходный элемент с ограничением, которое вы ДОЛЖНЫ использовать HashSet, я думаю, что вы застряли в нем итерации по нему и проверили equals() самостоятельно. API не позволяет вам что-то захватывать хеш-кодом. Таким образом, вы можете сделать:

MyObject findIfPresent(MyObject source, HashSet<MyObject> set)
{
   if (set.contains(source)) {
      for (MyObject obj : set) {
        if (obj.equals(source)) 
          return obj;
      } 
   }

  return null;
}

Грубая сила и O (n) уродливые, но если это то, что вам нужно сделать...

Ответ 2

Похоже, вы пытаетесь использовать хэш-код в качестве ключа на карте (это то, что HashSets делает за кулисами). Вы можете просто сделать это явно, объявив HashMap<Integer, MyHashObject>.

Для HashSets нет get, потому что обычно объект, который вы передадите методу get в качестве параметра, - это тот же объект, который вы вернетесь.

Ответ 3

Вы можете HashMap<MyHashObject,MyHashObject> вместо HashSet<MyHashObject>.

Вызов ContainsKey() на вашем "восстановленном" MyHashObject будет сначала hashCode() -check collection, и если будет удалено дублирующее хэш-код, наконец equals() -check ваш "реконструированный" против оригинала, на котором вы может извлекать оригинал с помощью get()

Это O (1), но недостатком является то, что вам, вероятно, придется переопределить методы equals() и hashCode().

Ответ 4

Если вы знаете порядок элементов в Установить, вы можете получить их, преобразов Установить в Массив. Что-то вроде этого:

Set mySet = MyStorageObject.getMyStringSet();
Object[] myArr = mySet.toArray();
String value1 = myArr[0].toString();
String value2 = myArr[1].toString();

Ответ 5

Если я точно знаю, что в моем приложении объект не используется в поиске в любой из структуры списка или хеш-данных и не используется метод equals в другом месте, кроме тех, которые косвенно используются в структуре хэш-данных при добавлении. Рекомендуется ли обновлять существующий объект в методе equals. См. Приведенный ниже код. Если я добавлю этот bean в HashSet, я могу выполнить агрегацию групп на соответствующем объекте на ключе (id). Таким образом, я могу выполнять функции агрегации, такие как sum, max, min,.... Если это не рекомендуется, пожалуйста, не стесняйтесь делиться со мной своими мыслями.

public class MyBean {
  String id;
  String name;
  double amountSpent;

    @Override
    public int hashCode() {
        return id.hashCode();
    }
    @Override
    public boolean equals(Object obj) {
        if(obj!=null && obj instanceof MyBean ) {
            MyBean tmpObj = (MyBean) obj;
            if(tmpObj.id!=null && tmpObj.id.equals(this.id)) {
                tmpObj.amountSpent += this.amountSpent;
                retuen true;
            }
        }
        return false;
    }
}

Ответ 6

Идея о том, что вам нужно получить ссылку на объект, содержащийся внутри объекта Set, является общей. Его можно архивировать двумя способами: 1. Используйте HashSet, как вы хотели, затем:

public Object getObjectReference(HashSet<Xobject> set, Xobject obj) {
    if (set.contains(obj)) {
        for (Xobject o : set) {
            if (obj.equals(o))
                return o;
        }
    }
    return null;
}

Для этого подхода к работе вам необходимо переопределить методы hashCode() и equals (Object o) В худшем случае O (n)

  1. Второй подход - использовать TreeSet public Object getObjectReference(TreeSet<Xobject> set, Xobject obj) { if (set.contains(obj)) { return set.floor(obj); } return null; }

Этот подход дает O (log (n)), более эффективный. Вам не нужно переопределять hashCode для этого подхода, но вам нужно реализовать интерфейс Comparable. (определите функцию compareTo (Object o))

Ответ 7

Если вы можете использовать List как структуру данных для хранения ваших данных, вместо использования Map для сохранения результата в значении карты вы можете использовать следующий фрагмент и сохранить результат в том же объекте.

Вот класс Node:

private class Node {
    public int row, col, distance;

    public Node(int row, int col, int distance) {
        this.row = row;
        this.col = col;
        this.distance = distance;
    }

    public boolean equals(Object o) {
        return (o instanceof Node &&
                row == ((Node) o).row &&
                col == ((Node) o).col);
    }
}

Если вы сохраняете свой результат в переменной distance, и элементы в списке проверяются на основе их координат, вы можете использовать следующее, чтобы изменить расстояние до нового с помощью lastIndexOf, пока вам нужно хранить только один элемент для каждой информации:

    List<Node> nodeList;
    nodeList = new ArrayList<>(Arrays.asList(new Node(1, 2, 1), new Node(3, 4, 5)));
    Node tempNode = new Node(1, 2, 10);
    if(nodeList.contains(tempNode))
        nodeList.get(nodeList.lastIndexOf(tempNode)).distance += tempNode.distance;

В основном это переопределение Set, элементы которого могут быть доступны и изменены.