/* * SetUtils.java * * Copyright (C) 2009 Leo Osvald <leo.osvald@gmail.com> * * This file is part of SGLJ. * * SGLJ is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SGLJ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see <http://www.gnu.org/licenses/>. */ package org.sglj.util; import java.util.Collection; import java.util.Comparator; import java.util.Set; import java.util.TreeSet; /** * Utility class with various methods regarding sets. * * @author Leo Osvald * */ public class SetUtils { protected SetUtils() { } /** * Sets contents of set <code>dest</code> to match the one from * <code>src</code> collection (ignoring duplicates).<br> * The equivalence of the assignment operator (=) for primitive types. * @param <T> * @param dest * @param src */ public static <T> void copy(Set<? super T> dest, Collection<? extends T> src) { dest.retainAll(src); dest.addAll(src); } /** * Moves all the contents from <code>src</code> collection to * <code>dest</code> set. * @param <T> * @param dest * @param src */ public static <T> void move(Set<? super T> dest, Collection<? extends T> src) { dest.retainAll(src); dest.addAll(src); src.clear(); } /** * Moves all elements contained in <code>elements</code> collection * from <code>src</code> set to <code>dest</code> set. * @param <T> type * @param dest set to which the elements should be moved * @param src set from which the elements should be moved * @param elements collection which contains elements which * should be moved from one set to another. */ public static <T> void moveElements(Set<? super T> dest, Set<? extends T> src, Collection<T> elements) { dest.addAll(elements); src.removeAll(elements); } /** * Returns the reverse comparator.<br> * That comparator's {@link Comparator#compare(Object, Object)} method * will the same absolute value but with reversed sign. * @param <T> type * @param cmp comparator * @return reverse comparator */ public static <T> Comparator<T> reverseComparator(final Comparator<T> cmp) { return new Comparator<T>() { @Override public int compare(T o1, T o2) { return -cmp.compare(o1, o2); } }; } /** * Clears the initial set, and creates a new one with same contents * and has the specified comparator. * @param <T> type * @param set set which is cleared and whose elements should contain * the newly create one (which is returned) * @param cmp comparator * @return copy of the specified set with the specified comparator */ public static <T> TreeSet<T> changeComparator(TreeSet<T> set, Comparator<? super T> cmp) { TreeSet<T> ret = new TreeSet<T>(cmp); ret.addAll(set); set.clear(); return ret; } /** * Returns the set difference of the two sets, A \ B. * Collections <code>a</code> and <code>b</code> will remain unchanged, * and <code>result</code> collection will contain the elements * which belongs to the set A\B. Unique elements from collections * <code>a</code> and <code>b</code> form the corresponding sets A and B. * @param <E> type of the elements in the two sets * @param <T> return type (some set) * @param a collection * @param b collection * @param result set set which should contain the result * of the set difference * @return result set - which was passed as the last argument */ public static <E, T extends Set<E>> T difference(Collection<E> a, Collection<E> b, T result) { if(!result.isEmpty()) result.clear(); result.addAll(a); result.removeAll(b); return result; } /** * Returns the set intersection of the two sets, A &cap B. * Collections <code>a</code> and <code>b</code> will remain unchanged, * and <code>result</code> collection will contain the elements * which belongs to the set A &cap B. Unique elements from collections * <code>a</code> and <code>b</code> form the corresponding sets A and B. * @param <E> type of the elements in the two sets * @param <T> return type (some set) * @param a collection * @param b collection * @param result set set which should contain the result * of the set intersection * @return result set - which was passed as the last argument */ public static <E, T extends Set<E>> T intersection(Collection<E> a, Collection<E> b, T result) { if(!result.isEmpty()) result.clear(); result.addAll(a); result.retainAll(b); return result; } /** * Returns the set union of the two sets, A &cup B. * Collections <code>a</code> and <code>b</code> will remain unchanged, * and <code>result</code> collection will contain the elements * which belongs to the set A &cup B. Unique elements from collections * <code>a</code> and <code>b</code> form the corresponding sets A and B. * @param <E> type of the elements in the two sets * @param <T> return type (some set) * @param a collection * @param b collection * @param result set set which should contain the result * of the set union * @return result set - which was passed as the last argument */ public static <E, T extends Set<E>> T union(Collection<E> a, Collection<E> b, T result) { if(!result.isEmpty()) result.clear(); result.addAll(a); result.addAll(b); return result; } /** * Returns the set union of the two sets, A &Delta B. * Collections <code>a</code> and <code>b</code> will remain unchanged, * and <code>result</code> collection will contain the elements * which belongs to the set A &Delta B. Unique elements from collections * <code>a</code> and <code>b</code> form the corresponding sets A and B. * @param <E> type of the elements in the two sets * @param <T> return type (some set) * @param a collection * @param b collection * @param result set set which should contain the result * of the set union * @return result set - which was passed as the last argument */ public static <E, T extends Set<E>> T symmetricDifference(Set<E> a, Set<E> b, T result) { if(!result.isEmpty()) result.clear(); for(E curr : a) if(!b.contains(curr)) result.add(curr); for(E curr : b) if(!a.contains(curr)) result.add(curr); return result; } }