Class Equivalence<T>
- java.lang.Object
-
- io.timeandspace.collect.Equivalence<T>
-
- Type Parameters:
T- type of objects compared by this equivalence
- Direct Known Subclasses:
StatelessEquivalence
public abstract class Equivalence<T> extends Object
A strategy for determining whether two instances are considered equivalent.This class is inspired and very similar to Guava's
Equivalence, with one notable difference: thisEquivalenceforces the actual implementation to overrideequals(Object)andhashCode(). Notice these areEquivalence's own equals and hashCode, not the strategyequivalent(Object, Object)andhash(Object)methods. It is needed because, for example,ObjCollection's equality depends onEquivalenceequality.In most cases, when
Equivalenceis stateless, you can extendStatelessEquivalencenot to bother with implementing these methods. See examples in the documentation to identity and case insensitive equivalences.
-
-
Constructor Summary
Constructors Modifier Constructor Description protectedEquivalence()Constructor for use by subclasses.
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description static Equivalence<String>caseInsensitive()Returns theStringequivalence that usesString.equalsIgnoreCase(java.lang.String)to compare strings.static Equivalence<CharSequence>charSequence()Returns the equivalence that comparesCharSequences by their contents.static <T> Equivalence<T>defaultEquality()Returns the default, built-in equivalence in Java, driven byObject.equals(Object)andObject.hashCode()methods.static <K,V>
Equivalence<Map.Entry<K,V>>entryEquivalence(Equivalence<K> keyEquivalence, Equivalence<V> valueEquivalence)Returns aMap.Entryequivalence for the given key and value equivalences.abstract booleanequals(Object o)abstract booleanequivalent(T a, T b)Returnstrueifaandbare considered equivalent,falseotherwise.abstract inthash(T t)Returns a hash code for the given object.abstract inthashCode()static <T> Equivalence<T>identity()Returns the equivalence that uses==to compare objects andSystem.identityHashCode(Object)to compute the hash code.booleannullableEquivalent(T a, T b)Returnstrueifaandbare considered equivalent,falseotherwise.intnullableHash(T t)Returns a hash code for the given object.
-
-
-
Method Detail
-
defaultEquality
public static <T> Equivalence<T> defaultEquality()
Returns the default, built-in equivalence in Java, driven byObject.equals(Object)andObject.hashCode()methods.- Type Parameters:
T- type of objects, needed to compare.Object.equals(java.lang.Object)could be applied to object of any type, so there aren't any constraints over the generic type parameter.- Returns:
- the built-in Java equality
-
identity
public static <T> Equivalence<T> identity()
Returns the equivalence that uses==to compare objects andSystem.identityHashCode(Object)to compute the hash code.nullableEquivalent(T, T)returnstrueifa == b, including in the case whenaandbare bothnull.This equivalence could be implemented as follows:
final class Identity extends StatelessEquivalence<Object> { static final Identity INSTANCE = new Identity(); private Identity() {} @Override public boolean equivalent(Object a, Object b) { return a == b; } @Override public int hash(Object t) { return System.identityHashCode(t); } }- Type Parameters:
T- type of objects, needed to compare. Identity check could be applied to objects of any type, so there aren't any constraints over the generic type parameter.- Returns:
- the identity equivalence
-
charSequence
public static Equivalence<CharSequence> charSequence()
Returns the equivalence that comparesCharSequences by their contents.This equivalence could be implemented as follows (actual implementation, of cause, is more efficient and doesn't allocate garbage objects):
final class CharSequenceEquivalence extends StatelessEquivalence<CharSequence> { static final CharSequenceEquivalence INSTANCE = new CharSequenceEquivalence(); private CharSequenceEquivalence() {} @Override public boolean equivalent(CharSequence a, CharSequence b) { return a.toString().equals(b.toString()); } @Override public int hash(CharSequence cs) { return cs.toString().hashCode(); } }- Returns:
- the
CharSequenceequivalence
-
caseInsensitive
public static Equivalence<String> caseInsensitive()
Returns theStringequivalence that usesString.equalsIgnoreCase(java.lang.String)to compare strings.This equivalence could be implemented as follows:
final class CaseInsensitive extends StatelessEquivalence<String> { static final CaseInsensitive INSTANCE = new CaseInsensitive(); private CaseInsensitive() {} @Override public boolean equivalent(String a, String b) { return a.equalsIgnoreCase(b); } @Override public int hash(String s) { return s.toLowerCase().hashCode(); } }- Returns:
- the case-insensitive
Stringequivalence
-
entryEquivalence
public static <K,V> Equivalence<Map.Entry<K,V>> entryEquivalence(Equivalence<K> keyEquivalence, Equivalence<V> valueEquivalence)
Returns aMap.Entryequivalence for the given key and value equivalences.- Type Parameters:
K- the entry key typeV- the entry value type- Parameters:
keyEquivalence- the entry key equivalencevalueEquivalence- the entry value equivalence- Returns:
- a
Map.Entryequivalence for the given key and value equivalences
-
nullableEquivalent
public boolean nullableEquivalent(@Nullable T a, @Nullable T b)
Returnstrueifaandbare considered equivalent,falseotherwise.aandbboth might benull.If the implementation overrides this method, it must ensure that it returns
trueif both the given objects are nulls andfalse, if only one of them isnull. If bothaandbare non-null, this method should perform just the same asequivalent(Object, Object)method does.- Parameters:
a- the first object to compareb- the second object to compare- Returns:
trueifaandbare considered equivalent,falseotherwise
-
equivalent
public abstract boolean equivalent(T a, T b)
Returnstrueifaandbare considered equivalent,falseotherwise.aandbare assumed to be non-null.This method implements an equivalence relation on object references:
- It is reflexive: for any reference
x,equivalent(x, x)returnstrue. - It is symmetric: for any references
xandy,equivalent(x, y) == equivalent(y, x). - It is transitive: for any references
x,y, andz, ifequivalent(x, y)returnstrueandequivalent(y, z)returnstrue, thenequivalent(x, z)returnstrue. - It is consistent: for any references
xandy, multiple invocations ofequivalent(x, y)consistently returntrueor consistently returnfalse(provided that neitherxnoryis modified).
This method is called by
nullableEquivalent(Object, Object).- Parameters:
a- the first object to compareb- the second object to compare- Returns:
trueifaandbare considered equivalent,falseotherwise
- It is reflexive: for any reference
-
nullableHash
public int nullableHash(@Nullable T t)
Returns a hash code for the given object. Thetobject might benull.If the implementation overrides this method, it must ensure that it returns
0if the given object isnull. Otherwise this method should perform just the same ashash(Object)method does.- Parameters:
t- the object to compute hash code for- Returns:
- a hash code for the given object
-
hash
public abstract int hash(T t)
Returns a hash code for the given object. Thetobject is assumed to be non-null.This method has the following properties:
- It is consistent: for any reference
x, multiple invocations ofhash(x)consistently return the same value providedxremains unchanged according to the definition of the equivalence. The hash need not remain consistent from one execution of an application to another execution of the same application. - It is distributable across equivalence: for any references
xandy, ifequivalent(x, y), thenhash(x) == hash(y). It is not necessary that the hash be distributable across inequivalence. Ifequivalence(x, y)is false,hash(x) == hash(y)may still be true.
This method is called by
nullableHash(Object).- Parameters:
t- the object to compute hash code for- Returns:
- a hash code for the given object
- It is consistent: for any reference
-
equals
public abstract boolean equals(Object o)
This method is made
abstractto force the Equivalence implementation to override it. This is needed because, for example,ObjObjMap's equality depends on the equality of key and valueEquivalenceobjects, configured for a map.
-
hashCode
public abstract int hashCode()
This method is made
abstractto force the Equivalence implementation to override it. This is needed becauseequals(Object)is also needed to be overridden.
-
-