在Java中的三胞胎课程的覆盖和哈希码



我有一个三重类,该类别可以包含3个整数(x,y,z)。我想覆盖等价/哈希码方法,以便可以在集合中使用它们。因此,具有(1,2,3)的OBJ应等于(3,2,1)或(3,1,2),因此应等于其置换。我知道如何与(x,y)对一对类别进行此操作 - 我所拥有的一对的代码是:

class Pair {
    int x;
    int y;
    public Pair(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof  Pair) {
            Pair p = (Pair) obj;
            if (this.x == p.x && p.y == this.y || this.x == p.y && this.y == p.x) {
                return true;
            }
        }
        return false;
    }
    @Override
    public int hashCode() {
        return Integer.hashCode(x) * Integer.hashCode(y);
    }
}

这可以正常工作,但是如果我想将其扩展到三级类,我知道我可以编辑等于方法并添加更多条件进行检查,但这似乎真的很长。在不使用Java中的外部库的情况下,有什么办法可以做到这一点?

一种解决方案是保留排序的数组以进行比较:

class Triple {
    private final int x, y, z;
    private final int[] sorted;
    public Triple(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.sorted = new int[] {x, y, z};
        Arrays.sort(sorted);
    }
    @Override
    public boolean equals(Object obj) {
        return obj instanceof Triple
                && Arrays.equals(((Triple)obj).sorted, this.sorted);
    }
    @Override
    public int hashCode() {
        return Arrays.hashCode(sorted);
    }
}

要检查组合,您可以将元素添加到list中并调用containsAll方法以检查平等,例如:

public static void main(String[] args) throws IOException {
    List<Integer> list1 = Arrays.asList(new Integer[]{1,2,4});
    List<Integer> list2 = Arrays.asList(new Integer[]{4,2,1});
    System.out.println(list1.containsAll(list2) && list2.containsAll(list1));
}

正确的答案取决于您要如何使用此类,如果相等性和哈希码需要便宜,请考虑初始化可以轻松比较的构造阵列。这样的东西:

import java.util.Arrays;
public class Triple {
    // Use this array only for hashCode & equals.
    private final int[] values;
    private final int x;
    private final int y;
    private final int z;
    public Triple(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.values = new int[]{x, y, z};
        // Sort the values for simpler comparison of equality.
        Arrays.sort(values);
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Triple triple = (Triple) o;
        return Arrays.equals(values, triple.values);
    }
    @Override
    public int hashCode() {
        return Arrays.hashCode(values);
    }
}

添加了一些测试以证明平等和非平等:

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNot.not;
import org.junit.Assert;
import org.junit.Test;
public class TripleTest {
    @Test
    public void valuesInDifferentOrderAreEqual() {
        Triple sortedTriple = new Triple(1, 2, 3);
        Triple outOfOrderTriple = new Triple(3, 2, 1);
        Assert.assertThat(sortedTriple, equalTo(outOfOrderTriple));
        Assert.assertThat(sortedTriple.hashCode(), is(outOfOrderTriple.hashCode()));
    }
    @Test
    public void valuesInOrderAreEqual() {
        Triple sortedTriple = new Triple(1, 2, 3);
        Triple outOfOrderTriple = new Triple(1, 2, 3);
        Assert.assertThat(sortedTriple, equalTo(outOfOrderTriple));
        Assert.assertThat(sortedTriple.hashCode(), is(outOfOrderTriple.hashCode()));
    }
    @Test
    public void valuesThatAreDifferentAreNotEqual() {
        Triple sortedTriple = new Triple(1, 2, 3);
        Triple outOfOrderTriple = new Triple(7, 8, 9);
        Assert.assertThat(sortedTriple, not(outOfOrderTriple));
        Assert.assertThat(sortedTriple.hashCode(), not(outOfOrderTriple.hashCode()));
    }
    @Test
    public void valuesWithSameSumAreNotEqual() {
        Triple sortedTriple = new Triple(11, 21, 31);
        Triple outOfOrderTriple = new Triple(36, 12, 21);
        Assert.assertThat(sortedTriple, not(outOfOrderTriple));
        Assert.assertThat(sortedTriple.hashCode(), not(outOfOrderTriple.hashCode()));
    }
    @Test
    public void valuesWithSameProductAreNotEqual() {
        Triple sortedTriple = new Triple(11, 21, 31);
        Triple outOfOrderTriple = new Triple(33, 7, 31);
        Assert.assertThat(sortedTriple, not(outOfOrderTriple));
        Assert.assertThat(sortedTriple.hashCode(), not(outOfOrderTriple.hashCode()));
    }
}

相关内容

  • 没有找到相关文章

最新更新