Set集合类:
似于一个罐子,Set集合通常不能记住元素的添加顺序,并且Set不允许包含重复元素,如果使用add方法对set集合进行添加重复元素,返回值为false,添加失败。
HashSet类:
HashSet是Set接口的典型实现,它具有以下特点。
1)不能保证元素排列顺序,顺序可能与添加顺序不同,顺序可能会发生变化。
2)HashSet是不能够同步的,如果多个线程同时访问HashSet,必须要加同步代码块进行访问。
3)集合的元素允许为空。
当我们向HashSet集合存放一个元素时,HashSet会调用该对象的HashCode()来得到HashCode的值,再通过哈希算法,得到该对象确定在哪个HashSet存放位置,调用equals方法判断是否重复,当返回值结果为true,但是HashCode码不相等的时候,也可以存入HashSet。
也就是说HashSet集合判断两个元素是否相等的标准时通过equals方法进行比较,并且两个对象的HashCode值也相等,才认为是相同的。
LinkedHashSet类:
LinkedHashSet集合也是根据元素的hashCode的值决定元素的存储位置,但是它同时使用链表维护元素的次序,这样可以让元素看起来是以插入的顺序来进行保存的,也就是说遍历LinkedHashSet时。LinkedHashSet会按照元素的添加顺序来访问集合中的元素,虽然LinkedHashSet是使用链表记录元素的添加顺序的,但是LinkedHashSet还是HashSet,因此它依然不允许集合元素重复。
TreeSet类:
TreeSet会按照元素的大小进行排序,并不会按照插入顺序排序,并且TreeSet是采用了红黑树的数据结构来存储集合元素。treeSet采取了两种排序方式来对元素进行排序:
1:自然元素
TreeSet会调用集合元素的comparaTo的方法来进行比较元素之间大小的关系,将元素进行升序排列。
Java提供了一个Comparable接口,这个接口定义了一个CompareTo的方法,这个方法返回了一个整数值,实现该接口类必须实现该方法,就可以比较对象的大小,如果返回值为正数时,说比前者要比比较的内容大,如果返回值为0,则说明两个内容相等
,如果返回值为-1的时候,就说明调用compareTo的对象要比括号中待比较的数字小。
Java中一些常用类已经实现了Comparable接口,提供了比较大小的标准,以下是实现了comparable的类:
BigDecimal等所有数值型对应的包装类
Boolean:true对应的包装类大于false对应的包装类实例。
String:按照字符串的UNICODE值进行比较
Date,Time后面的时间比前面的时间大
**如果把一个对象添加到TreeSet时,则该对象必须实现Comparable接口,否则程序就会抛出异常。
还有一点需要注意的是:大部分类在实现compareTo方法,都需要将比较对象obj强制类型转换成相同的类型,因为只有两个相同类的实例才会比较大小,当我们把一个元素添加到TreeSet中,会调用该对象的CompareTo方法与其他元素进行一一对比,这就要求了添加的元素与treeSet中的元素是同一个实例,否则也会发生异常。这就是说TreeSet中元素必须要是同一种类型的对象。
如何选用HashSet还是TreeSet类呢?
HashSet的性能总是比TreeSet好,特别是添加和查询元素的操作,因为TreeSet需要额外的红黑树算法来维持集合元素的次序,只有当需要一个保持排序二的Set时,我们才应该选用TreeSet,否则都应该选用HashSet。
HashSet还有个子类叫做LinkedHashSet,对于普通的插入操作时LinkdeHashSet要比HashSet慢一点,这是因为需要维护链表所带来的额外的开销,但是有了链表,遍历LinkedHashSet会更加的快一点。