ArrayList没有移除对象

huangapple go评论101阅读模式
英文:

ArrayList not removing object

问题

Remove语句未能移除该对象。在remove语句之前和之后,我可以看到列表大小为2。

public class Test {
    private static class Point {
        private int x, y;
        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(final String[] args) {
        List<Point> pList = new ArrayList<>();
        pList.add(new Point(1, 2));
        pList.add(new Point(3, 4));
        System.out.println(pList.size());
        pList.remove(new Point(3, 4));
    }
}
英文:

The Remove statement is not removing the object. I can see the list size as 2 before & after remove statement.

public class Test {
    private static class Point {
        private int x, y;
        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(final String[] args) {
        List&lt;Point&gt; pList = new ArrayList&lt;&gt;();
        pList.add(new Point(1, 2));
        pList.add(new Point(3, 4));
        System.out.println(pList.size());
        pList.remove(new Point(3, 4));
    }
}

答案1

得分: 8

你的 Point 类没有重写 equals 方法,而 remove 方法将使用该方法来判断项目是否在列表中。如果你将 new Point(3,4) 值保存到一个局部变量中,它将被移除,因为它是身份相等的。或者你可以重写 equalshashcode 方法。

英文:

You Point class does not override the equals method, which the remove method will use to determine whether or not the item is in the list. If you save your new Point(3,4) value into a local variable it will be removed because it is identity equal. Or you can override equals and hashcode.

答案2

得分: 1

如@sam指出的那样,这里有一个使用hashCode和equals的示例:

public class Test {
  private static class Point {
    private int x, y;

    Point(int x, int y) {
      this.x = x;
      this.y = y;
    }

    @Override
    public int hashCode() {
      return x * y;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Point) {
        Point p = (Point) o;
        return p.x == x && p.y == y;
      }
      return false;
    }
  }

  public static void main(final String[] args) {
    List<Point> pList = new ArrayList<>();
    pList.add(new Point(1, 2));
    pList.add(new Point(3, 4));
    System.out.println(pList.size());
    pList.remove(new Point(3, 4));
    System.out.println(pList.size());
  }
}
英文:

As @sam points out, here's an example with hashCode and equals:

public class Test {
  private static class Point {
    private int x, y;

    Point(int x, int y) {
      this.x = x;
      this.y = y;
    }

    @Override
    public int hashCode() {
      return x * y;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Point) {
        Point p = (Point) o;
        return p.x == x &amp;&amp; p.y == y;
      }
      return false;
    }
  }

  public static void main(final String[] args) {
    List&lt;Point&gt; pList = new ArrayList&lt;&gt;();
    pList.add(new Point(1, 2));
    pList.add(new Point(3, 4));
    System.out.println(pList.size());
    pList.remove(new Point(3, 4));
    System.out.println(pList.size());
  }
}

答案3

得分: 0

你需要重写 equalshashcode 方法。

  @Override
  public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      Point point = (Point) o;
      return x == point.x && y == point.y;
   }
   
   @Override
   public int hashCode() {
      return Objects.hash(x, y);
   }   
英文:

You need to override both equals and hashcode methods.

  @Override
  public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      Point point = (Point) o;
      return x == point.x &amp;&amp; y == point.y;
   }
   
   @Override
   public int hashCode() {
      return Objects.hash(x, y);
   }   

答案4

得分: 0

请参考 https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove(java.lang.Object) 获取ArrayList.remove()的预期行为。两个版本的"new Point(3, 4)"在堆上创建了不同的对象,因此它们具有不同的引用;由于Point类没有覆盖equals方法,比较没有找到匹配。

如果你满足以下条件,remove方法将会有你期望的行为:

    Point p = new Point(3, 4);
    pList.add(p);
    pList.remove(p);

或者你可以通过以下方式覆盖Point类中的equals方法:

	@Override
	public boolean equals(Object other) {
	    if (other == null) return false;
	    if (this == other) return true;
	    if (!(other instanceof Point)) return false;
	    Point otherPoint = (Point) other;
	    return x == otherPoint.x && y == otherPoint.y;
	}

另请参考:https://www.geeksforgeeks.org/equals-hashcode-methods-java/

英文:

Refer to https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove(java.lang.Object)
for the expected behavior of ArrayList.remove(). The two incarnations of "new Point(3, 4)" create different objects on the heap so they have different references, and since the Point class does not override the equals method, the comparison does not find a match.

The remove method will have the behavior you expect if either you have

    Point p = new Point(3, 4);
    pList.add(p);
    pList.remove(p);

or you override the equals method in the class Point with something like:

	@Override
	public boolean equals(Object other) {
	    if (other == null) return false;
	    if (this == other) return true;
	    if (!(other instanceof Point)) return false;
	    Point otherPoint = (Point) other;
	    return x == otherPoint.x &amp;&amp; y == otherPoint.y;
	}

See also: https://www.geeksforgeeks.org/equals-hashcode-methods-java/

答案5

得分: 0

虽然从技术上讲,您的问题已经有了正确的答案,但我想补充一些解释。

您的程序在以下几行中创建了三个 Point 实例(使用 new Point(...)):

public static void main(final String[] args) {
  List<Point> pList = new ArrayList<>();
  pList.add(new Point(1, 2));       // <-- 这是第一个实例
  pList.add(new Point(3, 4));       // <-- 这是第二个实例
  System.out.println(pList.size());
  pList.remove(new Point(3, 4));    // <-- 这是第三个实例
  System.out.println(pList.size());
}

第二个和第三个实例恰好具有相同的 xy 值,但这对于 Java 的库函数来说还不足以让它们在某种意义上被视为相等。从本质上讲,只有当两个实例实际上是对同一个实例的引用时(例如,如果您将第二个 Point 保存到一个局部变量中,并将其用于删除),它们才是相等的。

使用您的代码,尝试移除第三个 Point 会发现列表中并没有(完全)相同的 Point,因此不会执行任何操作。

但是您可以在 Point 类中编写一个 equals() 方法,在该方法中定义您希望在什么情况下将两个不同的 Point 视为相等。通常情况下,您可以在该方法中比较 xy

示例可以在其他答案中找到。或者,如果您使用诸如 Eclipse 之类的集成开发环境,您会找到一个名为“create hashCode() and equals()”的功能,它会为您编写一个完美的 equals() 方法,包括所有可能会被随意忽略的边界情况。

hashCode() 是什么鬼?为了支持除了 ArrayList(例如 HashMap)之外的不同数据结构,特定的 equals() 方法应该总是伴随一个匹配的 hashCode() 方法。

英文:

Although technically your question already has correct answers, I'd like to add some explanation.

Your program creates three Point instances (using new Point(...)) in the following lines:

  public static void main(final String[] args) {
    List&lt;Point&gt; pList = new ArrayList&lt;&gt;();
    pList.add(new Point(1, 2));       // &lt;-- Here is the first one
    pList.add(new Point(3, 4));       // &lt;-- Here is the second one
    System.out.println(pList.size());
    pList.remove(new Point(3, 4));    // &lt;-- Here is the third one
    System.out.println(pList.size());
  }

The second and third happen to have the same x and y values, but that isn't enough for Java's library functions to understand that they are equal in whatever sense. Per se, two instances are only equal if they are actually two references to the very same instance (e.g. if you saved your second Point to a local variable and used that for the removal).

With your code, trying to remove the third Point finds out that (exactly) this Point isn't on the list, and does nothing.

But you can write an equals() method in your Point class where you define, under which circumstances you want two different Points to be regarded as equal. You'd typically have this method compare x and y.

Examples can be seen in other answers. Or, if you use an IDE like Eclipse, you'll find a function named "create hashCode() and equals()" that writes a perfect equals() method for you, including all the corner cases that one might casually forget to cover.

WTF is hashCode()? To support different data structures besides ArrayList (e.g. HashMap), a specific equals() method should always be accompanied by a matching hashCode() method.

huangapple
  • 本文由 发表于 2020年8月14日 21:29:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/63413740.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定