我有以下代码块:
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循环中进行检查。 当我运行代码时,它似乎进入了无限循环,而我找不到原因。 预先谢谢你!
答案 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
,然后让数据结构本身为您实现该约束。如果采用这种方法,请确保为对象覆盖equals
和hashCode
方法。
答案 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