我已经用Java编写了2种方法。第二种方法对我来说看起来更干净,因为我来自python背景,但是我认为它会比第一种方法慢,因为indexOf()也可以进行迭代吗?有没有办法在这种情况下正确地用于循环?另外,如果有更好的方法(没有Streams),该怎么办?
private ArrayList<MyObject> myObjects;
第一种方法:
private int findObject(String objectName) {
for(int i=0; i<this.myObjects.size(); i++) {
MyObject myObject = this.myObjects.get(i);
if(myObject.getName().equals(objectName)) return i;
}
return -1;
}
第二种方法:
private int findObject(String objectName) {
for(MyObject myObject: this.myObjects) {
if(myObject.getName().equals(objectName)) return this.myObjects.indexOf(myObject);
}
return -1;
}
更好的方法(这样可以避免您必须维护单独的索引变量;并且也适用于非RandomAccess
列表)将使用ListIterator
:
for (ListIterator<MyObject> it = myObjects.listIterator(); it.hasNext();) {
MyObject myObject = it.next();
if(myObject.getName().equals(objectName)) return it.prevIndex();
}
return -1;
我认为它会比第一个慢,因为indexOf()也会进行迭代吗?
您是正确的。
在这种情况下是否可以正确使用
for each
循环?
您可以使用for each
和索引变量。
private int findObject(String objectName) {
int i = 0;
for (MyObject myObject: this.myObjects) {
if (myObject.getName().equals(objectName)) return i;
i++;
}
return -1;
}
如果myObjects.get(i)
是昂贵的操作(例如,在LinkedList中)...或无法实现,这将是一个很好的解决方案。
第一个版本是完美的如果您知道您正在使用ArrayList(或其他一些基于数组的列表,例如Vector)。
如果myObject
恰好是LinkedList
或类似名称,则列表越长,性能就会越差,因为get(i)
不再按固定时间执行。
您的第二种方法将同时处理LinkedList
和ArrayList
,但在列表上进行两次迭代,一次在for
循环中,一次在indexOf()
调用中。
我建议使用第三种版本:使用第二种方法中的for循环,并添加一个整数计数变量,并在循环内递增。这样,您将获得两者的优点:在不降低性能的情况下进行迭代以及廉价的头寸计数。