0

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 が影響を受けます。私はこれが起こることを望んでいません。誰か助けてください!:(

4

1 に答える 1

0

Java で参照と変数がどのように機能するかについて、いくつかの基本的な誤解があります。new通常、 with のようなキーワードが表示された場合にのみ、新しいオブジェクトを作成します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();

2 次元配列とほとんど同じです。1つだけ作成し、それを割り当てて、後でコード内で指しているのと同じ配列lを指しています。その後、いくつかの値をコピーしますが、実際には同じ配列オブジェクトとの間で値をコピーします。これはまた完全にナンセンスです。ループの上にラインを押し込むと、きっと驚かれることでしょう。glSystem.out.println(this.g[2][1]);for

this SO answer which @RCを見てください。彼のコメントに投稿されました。それはあなたの誤解の原因に対処しています。

于 2012-09-02T09:42:38.377 に答える