class CollectionHelper {

    public static <T> Set<T> intersect(Set<? extends T> setA, Set<? extends T> setB) {
        Validate.notNull(setA, "setA must not be null");
        Validate.notNull(setB, "setB must not be null");
        // the most common variant to calculate an intersection is something like this:
        // Set intersection = new HashSet(setA); intersection.retainAll(setB);
        // however, if both sets have considerably different sizes, this can be optimized,
        // by iterating over the smaller set and checking whether the current element
        // occurs in the larger set:
        Set<? extends T> smallerSet = setA;
        Set<? extends T> largerSet = setB;
        if (smallerSet.size() > largerSet.size()) { // swap smaller/larger set if necessary
            smallerSet = setB;
            largerSet = setA;
        }
        Set<T> intersection = new HashSet<>();
        for (T element : smallerSet) {
            if (largerSet.contains(element)) {
                intersection.add(element);
            }
        }
        return intersection;
    }

    private  CollectionHelper();

}