遍历 List 时出现 ConcurrentModificationException,尽管没有修改它
ConcurrentModificationException while iterating through List, altough not modifying it
我有以下代码(更新:我添加了完整代码)
public class Triangle {
private Vertex2D a;
private Vertex2D b;
private Vertex2D c;
private boolean divided = false;
public static ArrayList<Triangle> triangles = new ArrayList<>();
public static ArrayList<Triangle> newTriangles = new ArrayList<>();
public Triangle(Vertex2D a, Vertex2D b, Vertex2D c) {
this.a = a;
this.b = b;
this.c = c;
triangles.add(this);
}
public Triangle(Vertex2D a, Vertex2D b, Vertex2D c, int depth) {
this(a,b,c);
if (depth > 0) {
divide(depth);
}
}
public Vertex2D getVertexA() {
return a;
}
public Vertex2D getVertexB() {
return b;
}
public Vertex2D getVertexC() {
return c;
}
public boolean isDivided() {
return divided;
}
public Triangle getSubTriangle(int i) {
if ((!isDivided()) || (i > (triangles.size() - 1))) {
return null;
}
return triangles.get(i);
}
public boolean divide() {
if (isDivided()) {
return false;
}
Vertex2D ac = new Vertex2D((getVertexA().getX() + getVertexC().getX()) / 2, (getVertexA().getY() + getVertexC().getY()) / 2);
Vertex2D bc = new Vertex2D((getVertexB().getX() + getVertexC().getX()) / 2, (getVertexB().getY() + getVertexC().getY()) / 2);
Vertex2D ab = new Vertex2D((getVertexA().getX() + getVertexB().getX()) / 2, (getVertexA().getY() + getVertexB().getY()) / 2);
Triangle t1 = new Triangle(a, ab, ac);
Triangle t2 = new Triangle(ab, b, bc);
Triangle t3 = new Triangle(ac, bc, c);
newTriangles.add(t1);
newTriangles.add(t2);
newTriangles.add(t3);
divided = true;
return true;
}
public boolean divide(int depth) {
if (depth == 0) return false;
while (depth > 0) {
newTriangles.clear();
for (Iterator<Triangle> iterator = triangles.iterator(); iterator.hasNext();) {
Triangle t = iterator.next();
t.divide();
}
triangles.addAll(newTriangles);
divide(depth-1);
return true;
}
return true;
}
}
顶点二维:
public class Vertex2D {
private double x;
private double y;
public Vertex2D(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double distance(Vertex2D v) {
if (v == null) return -1.0;
return Math.sqrt(Math.pow(this.x - v.getX(),2.0) + Math.pow(this.y - v.getY(),2.0));
}
public String toString() {
return "[" + x + ", " + y + "]";
}
}
调用方法
public static void main(String[] args) {
Vertex2D a = new Vertex2D(-100,0);
Vertex2D b = new Vertex2D(0,100);
Vertex2D c = new Vertex2D(100,-100);
try {
Triangle triangle = new Triangle(a, b, c, 3);
} catch (ConcurrentModificationException e) {
e.printStackTrace();
}
}
每次 运行 我都会收到 ConcurrentModificationException。现在,我知道,这个问题已经在这里讨论了很多次,但是抛出这个异常的原因总是在迭代列表中的 adding/removing 元素中,而事实并非如此。在我的递归方法中,我创建了空的临时列表,并且通过迭代我只向临时列表添加新元素,而迭代列表保持不变,直到迭代结束。但我仍然得到例外。为什么是这样?
前几天我有一些类似的经历,我发现你应该使用迭代器而不是 foreach
for (Iterator<Triangle> iterator = triangles.iterator(); iterator.hasNext();) {
Triangle t = iterator.nect();
t.divide();
}
遍历三角形时:
for (Iterator<Triangle> iterator = triangles.iterator(); iterator.hasNext();) {
Triangle t = iterator.next();
t.divide(); //in divide you add new triangle to triangles
}
您在方法 divide() 中修改了构造函数中的三角形:
divide() {
//....
Triangle t1 = new Triangle(a, ab, ac);
//...
}
public Triangle(Vertex2D a, Vertex2D b, Vertex2D c) {
this.a = a;
this.b = b;
this.c = c;
triangles.add(this); //this is the place where you modify triangles
}
我有以下代码(更新:我添加了完整代码)
public class Triangle {
private Vertex2D a;
private Vertex2D b;
private Vertex2D c;
private boolean divided = false;
public static ArrayList<Triangle> triangles = new ArrayList<>();
public static ArrayList<Triangle> newTriangles = new ArrayList<>();
public Triangle(Vertex2D a, Vertex2D b, Vertex2D c) {
this.a = a;
this.b = b;
this.c = c;
triangles.add(this);
}
public Triangle(Vertex2D a, Vertex2D b, Vertex2D c, int depth) {
this(a,b,c);
if (depth > 0) {
divide(depth);
}
}
public Vertex2D getVertexA() {
return a;
}
public Vertex2D getVertexB() {
return b;
}
public Vertex2D getVertexC() {
return c;
}
public boolean isDivided() {
return divided;
}
public Triangle getSubTriangle(int i) {
if ((!isDivided()) || (i > (triangles.size() - 1))) {
return null;
}
return triangles.get(i);
}
public boolean divide() {
if (isDivided()) {
return false;
}
Vertex2D ac = new Vertex2D((getVertexA().getX() + getVertexC().getX()) / 2, (getVertexA().getY() + getVertexC().getY()) / 2);
Vertex2D bc = new Vertex2D((getVertexB().getX() + getVertexC().getX()) / 2, (getVertexB().getY() + getVertexC().getY()) / 2);
Vertex2D ab = new Vertex2D((getVertexA().getX() + getVertexB().getX()) / 2, (getVertexA().getY() + getVertexB().getY()) / 2);
Triangle t1 = new Triangle(a, ab, ac);
Triangle t2 = new Triangle(ab, b, bc);
Triangle t3 = new Triangle(ac, bc, c);
newTriangles.add(t1);
newTriangles.add(t2);
newTriangles.add(t3);
divided = true;
return true;
}
public boolean divide(int depth) {
if (depth == 0) return false;
while (depth > 0) {
newTriangles.clear();
for (Iterator<Triangle> iterator = triangles.iterator(); iterator.hasNext();) {
Triangle t = iterator.next();
t.divide();
}
triangles.addAll(newTriangles);
divide(depth-1);
return true;
}
return true;
}
}
顶点二维:
public class Vertex2D {
private double x;
private double y;
public Vertex2D(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double distance(Vertex2D v) {
if (v == null) return -1.0;
return Math.sqrt(Math.pow(this.x - v.getX(),2.0) + Math.pow(this.y - v.getY(),2.0));
}
public String toString() {
return "[" + x + ", " + y + "]";
}
}
调用方法
public static void main(String[] args) {
Vertex2D a = new Vertex2D(-100,0);
Vertex2D b = new Vertex2D(0,100);
Vertex2D c = new Vertex2D(100,-100);
try {
Triangle triangle = new Triangle(a, b, c, 3);
} catch (ConcurrentModificationException e) {
e.printStackTrace();
}
}
每次 运行 我都会收到 ConcurrentModificationException。现在,我知道,这个问题已经在这里讨论了很多次,但是抛出这个异常的原因总是在迭代列表中的 adding/removing 元素中,而事实并非如此。在我的递归方法中,我创建了空的临时列表,并且通过迭代我只向临时列表添加新元素,而迭代列表保持不变,直到迭代结束。但我仍然得到例外。为什么是这样?
前几天我有一些类似的经历,我发现你应该使用迭代器而不是 foreach
for (Iterator<Triangle> iterator = triangles.iterator(); iterator.hasNext();) {
Triangle t = iterator.nect();
t.divide();
}
遍历三角形时:
for (Iterator<Triangle> iterator = triangles.iterator(); iterator.hasNext();) {
Triangle t = iterator.next();
t.divide(); //in divide you add new triangle to triangles
}
您在方法 divide() 中修改了构造函数中的三角形:
divide() {
//....
Triangle t1 = new Triangle(a, ab, ac);
//...
}
public Triangle(Vertex2D a, Vertex2D b, Vertex2D c) {
this.a = a;
this.b = b;
this.c = c;
triangles.add(this); //this is the place where you modify triangles
}