Если у вас есть equals / hashcode, основанный на int, каков оптимальный способ сопоставления «полного» объекта из другой коллекции? - PullRequest
0 голосов
/ 24 сентября 2011

Скажем, у вас был этот класс DTO:

public class MyObj{
 private int id;

 private String displayName;
 private String backendData;

 public boolean equals(Object obj){
  return id.equals(obj);
 }

 private int hashCode(){
  return id.hashCode();
 }
}

Допустим, пользователь должен выбрать несколько экземпляров MyObj из списка, который показывает только displayName и id #, связанный в фоновом режиме. Чтобы сохранить пропускную способность, вы не отправляете backendData. Когда они возвращают свой выбор вам, клиент просто отправляет вам идентификатор #.

Теперь вы сохранили список серверных сторон оригинальных опций в Коллекции . Наивным подходом к возвращению «полного» объекта из коллекции было бы перебрать коллекцию и вызвать «.equals ()» для каждого объекта. Это масштабируется в O (n), хотя: (

Кажется, что с помощью коллекций операций с постоянным временем, таких как HashSet, я должен иметь возможность извлекать объект за постоянное время, если я знаю, что он идентичен. Но в HashSet есть только метод "contains ()" и он не возвращает найденный объект.

Любой совет? Как всегда, спасибо огромное стеку OverFlow!

Ответы [ 4 ]

2 голосов
/ 24 сентября 2011

Я предполагаю, что идентификатор уникален для всей коллекции?

Вы почти там используете Map<Integer, MyObj>, тогда map.get(id) - это асимптотически постоянное время.

0 голосов
/ 24 сентября 2011

hashCode предназначен для быстрого получения номера объекта. Команда equals должна выполнить полное сравнение всех полей, которые вы хотите проверить на предмет равенства.

public class MyObj
{
    private final Integer id;

    private String displayName;
    private String backendData;

    public boolean equals(Object obj)
    {
        final MyObj other;

        if(obj == null || obj.getClass() != MyObj.class)
        {
            return (false);
        }

        other = (MyObj)obj;

        if(!(displayName.equals(other.displayName))
        {
            return (false);
        }

        if(!(backendData.equals(other.backendData))
        {
            return (false);
        }

        return (true);
    }

    private int hashCode()
    {
        return id.hashCode();
    }
}

Это предполагает, что ни одно из полей не может быть нулевым, это немного сложнее в операторах if, если они могут быть нулевыми.

0 голосов
/ 24 сентября 2011

Ваш вопрос представляет несколько проблем ИМХО: во-первых, не используйте db id в качестве хеш-ключа, вы можете столкнуться с проблемами, если эта вещь генерируется автоматически. Во втором хэш-наборе / карте используется хэш-код и методы equals для извлечения объектов (когда вы используете метод getmethod). Сначала используется хеш-код, чтобы быстро найти область, в которой может находиться ваш объект. Затем, если в вашей коллекции хэшей были коллизии, и в этом сегменте есть несколько объектов, то для извлечения объекта будет использоваться равенство. Поэтому, когда вы используете get с экземпляром вашего класса, только поля, которые используются в хэш-коде и равно, должны иметь правильное значение, чтобы получить ваш объект. В этом случае, если ваш объект имеет правильный идентификатор (но неверное другое поле), он может быть использован для получения своего аналога с заполненным другим полем. Это или вы можете использовать карту.

0 голосов
/ 24 сентября 2011

Ваш объект не работает (потому что вы не можете вызывать методы примитивных типов данных). Измените id на Integer и используйте его в хешированной коллекции.

Map<Integer, T> objectMap = ...;
Integer id = someidfromfrontend;
T anObj = objectMap.get(id);
...