<一>HashSet类
HashSet按照Hash算法来存储集合中的元素,因此有很好的存取和查找性能
HashSet具有以下特点
1.不能保证元素的排列顺序,顺序可能与添加顺序不同
2.集合元素可以是null值
3.HashSet不是同步的,如果多线程同时访问一个 HashSet,假设有两个或者两个以上线程同修改了HashSet集合时,则必须通过代码来保证其同步
向HashSet存入一个对象时,它会调用该对象的hashCode()来得到该对象的hashCode值,然后根据hashCode值来确定该对象在HashSet中存储的位置,如果有两个元素通过equals()方法比较后返回true,但是这两个对象的hashCode值不同,HashSet依然把他们存储在不同的位置,添加成功
一句话说就是HashSet判断两个对象是否相等是通过equals()方法返回true,并且两个对象hashCode值相等
LinkedHashSet类
LinkedHashSet类是HashSet类的子类,它也是根据元素的hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序,当遍历LinkedHashSet集合里的元素时,LinkHashSet将会按元素的添加顺序来访问集合里的元素,输出LinkHashSet集合的元素时,元素的顺序总是与添加顺序一致
<二>TreeSet类
TreeSet可以确保集合元素处于排序状态,与HashSet集合采用hash算法来决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储集合元素
TreeSet类还额外提供几个方法
Object first(); //返回集合的第一个元素
Object last(); //返回集合的最后一个元素
Object lower(Object e);// 返回位于指定元素之前的元素
Object higher(Object d);//返回位于指定元素之后的元素
SortedSet subSet(ObjectfromElement,ObjecttoElement);返回此set的子集合,范围从fromElement到toElement
SortedSet headSet(Object toElement);返回此set的子集合,由小于toElement的元素组成
SortedSet tailSet(Object fromElement);返回此set的子集合,由大于或者等于fromElement的元素组成
当向TreeSet添加集合时,TreeSet会调用该对象的compareTo(Object obj)方法与集合中的其它元素进行比较,所以这需要集合中的其它元素必须与该元素时同一个对象的实例。所以TreeSet比较两个对象是否是同一个对象的标准是:通过compareTo()方法比较是否返回0,如果返回0,TreeSet会认为这两个对象相同,否则不相同。
如果是程序员自定义的类还需要实现Comparable接口
class R implements Comparable
{
int count;
public R(int count)
{
this.count=count;
}
public String toString()
{
return "R[count:"+count+"]";
}
public boolean equals(Object obj)
{
if(this==obj)
{
return true;
}
if(obj!=null&&obj.getClass()==R.class)
{
R r=(R)obj;
if(r.count==this.count)
{
return true;
}
}
return false;
}
public int compareTo(Object obj)
{
R r=(R)obj;
return count>r.count?1:
count<r.count?-1:0;
}
}
public class TreeSet
{
public static void main(String[] args)
{
TreeSet ts=new TreeSet();
ts.add(new R(5));
ts.add(new R(-3));
ts.add(new R(9));
ts.add(new R(-2));
System.out.println(ts);
System.out.println(ts.remove(new R(-2))); //删除field被改变的值,删除失败
System.out.println(ts);
System.out.println(ts.remove(new R(5))); //删除field没被改变的值,删除成功
System.out.println(ts);
}
}
class R是一个可变类,因此可以改变R对象的count实例变量的值,一旦改变了TreeSet集合里可变元素的field,当试图删除该对象时,TreeSet也会删除失败(甚至集合中原有的,field没被修改但与修改后元素相等的元素也无法删除)
<三>EnumSet类
EnumSet类是一个专门为枚举类设计的集合类
import java.util.EnumSet;
enum Season
{
SPRING,SUMMER,FALL,WINTER
}
public class EnumSetTest
{
public static void main(String[] args)
{
EnumSet es1=EnumSet.allOf(Season.class);
System.out.println(es1);
EnumSet es2=EnumSet.noneOf(Season.class);
System.out.println(es2);
es2.add(Season.WINTER);
es2.add(Season.SPRING);
System.out.println(es2);
EnumSet es3=EnumSet.of(Season.SUMMER,Season.WINTER);
System.out.print(es3);
EnumSet es4=EnumSet.range(Season.SUMMER,Season.WINTER);
System.out.println(es4);
EnumSet es5=EnumSet.complementOf(es4);
System.out.println(es5);
}
}
各Set类的性能分析
HashSet类的性能比TreeSet类的性能好,特别体现在添加,查询元素等操作。对于普通的插入,删除操作,linkedHashSet比HashSet要略慢一点,这是由维护链表所带来的额外开销造成的,不过,因为有了链表,遍历LinkedHashSet会更快。如果需要一个排序的Set时,才该使用TreeSet。EnumSet类是性能最好的