/* * Copyright 2014 Goldman Sachs. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gs.collections.impl.utility.internal; import java.util.Set; import com.gs.collections.api.LazyIterable; import com.gs.collections.api.block.function.Function; import com.gs.collections.api.block.function.Function2; import com.gs.collections.api.set.ImmutableSet; import com.gs.collections.api.set.MutableSet; import com.gs.collections.api.set.SetIterable; import com.gs.collections.api.tuple.Pair; import com.gs.collections.impl.set.mutable.SetAdapter; import com.gs.collections.impl.set.mutable.UnifiedSet; import com.gs.collections.impl.set.strategy.mutable.UnifiedSetWithHashingStrategy; import com.gs.collections.impl.tuple.Tuples; import com.gs.collections.impl.utility.Iterate; import com.gs.collections.impl.utility.LazyIterate; /** * Set algebra operations. * <p> * Most operations are non-destructive, i.e. no input sets are modified during execution. * The exception is operations ending in "Into." These accept the target collection of * the final calculation as the first parameter. */ public final class SetIterables { private SetIterables() { throw new AssertionError("Suppress default constructor for noninstantiability"); } public static <E> MutableSet<E> union( SetIterable<? extends E> setA, SetIterable<? extends E> setB) { return SetIterables.unionInto(setA, setB, UnifiedSet.<E>newSet()); } public static <E, R extends Set<E>> R unionInto( SetIterable<? extends E> setA, SetIterable<? extends E> setB, R targetSet) { Iterate.addAllIterable(setA, targetSet); Iterate.addAllIterable(setB, targetSet); return targetSet; } public static <E> MutableSet<E> intersect( SetIterable<? extends E> setA, SetIterable<? extends E> setB) { return SetIterables.intersectInto(setA, setB, UnifiedSet.<E>newSet()); } public static <E, R extends Set<E>> R intersectInto( SetIterable<? extends E> setA, SetIterable<? extends E> setB, R targetSet) { MutableSet<E> adapted = SetAdapter.adapt(targetSet); adapted.addAllIterable(setA); adapted.retainAllIterable(setB); return targetSet; } public static <E> MutableSet<E> difference( SetIterable<? extends E> minuendSet, SetIterable<? extends E> subtrahendSet) { return SetIterables.differenceInto(minuendSet, subtrahendSet, UnifiedSet.<E>newSet()); } public static <E, R extends Set<E>> R differenceInto( SetIterable<? extends E> minuendSet, SetIterable<? extends E> subtrahendSet, R targetSet) { MutableSet<E> adapted = SetAdapter.adapt(targetSet); adapted.addAllIterable(minuendSet); adapted.removeAllIterable(subtrahendSet); return targetSet; } public static <E> MutableSet<E> symmetricDifference( SetIterable<? extends E> setA, SetIterable<? extends E> setB) { return SetIterables.symmetricDifferenceInto(setA, setB, UnifiedSet.<E>newSet()); } public static <E, R extends Set<E>> R symmetricDifferenceInto( SetIterable<? extends E> setA, SetIterable<? extends E> setB, R targetSet) { return SetIterables.unionInto( SetIterables.difference(setA, setB), SetIterables.difference(setB, setA), targetSet); } public static <E> boolean isSubsetOf( SetIterable<? extends E> candidateSubset, SetIterable<? extends E> candidateSuperset) { return candidateSubset.size() <= candidateSuperset.size() && candidateSuperset.containsAllIterable(candidateSubset); } public static <E> boolean isProperSubsetOf( SetIterable<? extends E> candidateSubset, SetIterable<? extends E> candidateSuperset) { return candidateSubset.size() < candidateSuperset.size() && candidateSuperset.containsAllIterable(candidateSubset); } public static <T> MutableSet<MutableSet<T>> powerSet(Set<T> set) { MutableSet<MutableSet<T>> seed = UnifiedSet.<MutableSet<T>>newSetWith(UnifiedSet.<T>newSet()); return powerSetWithSeed(set, seed); } public static <T> MutableSet<MutableSet<T>> powerSet(UnifiedSetWithHashingStrategy<T> set) { MutableSet<MutableSet<T>> seed = UnifiedSet.<MutableSet<T>>newSetWith(set.newEmpty()); return powerSetWithSeed(set, seed); } private static <T> MutableSet<MutableSet<T>> powerSetWithSeed(Set<T> set, MutableSet<MutableSet<T>> seed) { return Iterate.injectInto(seed, set, new Function2<MutableSet<MutableSet<T>>, T, MutableSet<MutableSet<T>>>() { public MutableSet<MutableSet<T>> value(MutableSet<MutableSet<T>> accumulator, final T element) { return SetIterables.union(accumulator, accumulator.collect(new Function<MutableSet<T>, MutableSet<T>>() { public MutableSet<T> valueOf(MutableSet<T> innerSet) { return innerSet.clone().with(element); } })); } }); } /** * Returns an Immutable version of powerset where the inner sets are also immutable. */ public static <T> ImmutableSet<ImmutableSet<T>> immutablePowerSet(Set<T> set) { return powerSet(set).collect(new Function<MutableSet<T>, ImmutableSet<T>>() { public ImmutableSet<T> valueOf(MutableSet<T> set) { return set.toImmutable(); } }).toImmutable(); } public static <A, B> LazyIterable<Pair<A, B>> cartesianProduct(SetIterable<A> set1, final SetIterable<B> set2) { return LazyIterate.flatCollect(set1, new Function<A, LazyIterable<Pair<A, B>>>() { public LazyIterable<Pair<A, B>> valueOf(final A first) { return LazyIterate.collect(set2, new Function<B, Pair<A, B>>() { public Pair<A, B> valueOf(B second) { return Tuples.pair(first, second); } }); } }); } }