public class DeepDifference
extends java.lang.Object
Modifier and Type | Class and Description |
---|---|
static class |
DeepDifference.Difference |
private static class |
DeepDifference.DualKey |
Modifier and Type | Field and Description |
---|---|
private static java.util.Map<java.lang.Class<?>,java.lang.Boolean> |
customEquals |
private static java.util.Map<java.lang.Class<?>,java.lang.Boolean> |
customHash |
private static java.lang.String |
MISSING_FIELDS |
Constructor and Description |
---|
DeepDifference() |
Modifier and Type | Method and Description |
---|---|
private static boolean |
compareArrays(java.lang.Object array1,
java.lang.Object array2,
java.util.List<java.lang.String> path,
java.util.Deque<DeepDifference.DualKey> toCompare,
java.util.Set<DeepDifference.DualKey> visited)
Deeply compare to Arrays [].
|
private static <K,V> boolean |
compareOrderedCollection(java.util.Collection<K> col1,
java.util.Collection<V> col2,
java.util.List<java.lang.String> path,
java.util.Deque<DeepDifference.DualKey> toCompare,
java.util.Set<DeepDifference.DualKey> visited)
Deeply compare two Collections that must be same length and in same
order.
|
private static <K1,V1,K2,V2> |
compareSortedMap(java.util.SortedMap<K1,V1> map1,
java.util.SortedMap<K2,V2> map2,
java.util.List<java.lang.String> path,
java.util.Deque<DeepDifference.DualKey> toCompare,
java.util.Set<DeepDifference.DualKey> visited)
Deeply compare two SortedMap instances.
|
private static <K,V> boolean |
compareUnorderedCollection(java.util.Collection<K> col1,
java.util.Collection<V> col2,
java.util.List<java.lang.String> path,
java.util.Deque<DeepDifference.DualKey> toCompare,
java.util.Set<DeepDifference.DualKey> visited,
java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField,
TypeComparators comparatorByType) |
private static <K,V> boolean |
compareUnorderedCollectionByHashCodes(java.util.Collection<K> col1,
java.util.Collection<V> col2,
java.util.List<java.lang.String> path,
java.util.Deque<DeepDifference.DualKey> toCompare,
java.util.Set<DeepDifference.DualKey> visited)
It places one collection into a temporary Map by deepHashCode(), so that it
can walk the other collection and look for each item in the map, which
runs in O(N) time, rather than an O(N^2) lookup that would occur if each
item from collection one was scanned for in collection two.
|
private static <K1,V1,K2,V2> |
compareUnorderedMap(java.util.Map<K1,V1> map1,
java.util.Map<K2,V2> map2,
java.util.List<java.lang.String> path,
java.util.Deque<DeepDifference.DualKey> toCompare,
java.util.Set<DeepDifference.DualKey> visited)
Deeply compare two Map instances.
|
(package private) static int |
deepHashCode(java.lang.Object obj)
Get a deterministic hashCode (int) value for an Object, regardless of
when it was created or where it was loaded into memory.
|
private static java.util.List<DeepDifference.Difference> |
determineDifferences(java.lang.Object a,
java.lang.Object b,
java.util.List<java.lang.String> parentPath,
java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField,
TypeComparators comparatorByType) |
static java.util.List<DeepDifference.Difference> |
determineDifferences(java.lang.Object a,
java.lang.Object b,
java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField,
TypeComparators comparatorByType)
Compare two objects for differences by doing a 'deep' comparison.
|
private static java.util.Set<java.lang.String> |
getFieldsNames(java.util.Collection<java.lang.reflect.Field> fields) |
private static boolean |
hasCustomComparator(DeepDifference.DualKey dualKey,
java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField,
TypeComparators comparatorByType) |
(package private) static boolean |
hasCustomEquals(java.lang.Class<?> c)
Determine if the passed in class has a non-Object.equals() method.
|
(package private) static boolean |
hasCustomHashCode(java.lang.Class<?> c)
Determine if the passed in class has a non-Object.hashCode() method.
|
private static java.util.Deque<DeepDifference.DualKey> |
initStack(java.lang.Object a,
java.lang.Object b,
java.util.List<java.lang.String> parentPath,
java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField,
TypeComparators comparatorByType) |
private static boolean |
isContainerType(java.lang.Object o) |
private static final java.lang.String MISSING_FIELDS
private static final java.util.Map<java.lang.Class<?>,java.lang.Boolean> customEquals
private static final java.util.Map<java.lang.Class<?>,java.lang.Boolean> customHash
public static java.util.List<DeepDifference.Difference> determineDifferences(java.lang.Object a, java.lang.Object b, java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField, TypeComparators comparatorByType)
This method handles cycles correctly, for example A->B->C->A. Suppose a and a' are two separate instances of the A with the same values for all fields on A, B, and C. Then a.deepEquals(a') will return an empty list. It uses cycle detection storing visited objects in a Set to prevent endless loops.
a
- Object one to compareb
- Object two to comparecomparatorByPropertyOrField
- comparators to compare properties or fields with the given namescomparatorByType
- comparators to compare properties or fields with the given typesprivate static java.util.List<DeepDifference.Difference> determineDifferences(java.lang.Object a, java.lang.Object b, java.util.List<java.lang.String> parentPath, java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField, TypeComparators comparatorByType)
private static boolean hasCustomComparator(DeepDifference.DualKey dualKey, java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField, TypeComparators comparatorByType)
private static java.util.Deque<DeepDifference.DualKey> initStack(java.lang.Object a, java.lang.Object b, java.util.List<java.lang.String> parentPath, java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField, TypeComparators comparatorByType)
private static java.util.Set<java.lang.String> getFieldsNames(java.util.Collection<java.lang.reflect.Field> fields)
private static boolean isContainerType(java.lang.Object o)
private static boolean compareArrays(java.lang.Object array1, java.lang.Object array2, java.util.List<java.lang.String> path, java.util.Deque<DeepDifference.DualKey> toCompare, java.util.Set<DeepDifference.DualKey> visited)
array1
- [] type (Object[], String[], etc.)array2
- [] type (Object[], String[], etc.)path
- the path to the arrays to comparetoCompare
- add items to compare to the Stack (Stack versus recursion)visited
- Set of objects already compared (prevents cycles)private static <K,V> boolean compareOrderedCollection(java.util.Collection<K> col1, java.util.Collection<V> col2, java.util.List<java.lang.String> path, java.util.Deque<DeepDifference.DualKey> toCompare, java.util.Set<DeepDifference.DualKey> visited)
K
- the key typeV
- the value typecol1
- First collection of items to comparecol2
- Second collection of items to comparepath
- The path to the collectionstoCompare
- add items to compare to the Stack (Stack versus recursion)visited
- Set of objects already compared (prevents cycles) value of
'true' indicates that the Collections may be equal, and the
sets items will be added to the Stack for further comparison.private static <K,V> boolean compareUnorderedCollectionByHashCodes(java.util.Collection<K> col1, java.util.Collection<V> col2, java.util.List<java.lang.String> path, java.util.Deque<DeepDifference.DualKey> toCompare, java.util.Set<DeepDifference.DualKey> visited)
K
- the key typeV
- the value typecol1
- First collection of items to comparecol2
- Second collection of items to comparepath
- the path to the collections to comparetoCompare
- add items to compare to the Stack (Stack versus recursion)visited
- Set containing items that have already been compared, so as to
prevent cycles.private static <K,V> boolean compareUnorderedCollection(java.util.Collection<K> col1, java.util.Collection<V> col2, java.util.List<java.lang.String> path, java.util.Deque<DeepDifference.DualKey> toCompare, java.util.Set<DeepDifference.DualKey> visited, java.util.Map<java.lang.String,java.util.Comparator<?>> comparatorByPropertyOrField, TypeComparators comparatorByType)
private static <K1,V1,K2,V2> boolean compareSortedMap(java.util.SortedMap<K1,V1> map1, java.util.SortedMap<K2,V2> map2, java.util.List<java.lang.String> path, java.util.Deque<DeepDifference.DualKey> toCompare, java.util.Set<DeepDifference.DualKey> visited)
K1
- the first key typeV1
- the first value typeK2
- the second key typeV2
- the second value typemap1
- SortedMap onemap2
- SortedMap twopath
- the path to the maps to comparetoCompare
- add items to compare to the Stack (Stack versus recursion)visited
- Set containing items that have already been compared, to
prevent cycles.private static <K1,V1,K2,V2> boolean compareUnorderedMap(java.util.Map<K1,V1> map1, java.util.Map<K2,V2> map2, java.util.List<java.lang.String> path, java.util.Deque<DeepDifference.DualKey> toCompare, java.util.Set<DeepDifference.DualKey> visited)
K1
- the first key typeV1
- the first value typeK2
- the second key typeV2
- the second value typemap1
- Map onemap2
- Map twopath
- the path to the maps to comparetoCompare
- add items to compare to the Stack (Stack versus recursion)visited
- Set containing items that have already been compared, to
prevent cycles.static boolean hasCustomEquals(java.lang.Class<?> c)
c
- Class to check.static int deepHashCode(java.lang.Object obj)
obj
- Object who hashCode is desired.static boolean hasCustomHashCode(java.lang.Class<?> c)
c
- Class to check.