java – Overriding equals and hashCode to check if an object exists in a Set

Question:

I have a Set like this:

private Set<Row> selectedRows = new HashSet<>();

At a certain moment, it contains an object of the form:

[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}]]

I need when a Row object of the form comes in:

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}] 

The selectedRows.contains() method returned true . How can you override equals and hashCode for this purpose?

UPDATE: Row class:

public class Row implements HtmlPainter, Comparable<Row> {

    private String styleName = "editable-grid-row";
    private Map<String,String> rowData;
    private int index;

    public interface RowSelectChangeListener{
        void onSelectChange(Row row);
    }

    public Map<String, String> 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<String,TypedValue> asParams(){
        Map<String,TypedValue> params = new FastMap<TypedValue>();
        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<String, String> 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());
    }
}

Answer:

Victor, no, you don't need to take null = T into account when comparing. Everything else should be equal, null = T is not important.

Then as advised by iksuy:

In the calculation of the hashcode, include the calculation of the hashcode for the contents of the Map, such as sum the hashes of keys and values ​​there, for example. And in equals, respectively, compare pairs, if for all equal keys their values ​​are equal, then equals -> true

I propose a hashcode, it will not depend on the number of elements.

@Override
public int hashCode() {
    int h = 0;
    Iterator<Map.Entry<String, String>> i = rowData.entrySet().iterator();
    while (i.hasNext()) {
        Map.Entry<String, String> next = i.next();
        if(next.getKey() != null) {
            h += next.hashCode();
        }
    }
    return h;
}

Equals test this, it looks like it should work.

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Row row = (Row) o;


        Map<String, String> OrowData = row.rowData;

        //проверим списки ключей

        Set<String> copy = new HashSet<>(OrowData.keySet());
        Set<String> 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;
    }

As intended, it should return false if the number of keys or their name is different (excluding null). If everything is fine here, then we go through the list of keys without null and check their presence and correspondence in each Map . null was specially removed from the copy, suddenly you still need it in the original Map .

Scroll to Top