我正试图编写一个函数来更改一个通用列表,但是发生了一些非常奇怪的事情。如果我用数组替换所有的列表,那么下面的代码结构可以工作,但实际上,代码只需打印1、2、3次。为什么会这样呢?我认为这与通过价值传递还是参考传递有关。
//Main.java
import java.util.ArrayList;
import java.util.Set;
import java.util.List;
public class Main {
public static void main (String ... args) {
ArrayList<Integer> AL = new ArrayList<Integer>();
AL.add(1);
AL.add(2);
AL.add(3);
Permute<Integer> perm = new Permute<Integer>();
Set<List<Integer>> set = perm.listPermutations(AL);
for (List<Integer> lst : set) {
System.out.println(lst);
}
}
}
//Permute.java
import java.util.List;
import java.util.Set;
import java.util.HashSet;
public class Permute<E> {
public Set<List<E>> listPermutations(List<E> lst) {
Set<List<E>> perms = new HashSet<List<E>>();
permute(lst, 0, perms);
return perms;
}
private void permute(List<E> lst, int start, Set<List<E>> perms) {
if (start >= lst.size()) {
// nothing left to permute
perms.add(lst);
}
for (int i = start; i < lst.size(); i++) {
// swap elements at locations start and i
swap(lst, start, i);
permute(lst, start + 1, perms);
swap(lst, start, i);
}
}
private void swap(List<E> lst, int x, int y) {
E temp = lst.get(x);
lst.set(x, lst.get(y));
lst.set(y, temp);
}
}发布于 2014-09-13 05:40:04
当您调用permute时,您永远不会创建新的List。lst是对List的引用,该引用传递给所有递归调用,结果是将相同的引用添加到集合6次。通常,向集合添加相同的引用6次意味着Set只包含一个元素。
它似乎有6个元素的原因是因为在将List添加到哈希之后修改了它的内容,这是您不应该使用HashMap或HashSet做的事情。如果将对象引用添加到HashMap或HashSet,然后以更改哈希代码的方式修改对象,则会导致哈希操作混乱。
正因为如此,相同的引用以六种不同的哈希代码被添加到集合中六次。但它们仍然都是对同一个List的引用,这意味着当您打印出它们时,它们都会显示为相同的。
在递归调用List之前,需要创建permute的副本。如果permute知道List是一个ArrayList是可以的,您可以这样说
List<E> newList = new ArrayList<>(lst);然后使用newList执行第一个newList,然后将newList传递给递归调用。(可能不再需要第二个swap了。)
如果要创建一个类型与源列表类型相同的newList .我不确定是否有一种简单的方法,除了使用反射。
https://stackoverflow.com/questions/25820073
复制相似问题