com.slimgears.util.stream.Equality Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stream-utils Show documentation
Show all versions of stream-utils Show documentation
General purpose utils / module: stream-utils
package com.slimgears.util.stream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
public class Equality {
public interface Checker {
boolean equals(T self, Object other);
int hashCode(T self);
}
public static Checker of(BiFunction equalityTester, Function hashCodeGen) {
return new Checker() {
public boolean equals(T self, Object other) {
return equalityTester.apply(self, other);
}
@Override
public int hashCode(T self) {
return hashCodeGen.apply(self);
}
};
}
public static Checker of(Class cls, Function field) {
Checker checker = ofField(cls, field);
return of(checkNullAndIdentity(checker::equals), checker::hashCode);
}
private static BiFunction checkNullAndIdentity(BiFunction equalityTester) {
return (self, other) -> (other == self) || (other != null) && equalityTester.apply(self, other);
}
@SuppressWarnings("unchecked")
private static Checker ofField(Class cls, Function field) {
BiFunction equalityTester = (self, other) ->
cls.isInstance(other) &&
Objects.equals(field.apply(self), field.apply((T)other));
Function hashCodeGen = self -> Objects.hash(field.apply(self));
return of(equalityTester, hashCodeGen);
}
public static Builder builder(Class cls) {
return new Builder<>(cls);
}
public static class Builder {
private final Collection> fields = new ArrayList<>();
private final Class cls;
public Builder(Class cls) {
this.cls = cls;
}
public Builder add(Function field) {
this.fields.add(field);
return this;
}
@SuppressWarnings("unchecked")
public Checker build() {
BiFunction equalityChecker = (self, other) -> (other == self) ||
(cls.isInstance(other) && fields.stream()
.allMatch(f -> Objects.equals(f.apply(self), f.apply((T)other))));
Function hashCodeGen = self -> Objects.hash(fields.stream().map(f -> f.apply(self)).toArray(Object[]::new));
return of(equalityChecker, hashCodeGen);
}
}
}