org.qbicc.graph.schedule.Util Maven / Gradle / Ivy
package org.qbicc.graph.schedule;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.function.IntFunction;
import java.util.stream.Stream;
import io.smallrye.common.constraint.Assert;
public final class Util {
private Util() {}
/**
* Get an immutable, cached copy of the given (possibly mutable) set from the given cache.
* The given set can be modified after this call.
*
* @param setCache the set cache (must not be {@code null})
* @param set the set to copy (must not be {@code null})
* @return the copied set (not {@code null})
*/
public static Set getCachedSet(Map, Set> setCache, Set set) {
if (set.isEmpty()) {
return Set.of();
}
Set cached = setCache.get(set);
if (cached == null) {
cached = Util.copyOfTrusted(set);
setCache.put(cached, cached);
}
return cached;
}
/**
* Copy the given set to an immutable set, without constructing an intermediate {@code HashSet}.
*
* @param orig the original set (must not be {@code null})
* @return the immutable copy (not {@code null})
* @param the element type
*/
public static Set copyOfTrusted(Set orig) {
if (orig.isEmpty()) {
return Set.of();
} else {
return Set.of((E[])orig.toArray(Object[]::new));
}
}
/**
* Create an instance of a tiny (immutable) set implementation that adds an item to an existing (immutable) set.
* If the original set already contains the item, it is returned as-is.
* Use for short-lived keys into hash tables that are keyed by set.
*
* @param orig the original set (must not be {@code null})
* @param item the item to add (must not be {@code null})
* @return the union set (not {@code null} or empty)
* @param the item type
*/
public static Set setWith(Set orig, E item) {
Assert.checkNotNullParam("orig", orig);
Assert.checkNotNullParam("item", item);
if (orig.isEmpty()) {
return Set.of(item);
} else if (orig.contains(item)) {
return orig;
} else {
return new WithSet<>(orig, item);
}
}
/**
* A tiny set object which adds one item to another set.
*/
private static final class WithSet extends AbstractSet {
private final E item;
private final Set orig;
private WithSet(Set orig, E item) {
this.item = item;
this.orig = orig;
}
@Override
public Iterator iterator() {
final Iterator delegate = orig.iterator();
return new Iterator() {
private E next = item;
@Override
public boolean hasNext() {
if (next != null) {
return true;
} else if (delegate.hasNext()) {
next = delegate.next();
return true;
} else {
return false;
}
}
@Override
public E next() {
if (! hasNext()) throw new NoSuchElementException();
try {
return next;
} finally {
next = null;
}
}
};
}
@Override
public int size() {
return orig.size() + 1;
}
@Override
public int hashCode() {
return orig.hashCode() + item.hashCode();
}
@SuppressWarnings("SuspiciousMethodCalls")
@Override
public boolean equals(Object other) {
return other == this || other instanceof Set> set && size() == set.size() && hashCode() == set.hashCode() && set.contains(item) && set.containsAll(orig);
}
@Override
public boolean contains(Object o) {
return item.equals(o) || orig.contains(o);
}
@Override
public Stream stream() {
return Stream.concat(Stream.of(item), orig.stream());
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Object[] toArray() {
return toArray(Object[]::new);
}
@Override
public T[] toArray(T[] a) {
if (a.length >= size()) {
return toArray(ignored -> a);
} else {
return toArray(size -> Arrays.copyOf(a, size));
}
}
@Override
public T[] toArray(IntFunction generator) {
final int size = size();
T[] array = orig.toArray(generator.apply(size));
array[size - 1] = (T) item;
return array;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy