java.util.set
为接口,集合共有3种具体类型:HashSet
, LinkedSet
和 TreeSet
。
HashSet
元素无序。
LinkedSet
元素按添加顺序排列。
TreeSet
元素有序。
集合的哈希码为集合中所有元素的哈希码之和。
因为AbstractSet
类没有实现size
方法和iterator
方法,因此AbstractSet
类为抽象类。
HashSet
类是实现了Set
接口的具体类。
如果两个对象相等,那么它们的哈希码必须相同。但是两个不等的对象的哈希码有可能相同,但是这种情况要尽量避免。Java API中的绝大多数类都实现了hashCode
方法。例如, Integer 类的 hashCode返回他的 int值. Character类的hashCode方法返回字符的Unicode. The hashCode in the String class returns
s0*31(n - 1) + s1*31(n - 2) + c + sn - 1, where si is s.charAt(i).
例1 TestHashSet.java
import java.util.*;
public class TestHashSet {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("London");
set.add("Paris");
set.add("New York");
set.add("San Francisco");
set.add("Beijing");
set.add("New York");
System.out.println(set);
for (String s: set) {
System.out.print(s.toUpperCase() + " ");
}
}
}
例2 TestLinkedHashSet.java
import java.util.*;
public class TestLinkedHashSet {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();
set.add("London");
set.add("Paris");
set.add("New York");
set.add("San Francisco");
set.add("Beijing");
set.add("New York");
System.out.println(set);
for (String element: set)
System.out.print(element.toLowerCase() + " ");
}
}
例3 TestTreeSet.java
import java.util.*;
public class TestTreeSet {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("London");
set.add("Paris");
set.add("New York");
set.add("San Francisco");
set.add("Beijing");
set.add("New York");
TreeSet<String> treeSet = new TreeSet<String>(set);
System.out.println("Sorted tree set: " + treeSet);
System.out.println("first(): " + treeSet.first());
System.out.println("last(): " + treeSet.last());
System.out.println("headSet(\"New York\"): " + treeSet.headSet("New York"));
System.out.println("tailSet(\"New York\"): " + treeSet.tailSet("New York"));
// Use the methods in NavigableSet interface
System.out.println("lower(\"P\"): " + treeSet.lower("P"));
System.out.println("higher(\"P\"): " + treeSet.higher("P"));
System.out.println("floor(\"P\"): " + treeSet.floor("P"));
System.out.println("ceiling(\"P\"): " + treeSet.ceiling("P"));
System.out.println("pollFirst(): " + treeSet.pollFirst());
System.out.println("pollLast(): " + treeSet.pollLast());
System.out.println("New tree set: " + treeSet);
}
}
例4 TestMethodsInCollection.java
public class TestMethodsInCollection {
public static void main(String[] args) {
java.util.Set<String> set1 = new java.util.HashSet<String>();
set1.add("London");
set1.add("Paris");
set1.add("New York");
set1.add("San Francisco");
set1.add("Beijing");
System.out.println("set1 is " + set1);
System.out.println(set1.size() + " elements in set1");
set1.remove("London");
System.out.println("\nset1 is " + set1);
System.out.println(set1.size() + " elements in set1");
java.util.Set<String> set2 = new java.util.HashSet<String>();
set2.add("London");
set2.add("Shanghai");
set2.add("Paris");
System.out.println("\nset2 is " + set2);
System.out.println(set2.size() + " elements in set2");
System.out.println("\nIs Taipei in set2? " + set2.contains("Taipei"));
set1.addAll(set2);
System.out.println("\nAfter adding set2 to set1, set1 is " + set1);
set1.removeAll(set2);
System.out.println("After removing set2 from set1, set1 is " + set1);
set1.retainAll(set2);
System.out.println("After removing common elements in set2 " + "from set1, set1 is " + set1);
}
}
例5 CountKeywords.java
import java.util.*;
import java.io.*;
public class CountKeywords {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(System.in);
System.out.print("Enter a Java source file: ");
String filename = input.nextLine();
File file = new File(filename);
if (file.exists()) {
System.out.println("The number of keywords in " + filename + " is" + countKeywords(file));
}
else {
System.out.println("File " + filename + " does not exist");
}
}
public static int countKeywords(File file) throws Exception {
// Array of all Java keywords + true, false and null
String[] keywordString = {"abstract", "assert", "boolean",
"break", "byte", "case", "catch", "char", "class", "const",
"continue", "default", "do", "double", "else", "enum",
"extends", "for", "final", "finally", "float", "goto",
"if", "implements", "import", "instanceof", "int",
"interface", "long", "native", "new", "package", "private",
"protected", "public", "return", "short", "static",
"strictfp", "super", "switch", "synchronized", "this",
"throw", "throws", "transient", "try", "void", "volatile",
"while", "true", "false", "null"};
Set<String> keywordSet = new HashSet<String>(Arrays.asList(keywordString));
int count = 0;
Scanner input = new Scanner(file);
while (input.hasNext()) {
String word = input.next();
if (keywordSet.contains(word))
count++;
}
return count;
}
}
例6 SetListPerformanceTest.java
import java.util.*;
public class SetListPerformanceTest {
static final int N = 50000;
public static void main(String[] args) {
// Add numbers 0, 1, 2, ..., N - 1 to the array list
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < N; i++)
list.add(i);
Collections.shuffle(list); // Shuffle the array list
// Create a hash set, and test its performance
Collection<Integer> set1 = new HashSet<Integer>(list);
System.out.println("Member test time for hash set is " + getTestTime(set1) + " milliseconds");
System.out.println("Remove element time for hash set is " + getRemoveTime(set1) + " milliseconds");
// Create a linked hash set, and test its performance
Collection<Integer> set2 = new LinkedHashSet<Integer>(list);
System.out.println("Member test time for linked hash set is " + getTestTime(set2) + " milliseconds");
System.out.println("Remove element time for linked hash set is " + getRemoveTime(set2) + " milliseconds");
// Create a tree set, and test its performance
Collection<Integer> set3 = new TreeSet<Integer>(list);
System.out.println("Member test time for tree set is " + getTestTime(set3) + " milliseconds");
System.out.println("Remove element time for tree set is " + getRemoveTime(set3) + " milliseconds");
// Create an array list, and test its performance
Collection<Integer> list1 = new ArrayList<Integer>(list);
System.out.println("Member test time for array list is " + getTestTime(list1) + " milliseconds");
System.out.println("Remove element time for array list is " + getRemoveTime(list1) + " milliseconds");
// Create a linked list, and test its performance
Collection<Integer> list2 = new LinkedList<Integer>(list);
System.out.println("Member test time for linked list is " + getTestTime(list2) + " milliseconds");
System.out.println("Remove element time for linked list is " + getRemoveTime(list2) + " milliseconds");
}
public static long getTestTime(Collection<Integer> c) {
long startTime = System.currentTimeMillis();
// Test if a number is in the collection
for (int i = 0; i < N; i++)
c.contains((int)(Math.random() * 2 * N));
return System.currentTimeMillis() - startTime;
}
public static long getRemoveTime(Collection<Integer> c) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < N; i++)
c.remove(i);
return System.currentTimeMillis() - startTime;
}
}
书上的练习
21.1 How do you create an instance of Set? How do you insert a new element in a set?
How do you remove an element from a set? How do you find the size of a set?
代码如下:
import java.util.*;
Set<String> set = new HashSet<String>();
set.add("Test");
set.add("Test1");
set.remove("Test");
System.out.println(set.size());
21.2 If two objects o1
and o2
are equal, what is o1.equals(o2)
and o1.hashCode() == o2.hashCode()
?
表达式值为true
21.3 What are the differences between HashSet
,LinkedHashSet
, and TreeSet
?
HashSet
,LinkedHashSet
, 和TreeSet
都是具体类,但是HashSet
无序,LinkedHashSet
按插入顺序排序,TreeSet
有序。
21.4 How do you traverse the elements in a set?
可以使用循环:
for (int i = 0; i < aSet.length; i++)
System.out.pritnln(aSet[i]);
for (Object o: aSet)
System.out.println(o);
21.5 How do you sort the elements in a set using the compareTo
method in the
Comparable
interface? How do you sort the elements in a set using the Comparator
interface? What would happen if you added an element that could not be compared
with the existing elements in a tree set?
21.6 Suppose that set1 is a set that contains the strings red
, yellow
, and green
, and that set2 is another set that contains the strings red
, yellow
, and blue
. Answer the following questions:
■ What are in set1
and set2
after executing set1.addAll(set2)
?
[red, blue, green, yellow]
[red, blue, yellow]
■ What are in set1
and set2
after executing set1.add(set2)
?
没有set1.add(set2)
, 表达式不对
■ What are in set1
and set2
after executing set1.removeAll(set2)
?
[green]
[red, blue, yellow]
■ What are in set1
and set2
after executing set1.remove(set2)
?
但是,remove()
原型是remove(Object o)
, 只限于对象,不知道这题目为什么要这么写。
[red, green, yellow]
[red, blue, yellow]
■ What are in set1
and set2
after executing set1.retainAll(set2)
?
set1.retainAll(set2)
为在set1
中保留set1
和set2
的公共元素:
[red, yellow]
[red, blue, yellow]
■ What is in set1
after executing set1.clear()
?
[]
21.7 Show the output of the following code:
import java.util.*;
public class Test {
public static void main(String[] args) {
LinkedHashSet<String> set1 = new LinkedHashSet<>();
set1.add("New York");
LinkedHashSet<String> set2 = set1;
LinkedHashSet<String> set3 = (LinkedHashSet<String>)(set1.clone());
set1.add("Atlanta");
System.out.println("set1 is " + set1);
System.out.println("set2 is " + set2);
System.out.println("set3 is " + set3);
}
}
输出结果是:
set1 is [New York, Atlanta]
set2 is [New York, Atlanta]
set3 is [New York]
21.8 Show the output of the following code:
import java.util.*;
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception {
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("c:\\test.dat"));
LinkedHashSet<String> set1 = new LinkedHashSet<>();
set1.add("New York");
LinkedHashSet<String> set2 = (LinkedHashSet<String>)set1.clone();
set1.add("Atlanta");
output.writeObject(set1);
output.writeObject(set2);
output.close();
ObjectInputStream input = new ObjectInputStream(new FileInputStream("c:\\test.dat"));
set1 = (LinkedHashSet<String>)input.readObject();
set2 = (LinkedHashSet<String>)input.readObject();
System.out.println(set1);
System.out.println(set2);
output.close();
}
}
输出结果是:
[New York, Atlanta]
[New York]
21.9 What will the output be if lines 6–7 in Listing 21.5 is replaced by the following
code:
Set<GeometricObject> set = new HashSet<>();
输出是
21.10 Suppose you need to write a program that stores unordered non-duplicate elements, what data structure should you use?
会使用HashMap
21.11 Suppose you need to write a program that stores non-duplicate elements in the order of insertion, what data structure should you use?
会使用LinkedHashMap
21.12 Suppose you need to write a program that stores non-duplicate elements in increasing order of the element values, what data structure should you use?
会使用TreeMap
21.13 Suppose you need to write a program that stores a fixed number of the elements (possibly duplicates), what data structure should you use?
会使用数组
21.14 Suppose you need to write a program that stores the elements in a list with frequent operations to add and insert elements at the end of the list, what data structure should you use?
使用Stack?
21.15 Suppose you need to write a program that stores the elements in a list with frequent operations to add and insert elements at the beginning of the list, what data structure should you use?
使用Queue?
21.16 Will the CountKeywords program work if lines 33–34 are changed to
Set<String> keywordSet = new LinkedHashSet<>(Arrays.asList(keywordString));
21.17 Will the CountKeywords program work if lines 33–34 are changed to
List<String> keywordSet = new ArrayList<>(Arrays.asList(keywordString));
[1] Introduction to Java Programming 10th. edition Chapter 21.