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