Java基础(二十二)集合(4)Set集合

  Set集合为集类型。集是最简单的一种集合,存放于集中的对象不按特定方式排序,只是简单地把对象加入集合中。对集中存放的对象的访问和操作时通过对象的引用进行的,所以,在集中不能存放重复对象。

  Set接口实现了Collection接口,从而拥有Collection接口提供的所有常用方法。

  实现了Set接口的类有三种,分别是HashSet类(子类为LinkedHashSet类)、EnumSet类和TreeSet类。  

  1.HashSet类

  由HashSet类实现的Set集合的优点是能够快速定位集合中的元素。

  Set集合中的对象是无序的,遍历集合输出对象的顺序与向集合中插入对象的顺序并不相同。

  由HashSet类实现的Set集合中的对象必须是唯一的,所以,添加到由HashSet类实现的Set集合中的对象,需要重新实现equals()方法,从而保证插入集合中的对象的标识的唯一性。(Eclipse代码编辑区,右键-Source-Generate hashCode() and equals()...)

  由HashSet类实现的Set集合按照哈希码排序,根据对象的哈希码确定对象的存储位置,所以,添加到由HashSet类实现的Set集合中的对象,还需要重新实现hashCode()方法,从而保证插入集合中的对象能够合理地分布在集合中,以便于快速定位集合中的对象。(Eclipse代码编辑区,右键-Source-Generate hashCode() and equals()...)

  创建一个HashSet类的对象(Person类实现了hashCode()和equals()方法):

Set<Person> hashSet = new HashSet<>();

  由于LinkedHashSet类是HashSet类的子类,如果既想保留HashSet类快速定位集合中对象的优点,又想让集合中的对象按插入的顺序保存,可以通过LinkedHashSet类来实现Set集合。

Set<Person> hashSet = new LinkedHashSet<>();

  使用HashSet和LinkedHashSet实现Set集合的代码示例:

package hashSet.jun.iplab;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

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 String getName() {
        return name;
    }

    public long getId_card() {
        return id_card;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        /*由于最后的hashCode的类型是int,  而int只有32位,所以64位的Long值,
         * 要砍掉一半。为了不失去一半的信息,这个expression的意思是,
         * 会值的高32位和低32位的值进行exclusive OR的结果,
         * 这样就保证结果均会受前后32位的影响,不会丢失信息。
         * 如果直接把Long转成int, 那就会丢掉高32位的信息。
         * */
        result = prime * result + (int) (id_card ^ (id_card >>> 32));
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        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;
    }
    
    public static void main(String[] args) {
        
        Set<Person> hashSet = new HashSet<>();
        hashSet.add(new Person("小红", 13211041));
        hashSet.add(new Person("小黄", 13211241));
        hashSet.add(new Person("小蓝", 13213231));
        
        Iterator<Person> it_Person = hashSet.iterator();
        while (it_Person.hasNext()) {
            Person person = (Person) it_Person.next();
            System.out.println(person.getName() + " " + person.getId_card());
        }
        System.out.println();
        
        Set<Person> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add(new Person("小红", 13211041));
        linkedHashSet.add(new Person("小黄", 13211241));
        linkedHashSet.add(new Person("小蓝", 13213231));
        
        Iterator<Person> it_LinkedHashSet_Person = linkedHashSet.iterator();
        while (it_LinkedHashSet_Person.hasNext()) {
            Person person = (Person) it_LinkedHashSet_Person.next();
            System.out.println(person.getName() + " " + person.getId_card());
        }
    }
    
}

输出:
小蓝 13213231
小红 13211041
小黄 13211241

小红 13211041
小黄 13211241
小蓝 13213231
View Code

 

  2.TreeSet类  

  TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,从而保证在遍历集合时按照递增的顺序获得对象。

  遍历对象时可能是按照自然顺序递增排列,所以,存入由TreeSet类实现的集合的对象必须实现Comparable接口;也可能是按照指定比较器递增排列,即可以通过比较器对由TreeSet类实现的Set集合中的对象进行排序。

  创建一个TreeSet类的对象为(其中Person实现了Comparable接口,因此必须实现compareTo方法):

TreeSet<Person> treeSet = new TreeSet<>();

  TreeSet类由于实现了java.util.SortedSet接口而增加的一些常用方法:

  

  示例代码:

  • Person类中重写compareTo方法,按照id_card属性的大小进行访问排序,id_card大的返回1,相等返回0,小于返回-1
    // 重写compareTo方法,按照id_card的大小进行比较,如果大的返回1,等于返回0,小于返回-1
    @Override
    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;
    }
View Code
  • 首先创建五个Person对象并添加到TreeSet集合中
        Person person1 = new Person("小一", 13211123);
        Person person2 = new Person("小二", 13223131);
        Person person3 = new Person("小三", 13232412);
        Person person4 = new Person("小四", 13521312);
        Person person5 = new Person("小五", 13231231);
        
        TreeSet<Person> treeSet = new TreeSet<>();
        treeSet.add(person1);
        treeSet.add(person2);
        treeSet.add(person3);
        treeSet.add(person4);
        treeSet.add(person5);
View Code
  • 迭代器访问时,将通过id_card的大小按照从小到大访问
        Iterator<Person> it = treeSet.iterator();
        while (it.hasNext()) {
            Person person = (Person) it.next();
            System.out.println(person.getName() + " " + person.getId_card());
        }

输出:
小一 13211123
小二 13223131
小五 13231231
小三 13232412
小四 13521312
View Code
  • 通过headSet方法得到“小五”(不包括)前面部分的集合
        it = treeSet.headSet(person5).iterator();
        while (it.hasNext()) {
            Person person = (Person) it.next();
            System.out.println(person.getName() + " " + person.getId_card());
        }

输出:
小一 13211123
小二 13223131
View Code
  • 通过subSet方法得到“小二”(包括)到“小四”(不包括)部分的集合
        it = treeSet.subSet(person2, person4).iterator();
        while (it.hasNext()) {
            Person person = (Person) it.next();
            System.out.println(person.getName() + " " + person.getId_card());
        }

输出:
小二 13223131
小五 13231231
小三 13232412
View Code
  • 通过tailSet方法得到“小三”(包括)后面部分的集合
        it = treeSet.tailSet(person3).iterator();
        while (it.hasNext()) {
            Person person = (Person) it.next();
            System.out.println(person.getName() + " " + person.getId_card());
        }

输出:
小三 13232412
小四 13521312
View Code

 

  二、Queue集合

  Queue是Collection接口的最后一个子接口。

  队列只允许在队尾

posted @ 2018-08-02 17:01  BigJunOba  阅读(312)  评论(0编辑  收藏  举报