列表过程中的无限循环

时间:2018-10-02 08:27:24

标签: java arraylist

我有以下代码块:

ArrayList<ELPERouteStop> candidates = new ArrayList<>();
    for (int i=0; i < metric.length;i++) 
    {

        /*
         * We get a from object for each row (customer) and a to object for the element
         * of the matrix with the highest metric from the ith customer.
         */
        ELPERouteStop from = all_stops.get(i);
        ELPERouteStop to = all_stops.get(getMaxValue(metric[i]));
        if(i==0)
        {   
            candidates.add(from);
            candidates.add(to);
        }
        for (int j=0; j < candidates.size();j++)
        {
            int k=0;
            if (candidates.get(j) == from || candidates.get(j)==to) 
            {
                k++;
            }
            if (k == 0)
            {
                candidates.add(from);
                candidates.add(to);
            }
        }
    }

问题似乎出在每次迭代中候选列表大小的变化。 我需要将from和to对象插入候选列表,仅当它们尚不存在时。因此,我在第二个for循环中进行检查。 当我运行代码时,它似乎进入了无限循环,而我找不到原因。 预先谢谢你!

5 个答案:

答案 0 :(得分:3)

您可以使用Collection#contains而不是每次都迭代集合。

List<ELPERouteStop> candidates = new ArrayList<>();
for (int i=0; i < metric.length;i++) {

    ELPERouteStop from = all_stops.get(i);
    ELPERouteStop to = all_stops.get(getMaxValue(metric[i]));

    if (!candidates.contains(from) && !candidates.contains(to)) {
        candidates.add(from);
        candidates.add(to);
    }
}

或者,效率更高一点-取决于getMaxValue的速度:

for (int i=0; i < metric.length;i++) {

    ELPERouteStop from = all_stops.get(i);
    if (!candidates.contains(from)) {
        ELPERouteStop to = all_stops.get(getMaxValue(metric[i]));
        if (!candidates.contains(to)) {
            candidates.add(from);
            candidates.add(to);
        }
    }
}

答案 1 :(得分:2)

Reason for infinite loop is this conditional statement if (candidates.get(j) == from || candidates.get(j)==to) . As you are using == operator to compare the objects it always returns false because == operator always used to compare the reference of the objects not the values. So k value is increasing exponentially on every iteration so that it leads to infinte looping.for more details about the == and equals() method

Solution:

To compare the objects in collection you can use contains(). But for comparing objects you need to override the equals method in ELPERouteStop class.

For sample refer:

class Test{

String a;

Test(String a){
    this.a = a;
}
@Override
public boolean equals(Object obj) {
        return (this.a.equals( ((Test)obj).a));
}

}

public static void main(String[] args) {

    ArrayList<Test> arr = new ArrayList<Test>(4); 

    Test a = new Test("abc");

    arr.add(new Test("abc")); 

    boolean test = a == new Test("abc"); // Returns false due to reference checking

    boolean ans = arr.contains(a); // returns true as this checks with the value  

}

答案 2 :(得分:1)

I need to insert the from and to objects to the candidates list, only if they don't exist already.似乎是Set的很好的候选人。您可以尝试使用Set代替List,然后让数据结构本身为您实现该约束。如果采用这种方法,请确保为对象覆盖equalshashCode方法。

答案 3 :(得分:0)

如果订单很重要:

ArrayList<ELPERouteStop> candidates = new ArrayList<>();
        for (int i=0; i < metric.length;i++) 
        {

            /*
             * We get a from object for each row (customer) and a to object for the element
             * of the matrix with the highest metric from the ith customer.
             */
            ELPERouteStop from = all_stops.get(i);
            ELPERouteStop to = all_stops.get(getMaxValue(metric[i]));
            if(i==0)
            {   
                candidates.add(from);
                candidates.add(to);
            }
            else if(!candidates.contains(from)&&!candidates.contains(to))
            {
                    candidates.add(from);
                    candidates.add(to);
            }
        }

如果顺序无关紧要:

Set<ELPERouteStop> candidates = new hashset<>();
        for (int i=0; i < metric.length;i++) 
        {

            /*
             * We get a from object for each row (customer) and a to object for the element
             * of the matrix with the highest metric from the ith customer.
             */
            ELPERouteStop from = all_stops.get(i);
            ELPERouteStop to = all_stops.get(getMaxValue(metric[i]));
       //comment out to optimize
            //if(i==0)
            //{   
            //  candidates.add(from);
            //  candidates.add(to);
            //}
              candidates.add(from);
             candidates.add(to);
        }

答案 4 :(得分:0)

由于两个循环都是for循环,因此不可能输入无限循环。

您确定程序已在此块中停止吗?

我猜可能是由于性能低下导致它看起来像一个无限循环,请尝试减小metric的大小,然后再次运行以查看程序是否可以停止。

您还可以使用Set这样优化代码:

// first declare a set:
Set<int> candidatesSet = new HashSet<>();

// and after added each from/to to `candidates`
candidatedSet.add(from.hashCode())

// replace you second loop with
if (!candidatedSet.contains(from.hashCode()) && !candidatedSet.contains(to.hashCode())) {
    candidates.add(from);
    candidates.add(to);
    candidatedSet.add(from.hashCode());
    candidatedSet.add(to.hashCode());
}

当然,您需要确保hashCode 为每个不同的候选人返回不同的int