2016-01-27 2 views
3

Давайте предположим, что есть служба данных, которая возвращает экземпляры класса cat:Сравнение свойств объектов, которые равны через ид

class Cat { 
    int id; 
    String name; 
    int iq; 
} 

Я хочу, чтобы держать экземпляры внутри Set<Cat>, которые не должны занимать две кошки с тот же идентификатор. Поэтому мне нужно переопределить методы equals и hashcode только для проверки на id.

Вопрос: как я могу определить, требует ли кошка внутри моего набора обновления, когда я получаю новый экземпляр из службы с тем же идентификатором, но разные значения для name и/или iq? Я не могу добавить свойства к equals или hashcode, так как тогда было бы возможно, что Set содержит экземпляры одного и того же идентификатора.

Нужно ли сравнивать все поля вручную или есть другое типичное для Java решение?


Edit для осветления:

Просто обновление Set с новым экземпляром не будет достаточно, потому что это код запускается на обновление. Так что я хочу сделать, это:

if (set.contains(newCat)) { 
    Cat current = set.get(newCat); 
    if (!current.equals(newCat)) { //obviously this is not enough 
    set.add(current); 
    //notify EventBusses and such 
    } 
} 

Решения, которые пришли в мой ум:

  1. current.requiresUpdate(newCat) //basically copy of equals() with properties
  2. current.updateWith(newCat) //same as above but keeping the old instance
  3. if (!current.name.euqals(newCat.name)) //for each property
  4. получить только объекты из службы, которые имеют изменилось. Оптимально, но не для меня.

Все это потребует несколько избыточного кода, поэтому я надеялся, что есть образец или коллекция, которая выполняет эту работу для меня.
Решение может включать в себя классы Guava.

+4

Вы действительно хотите, чтобы набор не держать двух кошек с тем же ID, или вы на самом деле хотите нет двух кошек, не имеют такой же идентификатор? Если это первый, используйте «Map » и проверьте, '' map.containsKey (id) 'перед добавлением его. –

+1

Вы можете хранить все экземпляры внутри 'Map ' вместо 'Set '. Тогда вы все равно можете проверить свой метод 'equals()', кошки идентичны. Или просто напишите другой метод, который сравнивает все поля. Фактически, вы все равно должны это сделать. – khelwood

ответ

1

Я думаю, что у вас есть две различные проблемы:

  • Сравнение Cat объектов: Если два Cat объекты равны, только если id , name и iq равны, чем реализуют метод equals.
  • Поддержание коллекции Cat объектов: Для того, чтобы сохранить коллекцию Cat объектов, в которых не существует двух объектов с одинаковыми id, использовать Map<Integer, Cat>, как уже было предложено.

Ваш код может выглядеть примерно так:

if (mapOfCats.contains(newCat.id)) { 
    Cat current = mapOfCats.get(newCat.id); 
    if (!current.equals(newCat)) { 
    mapOfCats.put(newCat.id, newCat); 
    // notify EventBusses and such 
    } 
} 
+0

Я принял ваш ответ со своего пути Java, чтобы делать что-то. Для разработчиков Android с такой же проблемой можно посмотреть http://developer.android.com/reference/android/support/v7/util/SortedList.html. В конце концов этот класс решил все мои проблемы. – McFarlane

2

Вам просто нужно снова вставить значение.

Если идентификатор будет соответствовать предыдущему объекту cat, он будет перезаписан в наборе.

HashSet внутренне поддерживает HashMap для идентификации дубликатов.

+0

Мой вопрос был недостаточно конкретным. Я обновил его, чтобы показать, что простого обновления недостаточно. – McFarlane

0

Более простым решением является: если найдено равным - удалите его и добавьте снова, с обновленными значениями. Этот код может быть несколько, как это:

yourSet.remove(cat); 
yourSet.add(newCatObejectWithSameID); 

newCatObejectWithSameID будут иметь разные name и iq.

+0

Мой вопрос был недостаточно конкретным. Я обновил его, чтобы показать, что простого обновления недостаточно. – McFarlane

0

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

Однако, предполагая, что может быть несколько логически различные Cat экземпляры с таким же идентификатором, самый простой способ справиться с этим является использование Map<Integer, Cat>:

Map<Integer, Cat> cats = new HashMap<>(); 
for (Cat cat : getAllCats()) { 
    if (!cats.containsKey(cat.id)) { 
    cats.put(cat.id, cat); 
    } else { 
    // Do whatever - ignore, log a message, throw an exception? 
    } 
} 
Collection<Cat> catsWithUniqueIds = cats.values(); 
+0

Я думаю, что в вопросе говорится что-то вроде «есть экземпляр в наборе, я получаю обновленную обратную ссылку (где-то), как определить, нужно ли мне ее обновлять». Что тривиально ответственно, просто заменив его. Набор кажется прекрасным для этого, за исключением отсутствия «замены» или добавления, которое просто добавляет его:/ –

+0

Мой вопрос был недостаточно конкретным. Я обновил его, чтобы показать, что простого обновления недостаточно. – McFarlane

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