1.Set集合类似于一个罐子,集合中的多个对象之间没有明显的顺序,其方法几乎和Collection基本上完全一样,但集合中不允许包含重复的元素。
2.Set集合判断两个元素是否相同的方法是使用equals方法,而非==。
3.HashSet类
HashSet是按照Hash算法来存储集合中的元素,其特点:
1)是不能保证元素的排列顺序
2)Hash不是同步的,如果多个线程同时访问一个HashSet,则必须通过代码来保证其同步。
3)集合中的元素值可以是null。
4)判断过程:
当向HashSet中添加一个元素时,HashSet会调用该对象的hashCode()方法得到其hashCode值,然后根据该值决定该对象的存储位置,但是如果有两个元素通过equals()方法比较返回true,而它们的hashCode()方法返回值不等,HashSet也会将它们存储在不同的位置。
5)重写方法:
一般在重写hashCOde()时,也要对应的重写equals()方法,且当equals()方法返回true时,这两个对象的hashCode()方法应返回相同的值。
4.LinkedHashSet类
该类为HashSet的子类,也是根据元素的hashCode()值来决定其存储位置,但是通过链表来维护元素的次序(存储)。
5.TreeSet类
该类为SortedSet接口的实现类,其采用红黑树的数据结构来存储集合中的元素,即其中的元素时有序的。
1)自然排序+定制排序
前提:试图把一个对象添加到TreeSet时,该对象的类必须实现Comparable接口(comparTo(Object obj)方法),否则程序将抛出异常。
并通过compareTo(Object obj)方法与容器中的其它对象比较大小,如果比较返回0,则二者相等,否则,不等。
注意:当重写对象对应类的equals和compareTo()方法时,应保证二者一致。即前者返回true时,后者返回0.
且当添加一个可变对象后,并且修改了可变对象的Field,有可能导致它与其它对象的大小顺序发生了变化,但TreeSet不会调整他们的顺序,甚至有可能出现 compareTo()的返回结果为0。一般向这两个集合中放入不可变对象。
定制排序举例:
import java.util.*;
class M
{
int age;
public M(int age)
{
this.age=age;
}
public String toString()
{
return "M对象(age:"+age+")";
}
}
class TestTreeSet3
{
public static void main(String[] args)
{
TreeSet ts=new TreeSet(new Comparator()
{
public int compare(Object o1,Object o2)
{
M m1=(M)o1;
M m2=(M)o2;
return m1.age<m2.age?-1:m1.age>m2.age?1:0;//从小到大排序
}
});
ts.add(new M(5));
ts.add(new M(9));
System.out.println(ts);
}
}
6.EnumSet类
该类是一个专门为枚举类设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显示或隐式指定,且 不允许加入null元素。
举例如下:
import java.util.*;
enum Season
{
SPRING,SUMMER,FALL,WINTER
}
class EnumSetTest
{
public static void main(String[] args)
{
//创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值
EnumSet es1=EnumSet.allOf(Season.class);
System.out.println(es1);
//创建一个EnumSet空集合,制定其集合类型为Season类的枚举值
EnumSet es2=EnumSet.noneOf(Season.class);
System.out.println(es2);
es2.add(Season.WINTER);
es2.add(Season.SPRING);
System.out.println(es2);
//指定枚举值创建EnumSet集合
EnumSet es3=EnumSet.of(Season.SUMMER,Season.WINTER);
System.out.println(es3);
EnumSet es4=EnumSet.range(Season.SUMMER,Season.WINTER);
System.out.println(es4);
//es5+es4=全部的枚举值
EnumSet es5=EnumSet.complementOf(es4);
System.out.println(es5);
//使用集合来创建EnumSet集合,要求集合中的元素为同类型的枚举值
Collection c=new HashSet();
c.clear();
c.add(Season.FALL);
c.add(Season.SPRING);
EnumSet ens=EnumSet.copyOf(c);
System.out.println(ens);
}
}
只有当需要一个保持排序的Set时,使用TreeSet,否则使用HashSet.
而对于普通的插入和删除操作LinkedHashSet比HashSet要慢一点,但是遍历LinkedHashSet会更快。
EnumSet是所有Set实现类中性能最好的,但它只能保存同一枚举类型的枚举值。
但这三者都是线程不安全的,有多线程时修改Set集合时,则必须手动保证Set集合的同步性。一般使用Collection的synchronizedSortedSet方法来包装Set集合。
如:SortedSet s=Collection.synchronizedSortedSet(new TreeSet(...))。