package org.codefx.libfx.collection.transform; import java.util.function.BiPredicate; import java.util.function.ToIntFunction; /** * Wraps elements which are pout into an inner hashing data structure and delegates {@link #equals(Object)} and * {@link #hashCode()} to functions specified during construction. * * @param <E> * the type of the wrapped elements */ class EqHash<E> { /** * The default hash code used for null keys. * <p> * This value is mentioned in the comments of {@link EqualityTransformingMap} and {@link EqualityTransformingSet}. * Update on change. */ public static final int NULL_KEY_HASH_CODE = 0; private final E element; private final BiPredicate<? super E, ? super E> equals; private final ToIntFunction<? super E> hash; private EqHash(E element, BiPredicate<? super E, ? super E> equals, ToIntFunction<? super E> hash) { // null is allowed as an element assert equals != null : "The argument 'equals' must not be null."; assert hash != null : "The argument 'hash' must not be null."; this.element = element; this.equals = equals; this.hash = hash; } /** * @param <E> * the type of the wrapped elements * @param element * the wrapped element; may be null * @param equals * the function computing equality of two elements * @param hash * the function computing the hash code of the element * @return an instance of {@link EqHash} */ public static <E> EqHash<E> create( E element, BiPredicate<? super E, ? super E> equals, ToIntFunction<? super E> hash) { return new EqHash<E>(element, equals, hash); } /** * @return the wrapped element */ public E getElement() { return element; } @Override public int hashCode() { return hash.applyAsInt(element); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof EqHash)) return false; @SuppressWarnings("unchecked") // This cast is ok because no instance of EqHash can ever leave the inner map (without being transformed // by the equality transforming map). // If it can not leave it can not end up in an equality test in another map. EqHash<E> other = (EqHash<E>) obj; return equals.test(this.element, other.element); } @Override public String toString() { return "EqHash [" + element + "]"; } }