Hello! I have problem with Java's ArrayList. I've created an Object, that contains two attributes, x and y. Now I've loaded some object in my ArrayList. Problem is that I don't know how to find index of some object with x atribute I'm searching. Is there any way to do this?
Just iterate over the list and test every element.
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getX() == someValue) { // Or use equals() if it actually returns an Object.
// Found at index i. Break or return if necessary.
}
}
Verbose, yes, but possibly until JDK7 with Closures, there is no other standard way.
Assuming something like:
public class Point {
public final int x;
public final int y;
}
And a declaration of:
List<Point> points = ...;
You can use for-each to iterate through all the points and find the one you want:
for (Point p : points) {
if (p.x == targetX) {
process(p);
break; // optional
}
}
Note that this will not give you the index, but it will give you the Point
itself, which sometimes is enough. If you really need the index, then you'd want to use indexed for loop, using size()
and get(int index)
(see BalusC's answer).
See also
The above solution searches in O(N)
for each targetX
. If you're doing this often, then you can improve this by declaring class Point implements
Comparable<Point>
, using x
as the primary sorting key for Collections.sort
.
Then you can Collections.binarySearch
. With a setup time of O(N log N)
, each query can now be answered in O(log N)
.
Another option is to use a SortedSet
such as a TreeSet
, especially if what you have is a Set<Point>
, not a List<Point>
.
See also
Is this what you looking for?
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public boolean equals(Object o) {
return (o instanceof Point && getX() == ((Point) o).getX() && getY() == ((Point) o)
.getY());
}
}
public class TestIndexOf {
public static void main(String[] args){
Point p1 = new Point(10,30);
Point p2 = new Point(20,40);
Point p3 = new Point(50,40);
Point p4 = new Point(60,40);
List<Point> list = new ArrayList<Point>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
System.out.println(list.indexOf(p3));
}
}
If you just want to search on the x property, change the equals method to compare only the x values like:
@Override
public boolean equals(Object o) {
return (o instanceof Point && getX() == ((Point) o).getX());
}
I usually just use a map if i want to be able to fetch an object out of a collection based on one specific attribute value. I find that cleaner than having to iterate over lists.
Map<String, Object> map = new HashMap<String, Object>();
map.put(o1.getX(), o1);
map.put(o2.getX(), o2);
now, if i want the object that has an x-value of "foo", all it takes is
Object desiredObject = map.get("foo");
if order is important, consider a LinkedHashMap.