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: thisEquivalence
forces 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 onEquivalence
equality.In most cases, when
Equivalence
is stateless, you can extendStatelessEquivalence
not to bother with implementing these methods. See examples in the documentation to identity and case insensitive equivalences.
-
-
Constructor Summary
Constructors Modifier Constructor Description protected
Equivalence()
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 theString
equivalence that usesString.equalsIgnoreCase(java.lang.String)
to compare strings.static Equivalence<CharSequence>
charSequence()
Returns the equivalence that comparesCharSequence
s 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.Entry
equivalence for the given key and value equivalences.abstract boolean
equals(Object o)
abstract boolean
equivalent(T a, T b)
Returnstrue
ifa
andb
are considered equivalent,false
otherwise.abstract int
hash(T t)
Returns a hash code for the given object.abstract int
hashCode()
static <T> Equivalence<T>
identity()
Returns the equivalence that uses==
to compare objects andSystem.identityHashCode(Object)
to compute the hash code.boolean
nullableEquivalent(T a, T b)
Returnstrue
ifa
andb
are considered equivalent,false
otherwise.int
nullableHash(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)
returnstrue
ifa == b
, including in the case whena
andb
are 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 comparesCharSequence
s 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
CharSequence
equivalence
-
caseInsensitive
public static Equivalence<String> caseInsensitive()
Returns theString
equivalence 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
String
equivalence
-
entryEquivalence
public static <K,V> Equivalence<Map.Entry<K,V>> entryEquivalence(Equivalence<K> keyEquivalence, Equivalence<V> valueEquivalence)
Returns aMap.Entry
equivalence 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.Entry
equivalence for the given key and value equivalences
-
nullableEquivalent
public boolean nullableEquivalent(@Nullable T a, @Nullable T b)
Returnstrue
ifa
andb
are considered equivalent,false
otherwise.a
andb
both might benull
.If the implementation overrides this method, it must ensure that it returns
true
if both the given objects are nulls andfalse
, if only one of them isnull
. If botha
andb
are 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:
true
ifa
andb
are considered equivalent,false
otherwise
-
equivalent
public abstract boolean equivalent(T a, T b)
Returnstrue
ifa
andb
are considered equivalent,false
otherwise.a
andb
are 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
x
andy
,equivalent(x, y) == equivalent(y, x)
. - It is transitive: for any references
x
,y
, andz
, ifequivalent(x, y)
returnstrue
andequivalent(y, z)
returnstrue
, thenequivalent(x, z)
returnstrue
. - It is consistent: for any references
x
andy
, multiple invocations ofequivalent(x, y)
consistently returntrue
or consistently returnfalse
(provided that neitherx
nory
is modified).
This method is called by
nullableEquivalent(Object, Object)
.- Parameters:
a
- the first object to compareb
- the second object to compare- Returns:
true
ifa
andb
are considered equivalent,false
otherwise
- It is reflexive: for any reference
-
nullableHash
public int nullableHash(@Nullable T t)
Returns a hash code for the given object. Thet
object might benull
.If the implementation overrides this method, it must ensure that it returns
0
if 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. Thet
object 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 providedx
remains 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
x
andy
, 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
abstract
to force the Equivalence implementation to override it. This is needed because, for example,ObjObjMap
's equality depends on the equality of key and valueEquivalence
objects, configured for a map.
-
hashCode
public abstract int hashCode()
This method is made
abstract
to force the Equivalence implementation to override it. This is needed becauseequals(Object)
is also needed to be overridden.
-
-