我在处理HashSet时遇到了concurrentModificatoin异常,因此转移到了ConcurrentSkipListSet。虽然并发问题已经解决,但我现在遇到了一个新问题。看来ConcurrentSkipListSet默认是静态的。是这样的吗?我在一个递归函数中使用它,它有一个遍历相同的迭代器。当迭代下一个元素时,由于同一函数的另一个重复实例而产生的更改将反映在同一个对象中(在正常递归中通常不是这种情况,其中每个实例在堆栈中分配了自己的空间)。我不希望这些变化得到反映。有没有解决这个问题的方法?
提前致谢:)
我正在使用java,这是代码......
public class TSA {
int[][] l = { { 0, 1, 30, 65535 }, { 50, 0, 15, 5 }, { 65535, 65535, 0, 15 }, { 15, 65535, 5, 0 } };
int[][] g;
TSA() {
int n = 4;
this.g = this.l;
int k = 0;
ConcurrentSkipListSet a = new ConcurrentSkipListSet();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
this.g[i][j] = this.l[i][j];
}
}
System.out.println(this.g[2][1]);
a.add(2);
a.add(3);
a.add(4);
Iterator ir = a.iterator();
int[] path = new int[n];
k = 0;
while (ir.hasNext()) {
ConcurrentSkipListSet b = new ConcurrentSkipListSet();
b = a;
b.add(2);
b.add(3);
b.add(4);
int next = (Integer) ir.next();
System.out.println("next in main is " + next);
System.out.println("called with " + b);
path[k++] = this.l[0][next - 1] + gfun(next, b);
System.out.println("min path is..." + path[k - 1]);
}
}
public static void main(final String[] args) {
new TSA();
}
int gfun(final int next, final ConcurrentSkipListSet d) {
ConcurrentSkipListSet b = d;
if (b.size() != 1 && b.size() != 2) {
b.remove(next);
System.out.println(b);
int[] path = new int[b.size()];
int k = 0;
Iterator ir = b.iterator();
while (ir.hasNext()) {
int a = (Integer) ir.next();
System.out.println(a + " iterator prob " + b);
path[k] = this.l[next - 1][a - 1] + gfun(a, b);
System.out.println("path[" + k + "] is" + path[k]);
k = k + 1;
}
return min(path);
}
else if (b.size() == 2) {
System.out.println("second instance..." + next + ".." + b);
Iterator irrr = b.iterator();
int a = (Integer) irrr.next();
b.remove(next);
return (gfun(next, b));
}
else {
Iterator irr = b.iterator();
int j = (Integer) irr.next();
System.out.println("inside prog size is 1" + b);
System.out.println("l[" + next + "][" + j + "] is " + this.l[next - 1][j - 1]);
int ans = this.l[next - 1][j - 1] + this.g[j - 1][0];
System.out.println("l[" + next + "][" + j + "]+g[" + j + "][1] which is " + ans + " is r returned");
return (ans);
}
}
private int min(final int[] path) {
int m = path[0];
for (int i = 0; i < path.length; i++) {
if (path[i] < m) {
m = path[i];
}
}
return m;
}
}
我正在从集合b中删除元素,当函数返回到先前的状态(while循环内的迭代器)时,原始集合b会受到影响。我不希望这种情况发生。有人请帮忙! :(
答案 0 :(得分:0)
您对Java中的引用和变量的工作方式有一些基本的误解。一般情况下,当您看到与new
类似的new ConcurrentSkipListSet()
关键字时,您只会创建一个新对象。 (有一些特殊情况如何创建对象而不会看到一些new
关键字,但是你可以在第一时间省略它。)
从一个变量到另一个变量的所有赋值都不会创建新对象。您将变量分配给与另一个相同的对象。这些是对同一对象的引用。
您有以下代码:
while (ir.hasNext()) {
ConcurrentSkipListSet b = new ConcurrentSkipListSet();
b = a; // 'b' now refers to the same object as 'a'.
...
}
这是完全没有意义的。您创建一个新列表并将其放在下一行中,因为现在您将引用b
指向引用a
所指向的同一对象。
这就是为什么你实际上只使用你在所有代码中创建的列表对象的原因:
ConcurrentSkipListSet a = new ConcurrentSkipListSet();
你的二维数组非常相似。您只创建了一个,将其分配给l
并在代码中稍后指向同一个数组g
指向的l
。之后,您复制了一些值,但实际上您将值复制到SAME数组对象和从SAME数组对象复制值。这完全没有意义了。将行System.out.println(this.g[2][1]);
推到for
循环的顶部,我打赌你会感到惊讶。
看看this SO answer哪个@RC。张贴在他的评论中。它正在解决你误解的根源。