Java tutorial
//package com.java2s; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class Main { private static final Map<Class<?>, Boolean> _customHash = new ConcurrentHashMap<Class<?>, Boolean>(); private static final Map<Class<?>, Collection<Field>> _reflectedFields = new ConcurrentHashMap<Class<?>, Collection<Field>>(); public static int deepHashCode(Object obj) { Set visited = new HashSet(); LinkedList<Object> stack = new LinkedList<Object>(); stack.addFirst(obj); int hash = 0; while (!stack.isEmpty()) { obj = stack.removeFirst(); if (obj == null || visited.contains(obj)) { continue; } visited.add(obj); if (obj.getClass().isArray()) { int len = Array.getLength(obj); for (int i = 0; i < len; i++) { stack.addFirst(Array.get(obj, i)); } continue; } if (obj instanceof Collection) { stack.addAll(0, (Collection) obj); continue; } if (obj instanceof Map) { stack.addAll(0, ((Map) obj).keySet()); stack.addAll(0, ((Map) obj).values()); continue; } if (hasCustomHashCode(obj.getClass())) { hash += obj.hashCode(); continue; } Collection<Field> fields = getDeepDeclaredFields(obj.getClass()); for (Field field : fields) { try { stack.addFirst(field.get(obj)); } catch (Exception ignored) { } } } return hash; } private static int getLength(int from, int to) { int newLength = to - from; if (newLength < 0) { StringBuffer sb = new StringBuffer(from); sb.append(" > ").append(to); throw new IllegalArgumentException(sb.toString()); } return newLength; } public static boolean hasCustomHashCode(Class<?> c) { Class<?> origClass = c; if (_customHash.containsKey(c)) { return _customHash.get(c); } while (!Object.class.equals(c)) { try { c.getDeclaredMethod("hashCode"); _customHash.put(origClass, true); return true; } catch (Exception ignored) { } c = c.getSuperclass(); } _customHash.put(origClass, false); return false; } public static int hashCode(byte[] data) { if (data == null) { return 0; } int i = data.length; int hc = i + 1; while (--i >= 0) { hc *= 257; hc ^= data[i]; } return hc; } public static int hashCode(char[] data) { if (data == null) { return 0; } int i = data.length; int hc = i + 1; while (--i >= 0) { hc *= 257; hc ^= data[i]; } return hc; } public static int hashCode(int[][] ints) { int hc = 0; for (int i = 0; i != ints.length; i++) { hc = hc * 257 + hashCode(ints[i]); } return hc; } public static int hashCode(int[] data) { if (data == null) { return 0; } int i = data.length; int hc = i + 1; while (--i >= 0) { hc *= 257; hc ^= data[i]; } return hc; } public static int hashCode(short[][][] shorts) { int hc = 0; for (int i = 0; i != shorts.length; i++) { hc = hc * 257 + hashCode(shorts[i]); } return hc; } public static int hashCode(short[][] shorts) { int hc = 0; for (int i = 0; i != shorts.length; i++) { hc = hc * 257 + hashCode(shorts[i]); } return hc; } public static int hashCode(short[] data) { if (data == null) { return 0; } int i = data.length; int hc = i + 1; while (--i >= 0) { hc *= 257; hc ^= (data[i] & 0xff); } return hc; } public static int hashCode(BigInteger[] data) { if (data == null) { return 0; } int i = data.length; int hc = i + 1; while (--i >= 0) { hc *= 257; hc ^= data[i].hashCode(); } return hc; } public static Collection<Field> getDeepDeclaredFields(Class<?> c) { if (_reflectedFields.containsKey(c)) { return _reflectedFields.get(c); } Collection<Field> fields = new ArrayList<Field>(); Class<?> curr = c; while (curr != null) { try { Field[] local = curr.getDeclaredFields(); for (Field field : local) { if (!field.isAccessible()) { try { field.setAccessible(true); } catch (Exception ignored) { } } int modifiers = field.getModifiers(); if (!Modifier.isStatic(modifiers) && !field.getName().startsWith("this$") && !Modifier.isTransient(modifiers)) { fields.add(field); } } } catch (ThreadDeath t) { throw t; } catch (Throwable ignored) { } curr = curr.getSuperclass(); } _reflectedFields.put(c, fields); return fields; } }