Reputation: 82
I have written 2 methods in Java. Second method looks cleaner to me because I come from python background, but I think it will be slower than first because indexOf() also does the iteration? Is there a way to use for in loop correctly in situation like this? Also, if there is better way to do it (without Streams), how can it be done?
private ArrayList<MyObject> myObjects;
First method:
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;
}
Second method:
private int findObject(String objectName) {
for(MyObject myObject: this.myObjects) {
if(myObject.getName().equals(objectName)) return this.myObjects.indexOf(myObject);
}
return -1;
}
Upvotes: 0
Views: 65
Reputation: 718788
I think it will be slower than first because indexOf() also does the iteration?
You are correct.
Is there a way to use
for each
loop correctly in situation like this?
You can use a for each
AND an index variable.
private int findObject(String objectName) {
int i = 0;
for (MyObject myObject: this.myObjects) {
if (myObject.getName().equals(objectName)) return i;
i++;
}
return -1;
}
This would be a good solution if myObjects.get(i)
is an expensive operation (e.g. on a LinkedList
where get(n)
is O(N)
) or if it is not implementable (e.g. if you were iterating a Stream
).
You could also use a ListIterator
provided that myObjects
has a method that returns a ListIterator
; see @Andy Turner's answer for an example. (It won't work for a typical Set
or Map
class.)
Upvotes: 2
Reputation: 7290
The first version is perfect if you know you're working with an ArrayList (or some other array-based List, e.g. Vector).
If myObject
happens to be a LinkedList
or similar, your performance will degrade with longer lists, as then get(i)
no longer executes in constant time.
Your second approach will handle LinkedList
s as well as ArrayList
s, but it iterates twice over your list, once in your for
loop, and once in the indexOf()
call.
I'd recommend a third version: use the for loop from the second approach, and add an integer counting variable, incrementing inside the loop. This way, you get the best of both: iterating without performance degradation, and cheap position-counting.
Upvotes: 1
Reputation: 140318
The better way of doing this (that avoids you having to maintain a separate index variable; and works for non-RandomAccess
lists too) would be to use a ListIterator
:
for (ListIterator<MyObject> it = myObjects.listIterator(); it.hasNext();) {
MyObject myObject = it.next();
if(myObject.getName().equals(objectName)) return it.prevIndex();
}
return -1;
Upvotes: 0