PredicateSet.java
package it.fulminazzo.yagl.structures;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.BiPredicate;
/**
* A type of set that uses a {@link BiPredicate} to compare two {@link E} elements when calling {@link #add(Object)}.
*
* @param <E> the type parameter
*/
public class PredicateSet<E> extends AbstractSet<E> implements Serializable {
protected final Set<E> internal;
protected final BiPredicate<E, E> addTest;
/**
* Instantiates a new Predicate set.
*
* @param addTest the predicate used to verify if an element is eligible for adding
*/
public PredicateSet(final @NotNull BiPredicate<E, E> addTest) {
this.addTest = addTest;
this.internal = new HashSet<>();
}
@Override
public int size() {
return this.internal.size();
}
@Override
public @NotNull Iterator<E> iterator() {
return this.internal.iterator();
}
@Override
public boolean add(E e) {
return add(e, false);
}
/**
* Adds the given element to the set.
*
* @param e the element
* @param replace if true, replace nonetheless.
* @return true if it was added
*/
public boolean add(E e, boolean replace) {
E internalE = getInternal(e);
if (internalE == null || (this.addTest.test(internalE, e) || replace)) {
if (internalE != null) this.internal.remove(internalE);
this.internal.add(e);
return true;
}
return false;
}
/**
* Gets the internal element that equals to the given one.
*
* @param e the element
* @return the internal element
*/
protected @Nullable E getInternal(@Nullable E e) {
return e == null ? null : this.internal.stream().filter(t -> t.equals(e)).findFirst().orElse(null);
}
}