Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
ASet
is aCollection
that cannot contain duplicate elements. It models the mathematical set abstraction. TheSet
interface contains only methods inherited fromCollection
, and adds the restriction that duplicate elements are prohibited.Set
also adds a stronger contract on the behavior of theequals
andhashCode
operations, allowingSet
instances to be compared meaningfully even if their implementation types differ. TwoSet
instances are equal if they contain the same elements.The
Set
interface is:The Java platform contains three general-purposepublic interface Set<E> extends Collection<E> { // Basic Operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); // Optional boolean remove(Object element); // Optional Iterator iterator(); // Bulk Operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); // Optional boolean removeAll(Collection<?> c); // Optional boolean retainAll(Collection<?> c); // Optional void clear(); // Optional // Array Operations Object[] toArray(); <T> T[] toArray(T[] a); }Set
implementations:HashSet
,TreeSet
, andLinkedHashSet
HashSet
, which stores its elements in a hash table, is the best-performing implementation but it makes no guarantees concerning the order of iteration.TreeSet
, which stores its elements in a red-black tree, orders its elements based on their values, but is substantially slower thanHashSet
.LinkedHashSet
, which is implemented as a hash table with a linked list running through it, orders its elements based on the order in which they were inserted into the set (insertion-order).LinkedHashSet
spares its clients from the unspecified, generally chaotic ordering provided byHashSet
, at a cost that is only slightly higher.Here's a simple but useful
Set
idiom. Suppose you have aCollection
,c
, and you want to create anotherCollection
containing the same elements but with all duplicates eliminated. The following one-liner does the trick:It works by creating aCollection<Type> noDups = new HashSet<Type>(c);Set
, which by definition, cannot contain duplicate,) initially containing all the elements inc
. It uses the standard conversion constructor described in the section The Collection Interface.Here is a minor variant of this idiom that preserves the order of the original collection while removing duplicate element:
Collection<Type> noDups = new HashSet<Type>(c);Here is a generic method that encapsulates the above idiom, returning a set of the same generic type as the one passed in:
public static <E> Set<E> removeDups(Collection<E> c) { return new LinkedHashSet<E>(c); }
Thesize
operation returns the number of elements in theSet
(its cardinality). TheisEmpty
method does exactly what you think it does. Theadd
method adds the specified element to theSet
if it's not already present, and returns a Boolean indicating whether the element was added. Similarly, theremove
method removes the specified element from theSet
if it's present and returns a Boolean indicating whether the element was present. Theiterator
method returns anIterator
over theSet
.Here's
a program
that takes the words in its argument list and prints out any duplicate words, the number of distinct words, and a list of the words with duplicates eliminated:Now let's run the program:import java.util.*; public class FindDups { public static void main(String args[]) { Set<String> s = new HashSet<String>(); for (String a : args) if (!s.add(a)) System.out.println("Duplicate: " + a); System.out.println(s.size()+" distinct words: "+s); } }The following output is produced:java FindDups i came i saw i leftNote that the code always refers to the collection by its interface type (Duplicate: i Duplicate: i 4 distinct words: [i, left, saw, came]Set
), rather than by its implementation type (HashSet
). This is a strongly recommended programming practice, as it gives you the flexibility to change implementations merely by changing the constructor. If either the variables used to store a collection or the parameters used to pass it around are declared to be of the collection's implementation type rather than its interface type, all such variables and parameters must be changed in order to change the collection's implementation type. Furthermore, there's no guarantee that the resulting program will work. If the program uses any nonstandard operations that are present in the original implementation type but not in the new one, the program will fail. Referring to collections only by their interface prevents you from using any nonstandard operations.The implementation type of the
Set
in the preceding example isHashSet
, which makes no guarantees as to the order of the elements in theSet
. If you want the program to print the word list in alphabetical order, merely change the set's implementation type fromHashSet
toTreeSet
. Making this trivial one-line change causes the command line in the previous example to generate the following output:java FindDups i came i saw i left Duplicate word: i Duplicate word: i 4 distinct words: [came, i, left, saw]
The bulk operations are particularly well suited toSets
; when applied to sets, they perform standard set-algebraic operations. Supposes1
ands2
areSets
. Here's what the bulk operations do:To calculate the union, intersection, or set difference of two sets nondestructively (without modifying either set), the caller must copy one set before calling the appropriate bulk operation. The resulting idioms follow:
s1.containsAll(s2)
: Returnstrue
ifs2
is a subset ofs1
. (s2
is a subset ofs1
if sets1
contains all the elements ins2
.)s1.addAll(s2)
: Transformss1
into the union ofs1
ands2
. (The union of two sets is the set containing all the elements contained in either set.)s1.retainAll(s2)
: Transformss1
into the intersection ofs1
ands2
. (The intersection of two sets is the set containing only the elements that are common to both sets.)s1.removeAll(s2)
: Transformss1
into the (asymmetric) set difference ofs1
ands2
. (For example, the set difference ofs1
-s2
is the set containing all the elements found ins1
but not ins2
.)The implementation type of the resultSet<Type> union = new HashSet<Type>(s1); union.addAll(s2); Set<Type> intersection = new HashSet<Type>(s1); intersection.retainAll(s2); Set<Type> difference = new HashSet<Type>(s1); difference.removeAll(s2);Set
in the preceding idioms isHashSet
, which is, as already mentioned, the best all-aroundSet
implementation in the Java platform. However, any general-purposeSet
implementation could be substituted.Let's revisit the
FindDups
program. Suppose that you want to know which words in the argument list occur only once and which occur more than once but that you do not want any duplicates printed out repeatedly. This effect can be achieved by generating two sets, one containing every word in the argument list and the other containing only the duplicates. The words that occur only once are the set difference of these two sets, which we know how to compute. Here's howthe resulting program
looks:When run with the same same argument list used earlier (import java.util.*; public class FindDups2 { public static void main(String args[]) { Set<String> uniques = new HashSet<String>(); Set<String> dups = new HashSet<String>(); for (String a : args) if (!uniques.add(a)) dups.add(a); // Destructive set-difference uniques.removeAll(dups); System.out.println("Unique words: " + uniques); System.out.println("Duplicate words: " + dups); } }i came i saw i left
), the program yields the output:A less common set-algebraic operation is the symmetric set difference: the set of elements contained in either of two specified sets but not in both. The following code calculates the symmetric set difference of two sets nondestructively:Unique words: [left, saw, came] Duplicate words: [i]Set<Type> symmetricDiff = new HashSet<Type>(s1); symmetricDiff.addAll(s2); Set<Type> tmp = new HashSet<Type>(s1); tmp.retainAll(s2)); symmetricDiff.removeAll(tmp);
The array operations don't do anything special forSets
beyond what they do for any otherCollection
. These operations are described in the section The Collection Interface.
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.