Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove equal item from java list

I have a list of items, where each item is a simple class containing 2 public strings. I have an equals method that simply makes use of the equalsIgnoreCase methot of String for both strings.

public class data
{
    public String a;
    public String b;

    public boolean equals(data d)
    {
        if(a.equalsIgnoreCase(d.a) && b.equalsIgnoreCase(d.b))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

I want to be able to remove an element even if it's not the same instance of the one in the list but equal to it.

Right now I'm doing this:

public void remove(data dataToRemove)
{
    for(data i : _list)
    {
        if(i.equals(dataToRemove))
        {
            _list.remove(i);
            break;
        }
    }
}

Is there a better way to do this?

like image 978
キキジキ Avatar asked Dec 03 '22 04:12

キキジキ


2 Answers

A few comments:

  • Your equals method does not override the equals method of Object (argument should be of Object type, not data type).
  • You should improve your equals method to account for nulls etc.
  • And finally, you should override hashcode() too when you override equals() - if not you might encounter some weird behaviors when using Sets or Maps for example.

If you properly override the equals method, you can then just use the remove method. See below the auto generated equals and hashcode generated by Netbeans, amended to use the equalsIgnoreCase method.

public static void main(String[] args) {
    List<Data> list = new ArrayList<Data>();
    list.add(new Data("a", "b"));
    list.add(new Data("a", "c"));
    System.out.println(list.size()); //2
    list.remove(new Data("A", "b"));
    System.out.println(list.size()); //1
}

public static class Data {

    public String a;
    public String b;

    public Data(String a, String b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        final Data other = (Data) obj;
        boolean sameA = (this.a == other.a) || (this.a != null && this.a.equalsIgnoreCase(other.a));
        if (!sameA) return false;
        boolean sameB = (this.b == other.b) || (this.b != null && this.b.equalsIgnoreCase(other.b));
        if (!sameB) return false;
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 89 * hash + (this.a == null ? 0 :this.a.toUpperCase().hashCode());
        hash = 89 * hash + (this.b == null ? 0 : this.b.toUpperCase().hashCode());
        return hash;
    }

}
like image 155
assylias Avatar answered Dec 09 '22 15:12

assylias


The clearest way is to just call the Remove method of the list without any loops and pass in your object the parameter. It uses the equals method that you defined on the object to find and remove it if it exists in the list.

_list.remove(data);

You also don't have to specify the hashcode method, but you should get in the habit of always creating one when you override the equals method in case you use it in a collection like a Set or a Map.

like image 29
Hiro2k Avatar answered Dec 09 '22 16:12

Hiro2k