将ArrayList的内容放入PriorityQueue Java Issue

时间:2017-04-17 15:22:04

标签: java arraylist nodes priority-queue

我有以下代码导致问题:

List<Node> tempList=new ArrayList<Node>(); //baseline
//creation of another temporary list of type Node for temporary storage
List<Node> tempList2=new ArrayList<Node>();

List<Node> temp = Adjacency_List.get(current.dest);
for(Node node: temp){
    //testing
    System.out.print(current.dest + " - " + node.dest);
        System.out.println("\t\t("+Main.getEdge(current, node)+")");

    for(int i=0; i<tempList.size(); i++){
        //copying nodes from tempList into tempList2
        tempList2.add(tempList.get(i));
        System.out.println("TEMP LIST2 : "+tempList2.size());
    }

    tempList2.add(node);
    System.out.println("TEMP LIST2 SIZE : "+tempList2.size());
    cost=tempCost;
    cost+=Main.getEdge(current, node);
    n=new Node(tempList2, cost);
    pq.add(n);
    tempList2.clear();
}

该代码的基本目标是获取当前节点的子节点(通过使用current.dest),并且对于temp中的每个节点,它将tempList的内容复制到tempList2(tempList也包含节点)。在将tempList2的内容添加到优先级队列pq(pq.add(n))然后使用tempList2.clear()清除之后出现问题。优先级队列pq中的tempList2的内容也被该行清除。有没有办法可以清除tempList2数组列表的内容而不同时清除优先级队列中的tempList2的内容(之前通过使用行pq.add(n)添加到优先级队列中)?)?

2 个答案:

答案 0 :(得分:1)

是的,这是可能的。

解决方案1 ​​

添加列表副本而不是原始列表本身。在clear()原件后,副本将保持不变。 变化

n = new Node(tempList2, cost);

n = new Node(new ArrayList<>(tempList2), cost);

解决方案2

创建新列表而不是在每次迭代中复制和清除相同列表可能更好(对于效率和可读性而言)。删除

tempList2.clear();

并移动

List<Node> tempList2 = new ArrayList<Node>();

到第一个循环的主体,这样你就可以在每次迭代中创建一个新的列表。

答案 1 :(得分:1)

当您将n添加到pq时,您正在创建别名:您添加的n的列表字段指的是到tempList2引用的完全相同的实例。按理说,如果通过调用clear()来改变该实例,那么你的队列也会丢失这些元素。

有两种方法可以避免别名:

  1. 在插入之前将列表复制到新列表,每次插入都会产生O(N)性能损失(其中N是tempList的长度)。
  2. 创建一个新的空列表实例,并将其分配给tempList2,而不是在每次迭代时使用clear(),从而导致O(1)惩罚。
  3. 我应该指出,如果tempList非空,那么使用tempList2的循环将其复制到get()会浪费大量周期。 addAll()方法通常更有效。