/*******************************************************************************
* Copyright 2014 Felipe Takiyama
*
* 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 br.usp.poli.takiyama.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import br.usp.poli.takiyama.prv.Replaceable;
import br.usp.poli.takiyama.prv.Substitution;
/**
* This class provides common operations over sets.
* @author ftakiyama
*
*/
public final class Sets {
private Sets() {
// avoids instantiation
}
/**
* Returns an empty set with size adapted to load factor of 0.75.
*/
public static final <T> Set<T> getInstance(int size) {
return new HashSet<T>((int) Math.ceil(size / 0.75));
}
public static final <T> Set<T> union(Set<T> set1, Set<T> set2) {
Set<T> set = Sets.getInstance(set1.size() + set2.size());
set.addAll(set1);
set.addAll(set2);
return set;
}
public static final <T> Set<T> union(Set<T> set1, Set<T> set2, Set<T> set3, Set<T> set4) {
Set<T> union = Sets.getInstance(set1.size() + set2.size() + set3.size()
+ set4.size());
union.addAll(set1);
union.addAll(set2);
union.addAll(set3);
union.addAll(set4);
return union;
}
public static final <T> Set<T> union(Collection<Set<T>> collectionOfSets) {
Set<T> union = new HashSet<T>();
for (Set<T> s : collectionOfSets) {
union.addAll(s);
}
return union;
}
public static final <T> Set<T> setOf(T e1) {
Set<T> set = Sets.getInstance(1);
set.add(e1);
return set;
}
public static final <T> Set<T> setOf(T e1, T e2) {
Set<T> set = Sets.getInstance(2);
set.add(e1);
set.add(e2);
return set;
}
public static final <T> Set<T> setOf(T e1, T e2, T e3) {
Set<T> set = Sets.getInstance(3);
set.add(e1);
set.add(e2);
set.add(e3);
return set;
}
public static final <T> Set<T> setOf(Collection<? extends T> c) {
return new HashSet<T>(c);
}
/**
* Returns the result of applying the specified substitution to the
* elements of the specified set.
* <p>
* When the result of applying of the substitution to a given element from
* the set is invalid, it is not added to the returned set.
* </p>
*
* @param <T> A {@link Replaceable} type
* @param s The substitution to be made
* @param set The set containing the elements to be substituted
* @return The result of applying the specified substitution to the
* elements of the specified set.
*/
public static final <T extends Replaceable<T>> Set<T> apply(Substitution s, Set<T> set) {
Set<T> replaced = Sets.getInstance(set.size());
for (Replaceable<T> element : set) {
try {
replaced.add(element.apply(s));
} catch (IllegalArgumentException e) {
// invalid replaceable is not added to the set
} catch (IllegalStateException e) {
// invalid replaceable is not added to the set
}
}
return replaced;
}
/**
* Returns the result of ordering the specified set using the specified
* comparator. The result is given in a list.
*
* @param <T> The type of element being ordered
* @param set The set to be ordered
* @param comparator The comparator to use to sort the set.
* @return The specified set sorted.
*/
public static final <T> List<T> sort(Set<T> set, Comparator<T> comparator) {
List<T> ordered = new ArrayList<T>(set);
Collections.sort(ordered, comparator);
return ordered;
}
/**
* Returns the difference between the specified set and the specified
* collection. That is, returns a set containing all elements in the set
* that are not in the collection.
* @param <T>
* @param set
* @param collection
* @return
*/
public static final <T> Set<T> difference(Set<T> set, Collection<T> collection) {
Set<T> difference = getInstance(set.size());
for (T element : set) {
if (!collection.contains(element)) {
difference.add(element);
}
}
return difference;
}
/**
* Returns the intersection of the specified sets.
* @param <T>
* @param set1
* @param set2
* @return
*/
public static final <T> Set<T> intersection(Set<T> set1, Set<T> set2) {
Set<T> intersection = getInstance(set1.size());
for (T element : set1) {
if (set2.contains(element)) {
intersection.add(element);
}
}
return intersection;
}
}