首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我如何在Java中更改一个泛型列表?

我如何在Java中更改一个泛型列表?
EN

Stack Overflow用户
提问于 2014-09-13 05:21:40
回答 1查看 828关注 0票数 1

我正试图编写一个函数来更改一个通用列表,但是发生了一些非常奇怪的事情。如果我用数组替换所有的列表,那么下面的代码结构可以工作,但实际上,代码只需打印1、2、3次。为什么会这样呢?我认为这与通过价值传递还是参考传递有关。

代码语言:javascript
复制
//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);
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-13 05:40:04

当您调用permute时,您永远不会创建新的Listlst是对List的引用,该引用传递给所有递归调用,结果是将相同的引用添加到集合6次。通常,向集合添加相同的引用6次意味着Set只包含一个元素。

它似乎有6个元素的原因是因为在将List添加到哈希之后修改了它的内容,这是您不应该使用HashMapHashSet做的事情。如果将对象引用添加到HashMapHashSet,然后以更改哈希代码的方式修改对象,则会导致哈希操作混乱。

正因为如此,相同的引用以六种不同的哈希代码被添加到集合中六次。但它们仍然都是对同一个List的引用,这意味着当您打印出它们时,它们都会显示为相同的。

在递归调用List之前,需要创建permute的副本。如果permute知道List是一个ArrayList是可以的,您可以这样说

代码语言:javascript
复制
List<E> newList = new ArrayList<>(lst);

然后使用newList执行第一个newList,然后将newList传递给递归调用。(可能不再需要第二个swap了。)

如果要创建一个类型与源列表类型相同的newList .我不确定是否有一种简单的方法,除了使用反射。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25820073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档