Skip to content

Instantly share code, notes, and snippets.

@hakanai
Last active October 31, 2018 04:20
Show Gist options
  • Save hakanai/df5f6a81c20a2d38aba556d1b0b704f0 to your computer and use it in GitHub Desktop.
Save hakanai/df5f6a81c20a2d38aba556d1b0b704f0 to your computer and use it in GitHub Desktop.
I don't suppose there's a library like this out there somewhere already?
package magicutilities;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class EvenMoreObjects {
private EvenMoreObjects() {
}
public static <T> EqualsHelper<T> equalsHelper(@Nonnull T object, @Nonnull Class<T> expectedClass, @Nullable Object otherObject) {
if (otherObject == object) { // This branch might not even be helping anything
return EqualsHelper.trueTerminator();
}
if (!expectedClass.isInstance(otherObject)) {
return EqualsHelper.falseTerminator();
}
return EqualsHelper.chain(object, expectedClass.cast(otherObject));
}
public abstract static class EqualsHelper<T> {
public abstract EqualsHelper<T> append(Function<T, Object> getter);
public abstract boolean isEqual();
private static <T> EqualsHelper<T> falseTerminator() {
return new EqualsHelper<T>() {
@Override
public EqualsHelper<T> append(Function<T, Object> getter) {
return this;
}
@Override
public boolean isEqual() {
return false;
}
};
}
private static <T> EqualsHelper<T> trueTerminator() {
return new EqualsHelper<T>() {
@Override
public EqualsHelper<T> append(Function<T, Object> getter) {
return this;
}
@Override
public boolean isEqual() {
return true;
}
};
}
private static <T> EqualsHelper<T> chain(@Nonnull T object, @Nonnull T otherObject) {
return new EqualsHelper<T>() {
@Override
public EqualsHelper<T> append(Function<T, Object> getter) {
return Objects.equals(getter.apply(object), getter.apply(otherObject)) ?
this :
falseTerminator();
}
@Override
public boolean isEqual() {
return true;
}
};
}
}
public static <T> HashCodeHelper<T> hashCodeHelper(@Nonnull T object) {
return HashCodeHelper.chain(object);
}
public abstract static class HashCodeHelper<T> {
public abstract HashCodeHelper<T> append(ToIntFunction<T> fieldHash);
public abstract int toHashCode();
private static <T> HashCodeHelper<T> chain(@Nonnull T object) {
return new HashCodeHelper<T>() {
private int accumulator = 0;
@Override
public HashCodeHelper<T> append(ToIntFunction<T> fieldHash) {
accumulator = accumulator * 31 + fieldHash.applyAsInt(object);
return this;
}
@Override
public int toHashCode() {
return accumulator;
}
};
}
}
}
package magicutilities.example;
import magicutilities.EvenMoreObjects;
import javax.annotation.Nullable;
public class Example {
private final String name;
private final int age;
public Example(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean equals(@Nullable Object object) {
return EvenMoreObjects.equalsHelper(this, Example.class, object)
.append(Example::getName)
.append(Example::getAge)
.isEqual();
}
public int hashCode() {
return EvenMoreObjects.hashCodeHelper(this)
.append(Example::getName)
.append(Example::getAge)
.toHashCode();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment