[Java] 集合 (set)

java.util.set 为接口,集合共有3种具体类型:HashSet, LinkedSetTreeSet

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中保留set1set2的公共元素:

[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.

猜你喜欢

转载自blog.csdn.net/ftell/article/details/80830552