tags:

views:

224

answers:

4

I want to declare a List<int[]> or Map<int[],Boolean> but it's very difficult because arrays in Java doesn't implement the equals() method. If two arrays a and b are equal, a.equals(b) returns false.

Although java.util.Arrays.equals() compares arrays for equality, how do I get a List to use that method for comparison instead of the screwed-up equals()?

By the way, the int[] is a array [x,y,z] describing a coordinate. I want to put a bunch of these coordinates into a List or Map.

+2  A: 

First of all, this isn't legal syntax. List can only take a single generic type.

Second, I would say that if you're worried about doing things at this low a level you aren't thinking abstractly enough. An array of arrays or a List of Lists is common enough. People who create matrix classes for linear algebra use them all the time. But you leverage objects and Java best when you hide those implementation details from clients of your class. Try it for your case and see if it helps.

duffymo
+8  A: 

Why not declare your own class for a point? e.g.

class Point3D {
  int x, y, z;

  public boolean equals() {
    // logic
  }
}

and then declare List<Point3D>.

Richard Nichols
Only make you fields private and the class immutable!
Tom Hawtin - tackline
And add a `hashCode` method.
Tom Hawtin - tackline
Java already has a Point3d class.
Carl
Valid comments, I omitted the details for clarity.
Richard Nichols
+3  A: 

A general solution is to wrap the array in a method that does implement equals (and hashCode and perhaps compare, possibly toString and other methods that might make sense) as you wish:

public final class IntArrayWrapper {
    private final IntArrayWrapper[] values;
    public IntArrayWrapper(int... values) {
        if (values == null) {
            throw new NullPointerException();
        }
        this.values = values;
    }
    @Override public boolean equals(Object obj) {
        if (!(obj instanceof IntArrayWrapper)) {
            return false;
        }
        IntArrayWrapper other = (IntArrayWrapper)obj;
        return java.util.Arrays.equals(this.values, other.values);
    }
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(values);
    }
    public int[] getValues() {
        return values;
    }
    [...]
}

In this specific case, using arrays to contain certain fixed data values is poor design. Do it properly:

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

    public static Point of(int x, int y, int z) {
        return new Point(x, y, z);
    }
    private Point(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    @Override public boolean equals(Object obj) {
        if (!(obj instanceof Point)) {
            return false;
        }
        Point other = (Point)obj;
        return
            this.x == other.x &&
            this.y == other.y &&
            this.z == other.z;
    }
    @Override public int hashCode() {
        int hash;
        hash = x;
        hash = hash*41+y;
        hash = hash*41+z;
        return hash;
    }
    [...]
}
Tom Hawtin - tackline
As above, Java already has a Point3d class.
Carl
Java SE has `Point2D`, but no `Point3d`.
Tom Hawtin - tackline
A: 

You could always use the existing Point3d class instead of an array.

edit: The Apache Commons Math library also has some good options.

Carl
You are suggesting pulling in a huge dependent, dormant library for a single, trivial class? A class that uses the wrong datatype for the questioner and is mutable.
Tom Hawtin - tackline
Yes. Though the Apache Commons library is also a good option.
Carl
the Math one, I mean.
Carl