Страницы

Поиск по вопросам

пятница, 12 июля 2019 г.

Переопредление equals и hashCode для проверки наличия объекта в Set

У меня есть Set вида:
private Set selectedRows = new HashSet<>();
В определенный момент в нем лежит объект вида:
[Row [rowData={DFOBJ_ACC=105708976, DFNUMBER_ACC=229000032841, DFALIAS=Северо-Запад, FIRST_GROUP_DFOBJ=3180360969, FIRST_GROUP_NAME=Test 2 lines, SECOND_GROUP_DFOBJ=3180360970, SECOND_GROUP_NAME=Алиас, DFGROUP_NAME=, DFOBJ_CONTR=105708991, DFNUMBER_CONTR=№, от 09.07.2013, DFDATE_BEGIN=09.07.13, DFSUB_NUM=503, DFINVOICE=, DFBALANCE_OUT=0, null=T}]]
Мне нужно, когда приходит объект Row вида:
Row [rowData={DFOBJ_ACC=105708976, DFNUMBER_ACC=229000032841, DFALIAS=Северо-Запад, FIRST_GROUP_DFOBJ=3180360969, FIRST_GROUP_NAME=Test 2 lines, SECOND_GROUP_DFOBJ=3180360970, SECOND_GROUP_NAME=Алиас, DFGROUP_NAME=, DFOBJ_CONTR=105708991, DFNUMBER_CONTR=№, от 09.07.2013, DFDATE_BEGIN=09.07.13, DFSUB_NUM=503, DFINVOICE=, DFBALANCE_OUT=0}]
Метод selectedRows.contains() вернул true. Каким образом можно переопределить equals и hashCode для этой цели?
UPDATE: Класс Row
public class Row implements HtmlPainter, Comparable {
private String styleName = "editable-grid-row"; private Map rowData; private int index;
public interface RowSelectChangeListener{ void onSelectChange(Row row); }
public Map getRowData() { return rowData; }
public void setStyleName(String styleName) { this.styleName = styleName; }
RowSelectChangeListener selectListener;
public void setSelectListener(RowSelectChangeListener selectListener) { this.selectListener = selectListener; }
public int getIndex() { return index; }
public void setIndex(int index) { this.index = index; }
public Map asParams(){ Map params = new FastMap(); rowData.forEach((k,v) -> {params.put(k, new TypedValue(v));}); return params; }
@Override public String toString() { return "Row [" + (rowData != null ? "rowData=" + rowData : "") + "]"; }
private static String SELECTED = "eg-selected-row";
private Element el;
private static final RowTemplates TEMPLATES = GWT.create(RowTemplates.class);
private Cell[] cells; private GridView gridView;
public Row(int index, Map rowData, GridView gridView){ this.rowData = rowData; this.index = index; this.gridView = gridView; }
public HTMLPanel getGridPanel(){ return gridView.pnl; }
public void setCells(Cell[] cells) { this.cells = cells; }
public Cell getCell(int index) { return cells[index]; }
public String getValue(String key){ return rowData.get(key); }
public String getId(){ return rowData.get("DFOBJ"); }
public void putValue(String k , String v){ rowData.put(k , v); }
@Override public void renderStartTag(SafeHtmlBuilder builder) { builder.append(TEMPLATES.startRowDiv(styleName, index, hashCode())); }
@Override public void renderFinishTag(SafeHtmlBuilder builder) { builder.append(TEMPLATES.endRowDiv()); } }


Ответ

Виктор, нет, при сравнении не нужно учитывать null=T. Должно быть равно все остальное, null=T не важно.
Тогда как посоветовал iksuy:
В расчет хэшкода включите расчет хэшкода для содержимого Map, типа там суммируйте хэши ключей и значений например. А в equals соответственно сравнивайте пары, если для всех равных ключей равны их значения, то equals -> true
Хешкод предлагаю такой, он не будет зависеть от количества элементов.
@Override public int hashCode() { int h = 0; Iterator> i = rowData.entrySet().iterator(); while (i.hasNext()) { Map.Entry next = i.next(); if(next.getKey() != null) { h += next.hashCode(); } } return h; }

Equals потестируйте такой, на вид должен работать.
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false;
Row row = (Row) o;
Map OrowData = row.rowData;
//проверим списки ключей
Set copy = new HashSet<>(OrowData.keySet()); Set original = new HashSet<>(rowData.keySet()); copy.remove(null); original.remove(null);
if (!copy.equals(original)) return false;
//если все ключи совпадают проверим каждое занчение по ключу
for (String key : original) { if (!rowData.get(key).equals(OrowData.get(key))) return false; }
return true; }
По задумке должен выдать false если количество ключей или их имя разное (не учитывая null). Если тут все хорошо, то дальше идем по списку ключей без null и проверяем в каждой Map их наличие и соответствие. null спецально удалял из копии, вдруг в оригинальной Map он вам ещё понадобиться.

Комментариев нет:

Отправить комментарий