io.permazen.util.NavigableSets Maven / Gradle / Ivy
Show all versions of permazen-util Show documentation
/*
* Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
*/
package io.permazen.util;
import com.google.common.base.Preconditions;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.NavigableSet;
import java.util.stream.Collectors;
/**
* Utility methods relating to {@link NavigableSet}.
*/
public final class NavigableSets {
private NavigableSets() {
}
/**
* Create a read-only view of the intersection of two or more {@link NavigableSet}s that have a consistent sort order.
* The {@linkplain NavigableSet#comparator Comparator}s of the sets must all be {@linkplain Comparator#equals equal}
* (or else all null, for natural ordering).
*
*
* The returned intersection iterates efficiently: a complete iteration requires O(N * M) queries, where
* N is the size of the smallest set, and M is the number of sets.
*
* @param sets the sets to intersect
* @param element type
* @return the intersection of all {@code sets}
* @throws IllegalArgumentException if the {@code sets} do not have equal {@link Comparator}s
* @throws IllegalArgumentException if {@code sets}, or any {@link NavigableSet} therein, is null
*/
public static NavigableSet intersection(Collection extends NavigableSet> sets) {
Preconditions.checkArgument(sets != null, "null sets");
if (sets.stream().anyMatch(EmptyNavigableSet.class::isInstance))
return new EmptyNavigableSet<>(null);
return new IntersectionNavigableSet<>(sets);
}
/**
* Create a read-only view of the intersection of two or more {@link NavigableSet}s that have a consistent sort order.
* The {@linkplain NavigableSet#comparator Comparator}s of the sets must all be {@linkplain Comparator#equals equal}
* (or else all null, for natural ordering).
*
*
* The returned intersection iterates efficiently: a complete iteration takes time O(N * M) where
* N is the size of the smallest set, and M is the number of sets.
*
* @param sets the sets to intersect
* @param element type
* @return the intersection of all {@code sets}
* @throws IllegalArgumentException if the {@code sets} do not have equal {@link Comparator}s
* @throws IllegalArgumentException if {@code sets}, or any {@link NavigableSet} therein, is null
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static NavigableSet intersection(NavigableSet... sets) {
Preconditions.checkArgument(sets != null, "null sets");
return NavigableSets.intersection(Arrays.asList(sets));
}
/**
* Create a read-only view of the union of two or more {@link NavigableSet}s that have a consistent sort order.
* The {@linkplain NavigableSet#comparator Comparator}s of the sets must all be {@linkplain Comparator#equals equal}
* (or else all null, for natural ordering).
*
* @param sets the sets to union
* @param element type
* @return the union of all {@code sets}
* @throws IllegalArgumentException if the {@code sets} do not have equal {@link Comparator}s
* @throws IllegalArgumentException if {@code sets}, or any {@link NavigableSet} therein, is null
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static NavigableSet union(NavigableSet... sets) {
Preconditions.checkArgument(sets != null, "null sets");
return NavigableSets.union(Arrays.asList(sets));
}
/**
* Create a read-only view of the union of two or more {@link NavigableSet}s that have a consistent sort order.
* The {@linkplain NavigableSet#comparator Comparator}s of the sets must all be {@linkplain Comparator#equals equal}
* (or else all null, for natural ordering).
*
* @param sets the sets to union
* @param element type
* @return the union of all {@code sets}
* @throws IllegalArgumentException if the {@code sets} do not have equal {@link Comparator}s
* @throws IllegalArgumentException if {@code sets}, or any {@link NavigableSet} therein, is null
*/
public static NavigableSet union(Collection extends NavigableSet> sets) {
Preconditions.checkArgument(sets != null, "null sets");
sets = sets.stream()
.filter(set -> !(set instanceof EmptyNavigableSet))
.collect(Collectors.toList());
return sets.isEmpty() ? new EmptyNavigableSet<>(null) : new UnionNavigableSet<>(sets);
}
/**
* Create a read-only view of the difference of two {@link NavigableSet}s that have a consistent sort order.
* That is, a set containing all elements contained in the first set but not the second.
* The {@linkplain NavigableSet#comparator Comparator}s of the sets must all be {@linkplain Comparator#equals equal}
* (or else all null, for natural ordering).
*
* @param set1 original set
* @param set2 set of elements to exclude from {@code set1}
* @param element type
* @return the difference of {@code set1} and {@code set2}
* @throws IllegalArgumentException if the {@code set1} and {@code set2} do not have equal {@link Comparator}s
* @throws IllegalArgumentException if either parameter is is null
*/
public static NavigableSet difference(NavigableSet set1, NavigableSet set2) {
if (set1 instanceof EmptyNavigableSet || set2 instanceof EmptyNavigableSet)
return set1;
return new DifferenceNavigableSet<>(set1, set2);
}
/**
* Create a read-only view of the symmetric difference of two {@link NavigableSet}s that have a consistent sort order.
* That is, the set containing all elements contained in the first set or the second set, but not in both sets.
* The {@linkplain NavigableSet#comparator Comparator}s of the sets must all be {@linkplain Comparator#equals equal}
* (or else all null, for natural ordering).
*
* @param set1 first set
* @param set2 second set
* @param element type
* @return the symmetric difference of {@code set1} and {@code set2}
* @throws IllegalArgumentException if the {@code set1} and {@code set2} do not have equal {@link Comparator}s
* @throws IllegalArgumentException if either parameter is is null
*/
public static NavigableSet symmetricDifference(NavigableSet set1, NavigableSet set2) {
if (set1 instanceof EmptyNavigableSet)
return set2;
if (set2 instanceof EmptyNavigableSet)
return set1;
return NavigableSets.difference(NavigableSets.union(set1, set2), NavigableSets.intersection(set1, set2));
}
/**
* Create a {@link NavigableSet} containing a single element and natural ordering.
*
* @param value singleton value
* @param element type
* @return singleton set
* @throws IllegalArgumentException if {@code value} is null or
* {@code value}'s class has no natural ordering (i.e., does not implement {@link Comparable})
*/
public static NavigableSet singleton(E value) {
return NavigableSets.singleton(null, value);
}
/**
* Create a {@link NavigableSet} containing a single element.
*
* @param comparator comparator, or null for natural ordering
* @param value singleton value (possibly null)
* @param element type
* @return singleton set
* @throws IllegalArgumentException if {@code comparator} is null and either {@code value} is null or
* {@code value}'s class has no natural ordering (i.e., does not implement {@link Comparable})
*/
public static NavigableSet singleton(Comparator super E> comparator, E value) {
return new SingletonNavigableSet<>(comparator, value);
}
/**
* Create an empty {@link NavigableSet}.
* The returned set's {@link NavigableSet#comparator comparator()} method will return null.
*
* @param element type
* @return empty set
*/
public static NavigableSet empty() {
return NavigableSets.empty(null);
}
/**
* Create an empty {@link NavigableSet} with a specified {@link Comparator}.
*
* @param comparator comparator, or null for natural ordering
* @param element type
* @return empty set
*/
public static NavigableSet empty(Comparator super E> comparator) {
return new EmptyNavigableSet<>(comparator);
}
/**
* Get a non-null {@link Comparator} that sorts consistently with, and optionally reversed from, the given {@link Comparator}.
*
* @param comparator comparator, or null for natural ordering
* @param reversed whether to return a reversed {@link Comparator}
* @param compared type
* @return a non-null {@link Comparator}
*/
@SuppressWarnings("unchecked")
static Comparator getComparator(Comparator comparator, boolean reversed) {
if (comparator == null)
comparator = (Comparator)Comparator.naturalOrder();
return reversed ? comparator.reversed() : comparator;
}
}