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
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; }
- 首先创建五个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);
- 迭代器访问时,将通过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
- 通过headSet方法得到“小五”(不包括)前面部分的集合
it = treeSet.headSet(person5).iterator(); while (it.hasNext()) { Person person = (Person) it.next(); System.out.println(person.getName() + " " + person.getId_card()); } 输出: 小一 13211123 小二 13223131
- 通过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
- 通过tailSet方法得到“小三”(包括)后面部分的集合
it = treeSet.tailSet(person3).iterator(); while (it.hasNext()) { Person person = (Person) it.next(); System.out.println(person.getName() + " " + person.getId_card()); } 输出: 小三 13232412 小四 13521312
二、Queue集合
Queue是Collection接口的最后一个子接口。
队列只允许在队尾