Set集合为集类型,集是最简单的一种集合,存放于集中的对象不按特定方式排序,只是简单地把对象加入集合中,类似于向口袋里放东西。对集中存在的对象的访问和操作是通过对象的引用进行的,因此在集中不能存放重复对象。Set集合包括Set接口以及Set接口的所有实现类。因为Set接口继承了Collection接口,所以Set接口拥有Collection接口提供的所有常用方法。
(1)使用HashSet类
由HashSet类实现的Set集合的优点是能够快速定位集合中的元素
由HashSet类实现的Set集合中的对象必须是惟一的,因此需要添加到由HashSet类实现的Set集合中的对象,需要重新实现equals()方法,从而保证插入集合中对象的标识的惟一性
由HashSet类实现的Set集合的排列方式为按照哈希码排序,根据对象的哈希码确定对象的存储位置,因此需要添加到由HashSet类实现的Set集合中的对象,还需要重新实现hashCode()方法,从而保证插入集合中的对象能够合理地分布在集合中,以便于快速定位集合中的对象。
由于Set集合中的对象是无序的,这里所谓的无序并不是完全无序,只是不像List集合按对象的插入顺序保存对象,无序性!= 随机性。真正的无序性,指的是元素在底层存储的位置是无序的
例如:
源文件:Person.Java

public class Person{  
    private String name;  
    private long id_card;  
    public Person(String name,long id_card){  
        this.name = name;  
        this.id_card = id_card;  
    }  
    public long getId_card(){  
        return id_card;  
    }  
    public void setId_card(long id_card){  
        this.id_card = id_card;  
    }  
    public String getName(){  
        return name;  
    }  
    public void setName(String name){  
        this.name = name;  
    }  
    public int hashCode(){//重新实现hashCode()方法  
        final int PRIME = 31;  
        int result = 1;  
        result = PRIME*result+(int)(id_card^(id_card>>>32));  
        result = PRIME*result+((name ==null)?0:name.hashCode());  
        return result;  
    }  
    public boolean equals(Object obj){//重新实现equals()方法  
        if(this == obj){  
            return true;  
        }  
        if(obj == null){  
            return false;  
        }  
        if(getClass()!=obj.getClass()){  
            return false;  
        }  
        final Person other = (Person)obj;  
        if(id_card!=other.id_card){  
            return false;  
        }  
        if(name == null){  
            if(other.name != null){  
                return false;  
            }  
        }  
        else if(!name.equals(other.name)){  
            return false;  
        }  
        return true;  
    }  
}

源文件:TestSet.java

import java.util.*;  
public class TestSet{  
    public static void main(String args[]){  
        Set<Person> hashSet = new HashSet<Person>();  
        hashSet.add(new Person("马先生",22015));  
        hashSet.add(new Person("李×××",22018));  
        hashSet.add(new Person("李先生",22020));  
        Iterator<Person> it = hashSet.iterator();  
        while(it.hasNext()){  
            Person person = it.next();  
            System.out.println(person.getName()+"   "+person.getId_card());  
        }  
    }  
}

程序的运行结果如下:
李×××  22018
李先生  22020
马先生  22015

如果既想保留HashSet类快速定位集合中对象的优点,又想让集合中的对象按插入的顺序保存,可以通过HashSet类的子类LinkedHashSet实现Set集合,即修改上述代码如下:

将Set<Person> hashSet = new HashSet<Person>(); 修改为:Set<Person> hashSet = new LinkedHashSet<Person>();

 (2)使用TreeSet类
TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,从而保证在遍历集合时按照递增的顺序获得对象。遍历对象时可能是按照自然顺序递增排列,因此存入用TreeSet类实现的Set集合的对象必须实现Comparable接口;也可能是按照指定比较器递增排序,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序。
TreeSet类通过实现java.util.SortedSet接口增加的方法如下表4所示:


例如:
源文件:Person.java

public class Person implements Comparable{  
    private String name;  
    private long id_card;  
    public Person(String name,long id_card){  
        this.name = name;  
        this.id_card = id_card;  
    }  
    public String getName(){  
        return name;  
    }  
    public void setName(String name){  
        this.name = name;  
    }  
    public long getId_card(){  
        return id_card;  
    }  
    public void setId_card(long id_card){  
        this.id_card = id_card;  
    }  
    public int compareTo(Object o){//默认按编号升序排序  
        Person person = (Person)o;  
        int result = id_card>person.id_card?1:(id_card==person.id_card?0:-1);  
        return result;  
    }  
}

源文件:TestSet.java

import java.util.*;  
public class TestSet{  
    public static void main(String args[]){  
        TreeSet<Person> treeSet = new TreeSet<Person>();  
        Person p1 = new Person("马先生",22015);  
        Person p2 = new Person("李先生",22016);  
        Person p3 = new Person("王×××",22018);  
        Person p4 = new Person("尹先生",22020);  
        Person p5 = new Person("王先生",22012);  
        treeSet.add(p1);  
        treeSet.add(p2);  
        treeSet.add(p3);  
        treeSet.add(p4);  
        treeSet.add(p5);  
        System.out.println("初始化的集合:");  
        Iterator<Person> it = treeSet.iterator();  
        while(it.hasNext()){  
            Person p = it.next();  
            System.out.println(p.getId_card()+" "+p.getName());  
        }  
        System.out.println("截取前面部分得到的集合:");  
        it = treeSet.headSet(p1).iterator();  
        while(it.hasNext()){  
            Person p = it.next();  
            System.out.println(p.getId_card()+" "+p.getName());  
        }  
        System.out.println("截取中间部分得到的集合:");  
        it = treeSet.subSet(p1,p3).iterator();  
        while(it.hasNext()){  
            Person p = it.next();  
            System.out.println(p.getId_card()+" "+p.getName());  
        }  
        System.out.println("截取后面部分得到的集合:");  
        it = treeSet.tailSet(p3).iterator();  
        while(it.hasNext()){  
            Person p = it.next();  
            System.out.println(p.getId_card()+" "+p.getName());  
        }  
    }  
}

程序的运行结果如下:
初始化的集合:
22012   王先生
22015   马先生
22016   李先生
22018   王×××
22020   尹先生
截取前面部分得到的集合:
22012   王先生
截取中间部分得到的集合:
22015   马先生
22016   李先生
截取后面部分得到的集合:
22018   王×××
22020   尹先生

在使用由TreeSet类实现的Set集合时,也可以通过单独的比较器对集合中的对象进行排序。
例如:
比较器既可以作为一个单独的类,也可以作为对应类的内部类,本例中移内部类的形式实现比较器。
源文件:Person.java

import java.util.Comparator;  
public class Person implements Comparable{  
    private String name;  
    private long id_card;  
    public Person(String name,long id_card){  
        this.name = name;  
        this.id_card = id_card;  
    }  
    public String getName(){  
        return name;  
    }  
    public void setName(String name){  
        this.name = name;  
    }  
    public long getId_card(){  
        return id_card;  
    }  
    public void setId_card(long id_card){  
        this.id_card = id_card;  
    }  
    public int compareTo(Object o){//默认按编号升序排序  
        Person person = (Person)o;  
        int result = id_card>person.id_card?1:(id_card==person.id_card?0:-1);  
        return result;  
    }  
    static class PersonComparator implements Comparator{  
        public static final int NAME = 1;  
        public static final int ID_CARD = 2;  
        private int orderByColumn = 1;//默认为按姓名排序  
        public static final boolean ASC = true;  
        public static final boolean DESC = false;  
        private boolean orderByMode = true;//默认为按升序排序  
        public int compare(Object o1,Object o2){//实现Comparator接口的方法  
            Person p1 = (Person)o1;  
            Person p2 = (Person)o2;  
            int result = 0;//默认的判断结果为两个对象相等  
            switch(orderByColumn){//判断排序条件  
                case 1:  
                    String s1 = CnToSpell.getFullSpell(p1.getName());  
                    String s2 = CnToSpell.getFullSpell(p2.getName());   
                    if(orderByMode){//升序  
                        result = s1.compareTo(s2);  
                    }  
                    else{//降序  
                        result = s2.compareTo(s1);  
                    }  
                    break;  
                case 2:  
                    if(orderByMode){//升序  
                        result = (int)(p1.getId_card()-p2.getId_card());  
                    }  
                    else{//降序  
                        result = (int)(p2.getId_card()-p1.getId_card());  
                    }  
                    break;  
            }  
            return result;  
        }  
        public void orderByColumn(int orderByColumn){//用来设置排序条件  
            this.orderByColumn = orderByColumn;  
        }  
        public void orderByMode(boolean orderByMode){//用来设置排序方式  
            this.orderByMode = orderByMode;  
        }  
    }  
}

源文件:TestSet.java

import java.util.*;  
public class TestSet{  
    public static void main(String args[]){  
        TreeSet<Person> treeSet1 = new TreeSet<Person>();  
        Person p1 = new Person("马先生",22015);  
        Person p2 = new Person("李先生",22016);  
        Person p3 = new Person("王×××",22018);  
        treeSet1.add(p1);  
        treeSet1.add(p2);  
        treeSet1.add(p3);  
        System.out.println("客户化排序前,默认按编号升序排序:");  
        //新创建一个Set集合,不进行客户化排序,默认按编号升序排序  
        TreeSet<Person> treeSet2 = new TreeSet<Person>(treeSet1);//通过构造函数初始化集合  
        Iterator<Person> it1 = treeSet2.iterator();  
        while(it1.hasNext()){  
            Person p = it1.next();  
            System.out.println(p.getId_card()+" "+p.getName());  
        }  
        System.out.println("客户化排序后,按编号降序排序:");  
        //新创建一个Set集合,进行客户化排序,客户化排序方式为按编号降序排序  
        Person.PersonComparator pc = new Person.PersonComparator();//创建比较器(内部类)的实例  
        pc.orderByColumn(Person.PersonComparator.ID_CARD);//设置排序依据的属性  
        pc.orderByMode(Person.PersonComparator.DESC);//设置排序方式  
        TreeSet<Person> treeSet3 = new TreeSet<Person>(pc);//必须通过构造函数设置比较器  
        treeSet3.addAll(treeSet1);//初始化集合  
        Iterator<Person> it2 = treeSet3.iterator();  
        while(it2.hasNext()){  
            Person p = it2.next();  
            System.out.println(p.getId_card()+" "+p.getName());  
        }  
    }  
}

程序的运行结果如下:
客户化排序前,默认按编号升序排序:
22015   马先生
22016   李先生
22018   王×××
客户化排序后,按编号降序排序:
22018   王×××
22016   李先生
22015   马先生