概述:
1.Set不允许重复数据,判断重复标准:equals方法
2.HashSet
1.无序(序号的序),允许存在null
2.hashCode值决定它在HashSet中的位置,通过hashCode值算出存储位置
3.判断重复标准:equals方法 和 hashCode方法 同时相等
a.如果equals相同,hashCode不同,两个相同值的对象存在不同的位置(原因见第二点)
b.如果hashCode相同,equals不同,采用链式结构将2个对象存在同一位置(桶的概念,bucket),这会导致性能下降
4.两个概念初始容量 和 加载因子(hashSet尚未爆仓(只需达到初始容量*加载因子,即16*0.75),系统会动态扩大容量)
5.没有实现线程同步 如果需要同步操作(多线程安全)请使用
Set s = Collections.synchronizedSet(new HashSet(...));
6.迭代过程中必须使用迭代器自身的remove方法删除数据,否则会出异常
3.LinkedHashSet
1.他是HashSet子类。
2.它以链表的方式维护元素的次序,所以它会按照添加顺序访问集合中的对象。
3.顺序遍历的时候性能比HashSet好,但是其他涉及到元素位置变化的操作性能就不如HashSet了。(数据结构知识)
4.虽然它有一定的访问顺序,但是它和List还是有区别的,最明显的一点:它仍然不能有重复对象。
4.TreeSet
1.SortedSet接口的实现类,它保持了排序状态。
2.方法:第一个、前一个、后一个、最后一个、范围截取、小于某元素、大于或者等于某元素
3.采用红黑树的数据结构来存储数据
4.支持2种排序方式:自然排序 和 定制排序
1.自然排序
a.调用Comparable接口的compareTo方法进行比较
由于需要排序,进入TreeSet的对象需要是同一个类的实例,否则在比较的时候会出现类转化异常。
2.定制排序
实现Comparator接口(见例子)
5.如果碰到不能排序的对象加入到TreeSet中 会出现异常(见例子)
5.EnumSet
1.性能相对不错的 枚举Set
2.不多讲,有兴趣可以看看api
6.HashSet、TreeSet、EnumSet都是线程不安全的
PS:
1.Set不仅仅如此,这里只做基本的阐述,更加详细的请参见 JAVA API
2.初学者挑能看懂的看吧,基础的操作其实还是比较简单的
package com.cxy.collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
/**
* @author cxy
*/
public class SetTest
{
public static void main(String[] args)
{
Set s = new HashSet();
s.add(null);
s.add(new A());
s.add(new A());
//由于2个A对象的hashCode返回的都是1,并且equals方法返回的是true,所以这两个对象只能存在1个
s.add(new B());
s.add(new B());
//B对象的equals方法返回的永远是false,所以这两个B对象都能留下
s.add(new C());
s.add(new C());
//2个C对象hashCode返回的都是2,并且equals方法返回的是true,并且hashCode没有和以往对象相等的,所以留住1个C对象
System.out.println(s); //通过打印结果可以看出 HashSet无序性。
LinkedHashSet<String> lhs = new LinkedHashSet<String>();
lhs.add("world");
lhs.add("said");
lhs.add("hello");
System.out.println(lhs); //按照加入顺序打印
TreeSet ts=new TreeSet();
ts.add(100);
ts.add(64);
ts.add(-100);
ts.add(0);
System.out.println(ts); //发现打印出来的已然是有序状态
System.out.println("第一个:"+ts.first());
System.out.println("最后一个:"+ts.last());
System.out.println("小于64的最大元素(64前面的):"+ts.lower(64));
System.out.println("大于0的最小元素(0后面的):"+ts.higher(0));
System.out.println("0~100之间的:"+ts.subSet(0, 100)); //半闭半开区间
System.out.println("小于64的集合"+ts.headSet(64));
System.out.println("大于或者等于0的集合"+ts.tailSet(0));
try
{
TreeSet errorSet=new TreeSet();
errorSet.add(new error());
errorSet.add(new error());
}catch(Exception e)
{
System.out.println("由于error类没有实现Comparable接口的compareTo方法,所以这里出现类型转换的异常");
}
try
{
TreeSet errorSet1=new TreeSet();
errorSet1.add(123);
errorSet1.add("asd");
}catch(Exception e)
{
System.out.println("不同类实例的比较 会出类转换异常");
}
//一个定制排序的set
TreeSet myStyleSet=new TreeSet(new Comparator()
{
@Override
public int compare(Object o1, Object o2)
{
return 0; //一个永远平等的集合~ 你懂的~
}
});
}
}
class A
{
@Override
public int hashCode()
{
return 1;
}
@Override
public boolean equals(Object obj)
{
return true;
}
}
class B
{
@Override
public int hashCode()
{
return 1;
}
@Override
public boolean equals(Object obj)
{
return false;
}
}
class C
{
@Override
public int hashCode()
{
return 2;
}
@Override
public boolean equals(Object obj)
{
return true;
}
}
//一个没有实现比较的类
class error
{
}
相关文章连接:
声明:
1.原创文章,转载请标明并加本文连接。
2.更详尽的API请参见 http://docs.oracle.com/javase/7/docs/api/
3.文章反映个人愚见,如有异议欢迎讨论指正