K.K
K.K

Reputation: 331

ArrayList contains() is not using equals() method of a class

I know there are so many answers for this question. But I have not found the solution.

class IpAddressRange
{
    InetAddress start;
    InetAddress end;

    public IpAddressRange(String start, String end) throws Exception
    {
        this.start = InetAddress.getByName(start);
        this.end = InetAddress.getByName(end);
    }

    @Override
    public boolean equals(Object input)
    {
        System.out.println("Inside equals");
        long lv = IpAddressRange.ipToLong(start);
        long hv = IpAddressRange.ipToLong(end);
        if(input != null && input instanceof InetAddress)
        {
            long iv = IpAddressRange.ipToLong((InetAddress)input);
            if( iv >= lv && iv <= hv)
                return true;
            }
            return false;
        }

    @Override
    public String toString()
    {
        return start.getHostAddress() + "-" + end.getHostAddress();
    }

    public static long ipToLong(InetAddress ip) {
        byte[] octets = ip.getAddress();
        long result = 0;
        for (byte octet : octets) {
            result <<= 8;
            result |= octet & 0xff;
        }
        return result;
    }
}

When I use contains() on the ArrayList, it is not using equals() method.

 ArrayList<IpAddressRange> allocatedList = new ArrayList<IpAddressRange>();
 allocatedList.add(new IpAddressRange("10.10.10.10","10.10.10.12"));

Below is the code that calls contains():

 InetAddress inetAddress1 = InetAddress.getByName("10.10.10.11");
 allocatedList.contains(inetAddress1);

But this contains() is not calling the equals() method of IpAdressRange class.

Upvotes: 0

Views: 593

Answers (1)

Martijn Courteaux
Martijn Courteaux

Reputation: 68907

The problem is that your implementation for equals() does not agree with the implementation of InetAddress. The equals() method should be symmetric.

Take a look at the contract here:

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified. For any non-null reference value x, x.equals(null) should return false.

The point is that you might be able to implement it like anIpAddressRange.equals(anInetAddress) returns true, but not the other way around, because you cannot edit the equals() method from InetAddress.

Upvotes: 4

Related Questions