Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

indexOf() will not find a custom object type

The following code does not give me right answer.

class Point {

    int x; int y;
    public Point(int a,int b){
        this.x=a;this.y=b;
    }
}

class A{

    public static void main(String[] args){

        ArrayList<Point> p=new ArrayList<Point>();
        p.add(new Point(3,4));
        p.add(new Point(1,2));
        System.out.println(p.indexOf(1,2));

    }
}

This gives -1;

In general if arraylist of point is given, how can we find index of a particular point in in array ?

like image 350
ajay Avatar asked Jul 25 '14 14:07

ajay


3 Answers

indexOf requires the object as input. If it does not find the object you are passing in, it will return -1. You need to pass the object whose location in the arraylist you are looking for as the input into the indexOf function. You should also override hashcode and equals for your class in this case.

Override hashcode and equals in your class Point. Then once you create instances of this class Point (using the new keyword) and add them to the arrayList, you can use the indexOf call on the arrayList using any of the Point objects as a parameter to the indexOf call.

Class Point

public class Point {

        int x; 
        int y;

        public Point(int a, int b) {
        this.x=a;this.y=b;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + x;
            result = prime * result + y;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Point other = (Point) obj;
            if (x != other.x)
                return false;
            if (y != other.y)
                return false;
            return true;
        }       
}

Class Test (you called it "a"):

import java.util.ArrayList;

public class Test {

     public static void main(String[] args){

            ArrayList<Point> p=new ArrayList<Point>();

            Point p1 = new Point(3,4);
            Point p2 = new Point(1,2);

            p.add(new Point(3,4));
            p.add(new Point(1,2));

            System.out.println(p.indexOf(p1));
     }

}
like image 158
ali haider Avatar answered Oct 23 '22 06:10

ali haider


You need to create a point to pass into the indexOf method.

p.indexOf(new Point(1,2));

But that change by itself will still return -1. See the api doc for indexOf:

public int indexOf(Object o)

Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.

It's using equals to decide whether it's found a match. You haven't overridden the equals method on your point class, so it's using the default implementation in java.lang.Object, which compares the references, and only returns true if the two references point to the same object.

Override equals and hashcode on your point class, like:

@Override public boolean equals(Object other) {
    if (!(other instanceof point)) {
        return false;
    }
    point otherPoint = (point)other;
    return otherPoint.x == this.x && otherPoint.y == this.y;
}

@Override public int hashCode() {
    return x + y; // same values should hash to the same number
}

and that way two different instances of the class can be compared by value.

like image 39
Nathan Hughes Avatar answered Oct 23 '22 08:10

Nathan Hughes


ArrayList.indexOf() doesn't accept two integers as argument. You must input one object, which is supposed to be a Point object.

If you still want to call ArrayList.indexOf(int, int), then you must create a subclass of ArrayList, implementing indexOf(int,int).

The following code should find the wanted object for you. First, you'll need to override the equals method from the Object class in the Point class, in order to compare two points.

public class Point {
    private int x;
    private int y;

    @Override
    public boolean equals(Object anotherObject) {
        if (!(anotherObject instanceof Point)) {
            return false;
        }
        Point p = (Point) anotherObject;
        return (this.x == p.x && this.y == p.y);
    }
}

Second, you can call indexOf(Object):

ArrayList<Point> p = new ArrayList<Point>();
// Create the point to find in the list.
Point findMe = new Point(1,2);
// Search the array and save the found index.
int index = p.indexOf(findMe);

PS: You should follow the Java naming conventions; classes must start with an uppercase letter.

like image 27
MC Emperor Avatar answered Oct 23 '22 08:10

MC Emperor