You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Codewars题目中:修改Java代码实现int数组元素级相等判断

数组元素相等判断问题的解决方案

问题背景

我在解决编程题时,遇到了数组相等判断的问题:我需要判断多个数组是否是同一矩阵的变体(通过旋转等操作得到),但HashSet的contains()方法总是把元素相同的数组判定为不同对象,导致结果不符合预期。

我的代码

public static void main(String[] args) {
    int[][] ms;

    ms = new int[][] {{1, 2, 3, 4},
            {3, 1, 4, 2},
            {4, 3, 2, 1},
            {2, 4, 1, 3}};
    System.out.println(count_different_matrices(ms));
}


private static final Set<int[]> registeredM = new HashSet<>();
static public int count_different_matrices(int[][] matrices) {
    Arrays.stream(matrices).forEach(m -> {
        if(unwrapPossibleMatrices(m).stream().noneMatch(registeredM::contains)) {
            registeredM.add(m);
        }
    });
    registeredM.forEach(e -> System.out.println(Arrays.toString(e)));
    return registeredM.size();
}

static private List<int[]> unwrapPossibleMatrices(int[] m) {
    return Arrays.asList(new int[][]{m,
            {m[2], m[0], m[3], m[1]},
            {m[3], m[2], m[1], m[0]},
            {m[1], m[3], m[0], m[2]}
    });
}

控制台输出

[1, 2, 3, 4]
[2, 4, 1, 3]
[4, 3, 2, 1]
[3, 1, 4, 2]
4

问题点

我预期输出仅为[1, 2, 3, 4],但实际输出了4个数组。原因是Java中int[]的equals()方法默认比较对象引用地址,而非数组元素是否相同,导致HashSet无法识别元素相同的数组。


解决方案

方法1:转换为List<Integer>存储(推荐)

将数组转为List<Integer>,因为List的equals()和hashCode()方法是基于元素实现的,能被HashSet正确识别:

修改后的代码:

import java.util.*;

public class MatrixCounter {
    public static void main(String[] args) {
        int[][] ms = new int[][] {{1, 2, 3, 4},
                {3, 1, 4, 2},
                {4, 3, 2, 1},
                {2, 4, 1, 3}};
        System.out.println(count_different_matrices(ms));
    }

    private static final Set<List<Integer>> registeredM = new HashSet<>();
    static public int count_different_matrices(int[][] matrices) {
        Arrays.stream(matrices).forEach(m -> {
            // 生成当前数组的所有变体
            List<int[]> variants = unwrapPossibleMatrices(m);
            // 检查是否有变体已在集合中
            boolean hasExistingVariant = variants.stream()
                    .map(arr -> Arrays.asList(Arrays.stream(arr).boxed().toArray(Integer[]::new)))
                    .anyMatch(registeredM::contains);
            if (!hasExistingVariant) {
                // 将当前数组转为List存入集合
                registeredM.add(Arrays.asList(Arrays.stream(m).boxed().toArray(Integer[]::new)));
            }
        });
        registeredM.forEach(System.out::println);
        return registeredM.size();
    }

    static private List<int[]> unwrapPossibleMatrices(int[] m) {
        return Arrays.asList(new int[][]{m,
                {m[2], m[0], m[3], m[1]},
                {m[3], m[2], m[1], m[0]},
                {m[1], m[3], m[0], m[2]}
        });
    }
}

方法2:遍历集合用Arrays.equals比较

如果不想转换集合类型,可以在判断时遍历registeredM,用Arrays.equals逐个比较数组元素:

修改count_different_matrices方法:

private static final Set<int[]> registeredM = new HashSet<>();
static public int count_different_matrices(int[][] matrices) {
    Arrays.stream(matrices).forEach(m -> {
        List<int[]> variants = unwrapPossibleMatrices(m);
        // 遍历所有变体,检查集合中是否有元素与变体元素相等
        boolean hasMatch = variants.stream()
                .anyMatch(variant -> registeredM.stream().anyMatch(r -> Arrays.equals(r, variant)));
        if (!hasMatch) {
            registeredM.add(m);
        }
    });
    registeredM.forEach(e -> System.out.println(Arrays.toString(e)));
    return registeredM.size();
}

这种方式无需转换类型,但每次判断都要遍历集合,适合数据量较小的场景。

方法3:使用TreeSet自定义比较器

通过TreeSet传入自定义比较器,实现基于元素的数组比较:

private static final Set<int[]> registeredM = new TreeSet<>((a, b) -> {
    // 先比较长度
    if (a.length != b.length) {
        return Integer.compare(a.length, b.length);
    }
    // 逐个比较元素
    for (int i = 0; i < a.length; i++) {
        int cmp = Integer.compare(a[i], b[i]);
        if (cmp != 0) {
            return cmp;
        }
    }
    return 0;
});

注意:TreeSet是有序集合,且比较器需要保证一致性(即compare(a,b)==0时,a.equals(b)理论上也应返回true,但数组的equals仍比较引用,所以这种方式不完全符合Set的严格规范,仅适合特定场景)。


内容的提问来源于stack exchange,提问作者BJagger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:45:14