Java阵列比较

时间:2010-03-22 15:59:45

标签: java arrays

在Java中工作,假设我有两个对象,感谢obj.getClass().isArray(),我知道这两个对象都是数组。让我们进一步说,我想将这两个数组相互比较 - 可能是使用Arrays.equals。是否有一种优雅的方式来做到这一点,而不诉诸一个大的详尽的if / else树来找出需要使用哪种Arrays.equals的味道?我正在寻找的东西不像这样:


      if (obj1 instanceof byte[] && obj2 instanceof byte[]) {
         return Arrays.equals((byte[])obj1, (byte[])obj2);
      }
      else if (obj1 instanceof boolean[] && obj2 instanceof boolean[]) {
         ...

6 个答案:

答案 0 :(得分:8)

您可以使用反射。

public static boolean arrayEquals(Object arr1, Object arr2) throws Exception {
    Class<?> c = arr1.getClass();
    if (!c.getComponentType().isPrimitive()) {
        c = Object[].class;
    }
    Method m = Arrays.class.getMethod("equals", c, c);
    return (Boolean) m.invoke(null, arr1, arr2);
}

反射仅用于在运行时找到正确的方法,而没有你想要避免的眼睛;实际的Arrays.equals方法应该运行得非常快。

显然,生产版本需要更强大的异常处理。对于非原始数组,您可能还希望使用deepEquals(Object[], Object[])而不是equals(Object[], Object[])

答案 1 :(得分:2)

我担心唯一的选择是使用反射,这几乎就是丑陋。

Arrays.getClass()
      .getMethod("equals", new Class[]{obj1.getClass(), obj2.getClass()})
      .invoke(null, new object[]{obj1, obj2});

未经测试,可能会以各种方式失败,需要大量的异常处理......

答案 2 :(得分:0)

也许Strategy Pattern可以帮助它看起来更好:)

答案 3 :(得分:0)

您可以使用不getClass()的{​​{1}}方法;看看这个例子:

isArray()

我事先承认这远不是一个完美的解决方案。它缩短了你在原帖中可能存在的巨大if-else链,但如果类型不一样会导致错误。以下类似的代码甚至不能在MyEclipse 8.0中编译:

byte[] foo = { 1, 2 };
byte[] bar = { 1, 2 };

System.out.println(foo.getClass());
System.out.println(bar.getClass());

if(foo.getClass() == bar.getClass())
    System.out.println(Arrays.equals(foo, bar));

如果您确信自己不会出现类型不匹配问题,并且您唯一的问题是您不想找出您拥有的类型,那么这可能会有效。

答案 4 :(得分:0)

您可以使用枚举策略模式为每种类型创建比较器:

public enum ArrayEq {
    BYTE_PRIMITIVE(Byte.TYPE) {
        protected boolean doEquals(Object array1, Object array2) {
            return Arrays.equals((byte[]) array1, (byte[]) array2);
        }
    },
    ... enum element for each component type

   private final Class<?> type;

   private ArrayEq(final Class<?> type) { this.type = type; }
   public Class<?> getComponentType() { return type; }

   // force all enums to implement this method
   protected abstract boolean doEquals(Object array1, Object array2);

   public static boolean equals(Object array1, Object array2) {
       if(array1 == null) return array2 == null;

       // you need to populate this map in a static initializer of the enum
       // a simple linear search would work too since the number of elements is small
       typeToElementMap.get(array1.getComponentType())
           .doEquals(array1, array2);
   }

}

忽略错误处理,当然,你想在传递错误类型的地方抛出IllegalArgumentException(我更喜欢让ClassCastException生成JVM,并在我检测到错误时在我自己的代码中抛出IAE。)

答案 5 :(得分:-1)

你试过这个吗?

// Test if both arrays are of the same type
if (array1.class.getComponentType.equals(array2.class.getComponentTYpe)) {
    // Polymorphism FTW !
    return Arrays.equals(array1, array2);
}