-2

私の質問は、参照する舞台裏についてです:)

そのため、特定のArrayList(getPermsOfMe)のすべての順列を見つけるための再帰的な実装を作成しようとしていました。私が質問している2つの特定の行にLOOKHEREを書きました。thisPermをallPermutationsに追加し、コードの後半でthisPermを変更しました。これにより、allPermutationsで以前に追加された値が新しい値に変更されました。

public ArrayList<ArrayList<Integer>> allPermsHelper(ArrayList<Integer> getPermsOfMe, ArrayList<ArrayList<Integer>> allPermutations, ArrayList<Integer> thisPerm){
    if (getPermsOfMe.isEmpty()){
        System.out.println("thisPerm = " + thisPerm);
        allPermutations.add(thisPerm); //LOOK HERE
        System.out.println("allPermutations = " +allPermutations);
    }
    else {
        for (int i = 0; i<ofMe.size(); i++){

            //swapping the two specified elements in getPermsOfMe
            x = getPermsOfMe.get(i);
            getPermsOfMe.set(i, getPermsOfMe.get(getPermsOfMe.size()-1));
            getPermsOfMe.set(getPermsOfMe.size()-1, x);

            if (thisPerm.isEmpty()){
                thisPerm.add(getPermsOfMe.remove(getPermsOfMe.size()-1));
            }
            else{
                thisPerm.add(0,getPermsOfMe.remove(getPermsOfMe.size()-1));
            }

            allPermsHelper(getPermsOfMe, allPermutations, thisPerm);  
            getPermsOfMe.add(0,thisPerm.remove(0)); // LOOK HERE
        }
    } 
    return allPermutations;
}

//an example output (if getPermsOfMe was [123]):
thisPerm = [123]
allPermutations = [[123]]
thisPerm = [231]
allPermutations = [[231],[231]]
thisPerm = [321]
allPermutations = [[321],[321],[321]]
... 

myQuestionは、(オブジェクトと参照に関して)正確に前の値が追加された後も変更されない理由です。そこで最初に[123]を追加しました。次に[231]を追加しましたが、allPermuationsは[[123][231]]ではなく[[231][231]]でした。

また、一度追加すると値が保持されないのは少し直感に反しているようです。Java(および他のいくつかの言語を想定しているim)がこのようにした理由はありますか?

スタックオーバーフローについて質問するのはこれが初めてなので、質問を簡単にするために何かする必要がある場合、または私に知らせてください。

4

2 に答える 2

0

了解しました。わかりました:)より良いサンプルコードを次に示します。

    ArrayList<Integer> list = new ArrayList<Integer>();
    ArrayList<ArrayList<Integer>> listOfList = new ArrayList<ArrayList<Integer>>();
    list.add(13);
    list.add(42);
    listOfList.add(list);
    System.out.println("list = " + list);
    System.out.println("listOfList = " + listOfList);

    list1.add(46);
    System.out.println("list = " + list);
    System.out.println("listOfList = " + listOfList);

出力があります:

list = [13, 42]
listOfList = [[13, 42]]
list = [13, 42, 46]
listOfList = [[13, 42, 46]]

そして、あなたはそれが次のようになることを期待しています:

list = [13, 42]
listOfList = [[13, 42]]
list = [13, 42, 46]
listOfList = [[13, 42]]

Javaでは、リストはオブジェクトのコレクションです(または、プリミティブの場合もありますが、この場合は、オブジェクトのリストであるリストのリストに焦点を当てています)。オブジェクトには変更可能なデータが含まれています。高校の生徒のリストがあり、生徒を変更した場合、それらを直接そこに入れるすべてのリストで生徒を変更するべきではありませんか?したがって、Javaは、舞台裏でメモリポインタを使用することにより、そのように機能します。静的な高校の生徒のリストを作成する場合は、すべての生徒のクローンを作成してから、それらをリストに追加する必要があります。同様に、Javaでは、オブジェクトの変更がリストに影響を与えないように、オブジェクトのクローンを作成する必要があります。

于 2012-11-05T01:10:46.227 に答える
0

方法:舞台裏では、に収まるものはすべてObject単なる参照であり、これにはリストと配列が含まれます。intこれは、やなどのプリミティブとは異なりdoubleます。

int primitive = 14;
int anotherPrimitive = primitive;
System.out.println(anotherPrimitive); // 14
primitive = 12;
System.out.println(anotherPrimitive); // still 14

String[] array = new String[] {"this is a string in the array"};
String[] anotherArray = array;
System.out.println(anotherArray); // ["this is a string in the array"]
array[0] = "now i've changed it";
System.out.println(anotherArray); // ["now i've changed it"]

ArrayListaがオブジェクトの一種であり、オブジェクト参照を格納しているのはたまたまです。これは、それが指しているオブジェクトを変更すると、リスト内で変更されることを意味します。

理由:ユーザーが明示的に要求せずにオブジェクトグラフ全体を自動的にコピーすることはあまり意味がありません。参照は、保存するのに非常に安価であり(メモリに4バイトまたは8バイト)、コピーするのに非常に安価です(多くの場合、1プロセッササイクルかかります)。double誰かが入力するたびに1000の配列をコピーするdoubleList.add(aThousandDoubles);と、多くの時間とメモリが不必要に浪費される可能性があります。さらに、別の参照は必要ないかもしれません。おそらくあなたはを持っていて、リストにアイテムを追加するたびに実装がオブジェクトをコピーするとList<Foo> monitoredFoos、変更を読み取ることができなくなります。List

addしたがって、既存のインスタンスへの参照をに格納するだけのナイーブな実装があり、オブジェクトをコピーする必要がある場合にのみ、オブジェクトをコピーするのはプログラマーに任せるのが理にかなっています。

于 2012-11-05T01:13:25.527 に答える