简体   繁体   中英

Make List.remove(Object o) remove via id and not equals

Lets say I have a list of objects List<Person> people . This list is composed of multiple Person objects - each has a name and age (and also implements the respective equals and hashCode methods)

The list is populated with multiple (different in memory) objects that are (same in values)

List<Person> people = new ArrayList<>();
Person person_1 = new Person("Tom", 21);
Person person_2 = new Person("Tom", 21);
Person person_3 = new Person("Tom", 21);

person_1.equals(person_2) // true
person_1 == person_2      // false

people.add(person_1);
people.add(person_2);
people.add(person_3);

The problem I have is that people.remove(person_1) removes person_2 and person_3 also.

What can I do to change this?

From the Java Documentation on List

boolean remove(Object o);

Removes the first occurrence of the specified element from this list, if it is present (optional operation). If this list does not contain the element, it is unchanged. More formally, removes the element with the lowest index i such that (o==null ? get(i)==null : o.equals(get(i)))


As far as == vs. .equals @brainydexter explained it pretty well here .

Essentially,

== is a comparison of references, ie both objects point to the same memory location.

.equals evaluates to the comparison of values in the objects

Since .remove() on a List<> object boils down to using .equals() it will only check for value comparisons, so any object with matching values will evaluate to being equal.

A few work arounds I can come up with off the top of my head:

  • Come up with an Identifier Injection method.

    1. Have a private variable inside of the Person() class.
    2. Have a global reference stored somewhere for tracking Person() identifiers.
    3. When a new Person() is instantiated, use that global tracking variable to determine the identifer for the new Person() and apply it to it's private identifier.
    4. Implement equals() in your Person() class and return the comparison of the private identifiers.

      • This way, each Person() object will be unique and .equals() will not consider them the same.
      • The main issue I could see with this method include overly complicating the identifier tracking for the objects. This seems unnessecary with such simple objects.
  • Remove a similar object

    1. Iterate over the list until you find only one object that matches the one you'd like to remove.
    2. Remove it based on it's index in the list.
      • The main issue with this is that your code becomes nonsense. You're asking to remove person2 , but you could run .remove(person2) three times and all would succeed as the it would remove the first element that matches your input object each time it's run. So, person2 would become person1 would become person3 under the scope of your custom .remove() function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM