diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java index 9c2497c690..d9964f9e9d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java @@ -8,13 +8,16 @@ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.function.Function; import net.sourceforge.pmd.annotation.InternalApi; @@ -29,6 +32,7 @@ import net.sourceforge.pmd.annotation.InternalApi; @Deprecated @InternalApi public final class CollectionUtil { + private static final int UNKNOWN_SIZE = -1; @SuppressWarnings("PMD.UnnecessaryFullyQualifiedName") public static final TypeMap COLLECTION_INTERFACES_BY_NAMES = new TypeMap(List.class, Collection.class, Map.class, Set.class); @@ -289,6 +293,109 @@ public final class CollectionUtil { return !isEmpty(items); } + /** + * Returns the set union of the given collections. + * + * @param c1 First collection + * @param c2 Second collection + * + * @return Union of both arguments + */ + @SafeVarargs + public static Set union(Collection c1, Collection c2, Collection... rest) { + Set union = new LinkedHashSet<>(c1); + union.addAll(c2); + for (Collection ts : rest) { + union.addAll(ts); + } + return union; + } + + /** + * Returns the set intersection of the given collections. + * + * @param c1 First collection + * @param c2 Second collection + * + * @return Intersection of both arguments + */ + @SafeVarargs + public static Set intersect(Collection c1, Collection c2, Collection... rest) { + Set union = new LinkedHashSet<>(c1); + union.retainAll(c2); + for (Collection ts : rest) { + union.retainAll(ts); + } + return union; + } + + + /** + * Returns the set difference of the first collection with the other + * collections. + * + * @param c1 First collection + * @param c2 Second collection + * + * @return Difference of arguments + */ + @SafeVarargs + public static Set diff(Collection c1, Collection c2, Collection... rest) { + Set union = new LinkedHashSet<>(c1); + union.removeAll(c2); + for (Collection ts : rest) { + union.removeAll(ts); + } + return union; + } + + + @SafeVarargs + public static Set setOf(T first, T... rest) { + if (rest.length == 0) { + return Collections.singleton(first); + } + Set union = new LinkedHashSet<>(); + union.add(first); + union.addAll(Arrays.asList(rest)); + return union; + } + + + @SafeVarargs + public static List listOf(T first, T... rest) { + if (rest.length == 0) { + return Collections.singletonList(first); + } + List union = new ArrayList<>(); + union.add(first); + union.addAll(Arrays.asList(rest)); + return union; + } + + public static List map(Collection from, Function f) { + return map(from.iterator(), from.size(), f); + } + + public static List map(Iterable from, Function f) { + return map(from.iterator(), UNKNOWN_SIZE, f); + } + + public static List map(Iterator from, Function f) { + return map(from, UNKNOWN_SIZE, f); + } + + private static List map(Iterator from, int sizeHint, Function f) { + if (!from.hasNext()) { + return Collections.emptyList(); + } + List res = sizeHint == UNKNOWN_SIZE ? new ArrayList<>() : new ArrayList<>(sizeHint); + while (from.hasNext()) { + res.add(f.apply(from.next())); + } + return res; + } + /** * Returns true if both arrays are if both are null or have zero-length, * otherwise return the false if their respective elements are not equal by