1

I've got a class using two generic parameters in its constructor. I would like to implement a method to compare two instances of this class, as done in the code below.

It works quite well except when one of the parameter is an arrays. I've read different topics about how to compare arrays with java.util.Arrays.equals(Object[] a, Object[] a2) but as my parameters are not defined as arrays, I can't use this method.

How could return "true" in the content of my array is the same? Or is it possible to cast my parameters to use java.util.Arrays.equals(Object[] a, Object[] a2)?

public class Pair<U, V> {

    public final U first;
    public final V second;

    public Pair(U first, V second) {
        this.first = first;
        this.second = second;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        Pair<?, ?> myPair= (Pair<?, ?>) o;

        if (!first.equals(myPair.first) || !second.equals(myPair.second))
            return false;
        return true;
    }
}
1
  • Could you define Point as an interface and have different implementations for it? One implementation could be PointOfArrays which would take two arrays. Commented Nov 2, 2018 at 10:26

4 Answers 4

1
@Override
public boolean equals(Object o) {
    if (this == o)
        return true;
    if (o == null || getClass() != o.getClass())
        return false;

    Pair<?, ?> myPair = (Pair<?, ?>)o;

    if (first.getClass().isArray() ^ first.getClass().isArray() || second.getClass().isArray() ^ second.getClass().isArray())
        return false;
    return deepEquals(first, myPair.first) && deepEquals(second, myPair.second);
}

private static boolean deepEquals(Object one, Object two) {
    if (one instanceof byte[])
        return Arrays.equals((byte[])one, (byte[])two);
    if (one instanceof char[])
        return Arrays.equals((char[])one, (char[])two);
    if (one instanceof short[])
        return Arrays.equals((short[])one, (short[])two);
    if (one instanceof int[])
        return Arrays.equals((int[])one, (int[])two);
    if (one instanceof long[])
        return Arrays.equals((long[])one, (long[])two);
    if (one instanceof boolean[])
        return Arrays.equals((boolean[])one, (boolean[])two);
    if (one instanceof float[])
        return Arrays.equals((float[])one, (float[])two);
    if (one instanceof double[])
        return Arrays.equals((double[])one, (double[])two);
    if (one instanceof Object[])
        return Arrays.equals((Object[])one, (Object[])two);
    return one.equals(two);
}
Sign up to request clarification or add additional context in comments.

4 Comments

It's better to provide some explaination of how this fixes OP's problem. A code-only answer hardly helps future readers.
did you try this code? I've got an Exception when I try to parse (Object[])first
Yes. What input data do you use?
I use this int[] test = {1, 3, 5}; (and test2 for the second Pair)
0

You can do this:

  • use the guidance given here to determine whether both objects (this and the "other") contain arrays. Of course, detecting the actual member type means even more work.
  • utilize Array.equals() to write specific comparison code when the fields are in fact arrays.

But make no mistake: getting your equals() implementation to be correct, and work with inheritance and what not ... will be a major challenge!

For example: do you consider an array of int to be equal to a list of Integer values (assuming the values are all in fact the same)? Or what about nested arrays?

The real point here: Java doesn't have deep equality for arrays, and it is close to impossible to cover all potential cases yourself!

4 Comments

That's not "doing two things" - as in two approaches. That's one approach that has 2 steps.
I actually tried to do this, but as first and second are not declared as Array, I've got this error when I try to use Arrays.equals() : The method equals(Object) in the type Object is not applicable for the arguments (V, capture#12-of ?)
That's why I asked if a cast could be a solution but I don't know the type of my array
Casting would not help with anything. See my updated answer.
0
public class Fourth {

    public static void main(String[] args) {

        Integer a[] = {1,2,3,4,5};
        Integer b[] = {1,2,3,4,6,7};

        CompareArrays<Integer, Integer> comp = new CompareArrays<Integer, Integer>(a,b);

        comp.compareArrays();

    }
}

class CompareArrays<One extends Number, Two extends Number> {

    One[] array1;
    Two[] array2;

    CompareArrays(One[] ob1, Two[] ob2){
        array1 = ob1;
        array2 = ob2;
    }

    void compareArrays() {

        if(array1.length != array2.length) {
            System.out.println("Two arrays are not equal");

        }else {

            int flag = 0;

            for (int i = 0; i < array1.length; i++) {


                  if(array1[i] != array2[i]) {
                      flag =1;
                  }
            }

            if(flag == 0) {
                System.out.println("Two arrays are equal");
            }else {
                System.out.println("Two arrays are not equal");
            }

        }
    }
}

Comments

-1

It's worth noting that no collection in Java that I'm aware of - pairs, lists, sets... - makes a concession for this case. As an example:

List<Integer[]> one = Arrays.asList(
    new Integer[]{1}, new Integer[]{2}
);
List<Integer[]> two = Arrays.asList(
    new Integer[]{1}, new Integer[]{2}
);
System.out.println(one.equals(two));

Output: false

Equality of two collections should only be determined by the equality of its elements. Anything other than that just makes the contract of your class increasingly vague.

Arrays in Java do not override equals. That's a design decision that's already been made. It's not your job to try to correct what you must perceive as the wrong decision by hacking your implementation.

So, in short, you don't.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.