Javaarrays比较

在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[]) { ... 

你可以使用reflection。

 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); } 

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

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

我担心唯一的选择是使用reflection,这几乎就像丑陋一样。

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

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

也许策略模式可以帮助它看起来更好:)

您可以使用不带isArray()getClass()方法; 看看这个例子:

 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)); 

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

 byte[] obj1 = { 1, 2 }; String[] obj2 = { "1", "2" }; System.out.println(obj1.getClass()); System.out.println(obj2.getClass()); if(obj1.getClass().toString().equals(obj2.getClass().toString())) System.out.println(Arrays.equals(obj1, obj2)); 

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

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

 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); } 

}

error handling被省略,但当然,你想在传递不正确类型的地方抛出IllegalArgumentException(我更喜欢让ClassCastException生成JVM,并在我检测到错误时在我自己的代码中抛出IAE)。

你试过这个吗?

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