您好
我已经编写了这段代码,通过输出你可以得到.remove()
方法不起作用。 a
,b
,c
和d
是Points
个拥有x
和y
成员的对象。
以下是a and b and c and d
值,必须在upper
中删除if语句,但不会删除。
X :59 Y: 143
X :165 Y: 140
X :59 Y: 143
X :165 Y: 140
System.out.println(upper.toString());
for(int i =0;i<upper.size();i++)
if(upper.get(i)==a||upper.get(i)==b||upper.get(i)==c||upper.get(i)==d){
upper.remove(i);
}
for(int i =0;i<lower.size();i++)
if(lower.get(i)==a||lower.get(i)==b||lower.get(i)==c||lower.get(i)==d){
upper.remove(i);
}
System.out.println(upper.toString());
System.out.println(lower.toString());
first println : [X :108 Y: 89, X :165 Y: 140]
second println: [X :108 Y: 89, X :165 Y: 140]
third println : [X :105 Y: 191]
答案 0 :(得分:7)
如果我正确地阅读你的问题,你假设==
将比较两个对象的属性。它没有,这就是equals
所做的。 ==
告诉您两个引用是否属于相同对象实例,而不是等效对象实例。
例如:
public class Foo {
public Foo(int x, int y) {
this.x = x;
this.y = y;
}
@override
public boolean equals(Object other) {
Foo otherFoo;
if (other == null || !(other instanceof Foo)) { // or you might be more restrictive
return false;
}
otherFoo = (Foo)other);
return otherFoo.x == this.x && otherFoo.y == this.y;
}
@override
public int hashCode() {
// ...appropriate implementation of hashCode...
}
}
Foo a = new Foo(0, 0);
Foo b = new Foo(0, 0);
System.out.println(a == b); // "false"
System.out.println(a.equals(b)); // "true"
另外:考虑当你必须删除ArrayList
中的两个连续匹配对象时会发生什么。假设他们在列表中的索引8和9处。因此,当i == 8
时,您会删除索引8
处的项目,而曾经位于9
的项目现在位于8
。但是,然后在for循环中递增i
并继续索引9
处的新项目,而保持第二个不变。如果要在循环中修改列表,请考虑向后循环以避免这种情况,或使用Iterator
。
答案 1 :(得分:4)
这里有两个问题。首先,您在迭代时从列表中删除对象。这不是一个好主意。
其次,我认为你误解了@T.J. Crowder中提到的Java中的==
运算符。
这是一种更好的方式来做你想做的事情(修复equals
问题后):
List<Point> mypoints = new ArrayList();
mypoints.add(a);
mypoints.add(b);
mypoints.add(c);
mypoints.add(d);
List<Point> otherPoints = new ArrayList();
for(Point p: upper)
for(Point myPoint: mypoints)
{
if(p.equals(myPoint))
break;
otherPoints.add(p);
}
upper = otherPoints;
另一种实现(仅当upper
为Set
时才有效,因为它不会捕获重复项):
List<Point> mypoints = new ArrayList();
mypoints.add(a);
mypoints.add(b);
mypoints.add(c);
mypoints.add(d);
for(Point myPoint: mypoints)
{
upper.remove(myPoint);
}
答案 2 :(得分:0)
正如Eric所暗示的那样,列表的长度随着项目的删除而改变,刚刚删除的元素之后的所有值的索引也是如此。
我不确定“较低”的含义是什么。我注意到循环遍历“较低”的循环尝试从“上部”删除元素。这是故意的吗?
这是我的解决方案,基于应从“上方”删除的“删除”点列表。也可以使用原始测试的样式,除了每个==检查必须用等号()检查替换。
如果从Point类中删除了equals(...)实现,则不会从“upper”中删除任何内容,因为测试用例故意使用原始a,b,c和d值的克隆。
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import org.junit.Test;
public class TestArrayList
{
@Test
public void testRemove()
{
// Test fixture:
Point a = new Point(115, 70);
Point b = new Point(139, 66);
Point c = new Point(195, 111);
Point d = new Point(144, 165);
List<Point> upper = new ArrayList<Point>();
upper.add(a.clone());
upper.add(b.clone());
upper.add(c.clone());
upper.add(d.clone());
List<Point> remove = new ArrayList<Point>();
remove.add(a.clone());
remove.add(b.clone());
remove.add(c.clone());
remove.add(d.clone());
// Assertions:
Assert.assertTrue(upper.size() == 4);
Assert.assertTrue(remove.size() == 4);
// Modified code:
System.out.println(upper.toString());
System.out.println(remove.toString());
for (Point p : remove)
{
upper.remove(p);
}
System.out.println(upper.toString());
System.out.println(remove.toString());
// Assertions:
Assert.assertTrue(upper.isEmpty());
Assert.assertTrue(remove.size() == 4);
}
}
class Point implements Cloneable
{
public int x;
public int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
@Override
public Point clone()
{
return new Point(x, y);
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
else if (o instanceof Point)
{
Point p = (Point) o;
return x == p.x && y == p.y;
}
else
{
return false;
}
}
@Override public String toString()
{
return "X: " + x + " Y: " + y;
}
}