Set集合是Collection集合的子类,与Collection基本上完全一样,它没有提供额外的方法,只是在行为上略有不同。
Set集合不允许包含相同的元素,如果把两个相同的元素加入到同一个Set集合中去,则添加操作失败,add方法返回false,且新元素不会被加入。
Set判断两个对象相同不是使用==运算符,而是使用equals方法。也就是说,只要两个对象equals方法比较返回true,Set就不会接受这两个对象;反之,则可以。
1. HashSet
HashSet是Set接口的典型实现,大多数时候使用Set集合时就是使用这个实现类。HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。
HashSet具有以下特点:
- 不能保证元素的排列顺序,排列顺序可能与添加顺序不同。
- HashSet不是同步的,如果多个线程同时访问一个HashSet时,假设有一个或多个线程同时修改了HashSet集合时,则必须通过代码块来保证其同步。
- 集合元素可以是null。
- 当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的值,然后根据该HashCode()值决定该对象在HashSet中的存储位置。如果两个元素通过equals()方法比较返回true,而他们的hashCode()方法返回值不同,HashSet会将他们存储在不同的位置,依然添加成功。这就与Set集合的规则有些出入了。
- 注意:如果通过equals方法比较返回true,同时根据hashCode()方法获取的返回值也相同,则只能存储一个对象。
当把一个对象放入到HashSet中时,如果重写了这个对象的equals方法,那么也必须重写这个对象的hashCode方法。其规则就是如果equals方法返回true,那么这两个对象的hashCode的值也应该相同。
如果两个对象通过equals方法比较返回false,而hashCode值返回一样,这就有点违背了HashSet的设计规则,本来通过Hash算法我们可以计算对象的存储位置,现在却成了在同一个位置上存储了两个对象。从而减低了HashSet快速查找对象的功能。
2. TreeSet
TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。与HashSet相比,TreeSet还提供了额外方法:
HashSet集合采用hash算法来决定元素的存储位置,TreeSet采用红黑树的数据结构来存储集合元素。TreeSet支持两种排序方法:自然排序和定制排序。
- 自然排序
TreeSet会调用集合元素的compareTo(Object obj):方法来比较元素之间的大小关系,然后将集合元素按升序排列,这种方式就是自然排序。
Java中提供了一个Comparable接口,此接口中定义了一个方法compareTo(Object obj),该方法返回一个整数值,实现了该接口的类的对象就可以比较大小。由于在向TreeSet集合中存放数据时,TreeSet会调用该元素对象的compareTo方法,因此往TreeSet集合中存放是元素对象必须实现了该方法。
大部分类在实现compareTo方法时,都需要将被比较对象obj强制转换成相同类型,因为只有相同类型的实例才能比较大小。因此TreeSet集合中存放的元素必须是同一类型的实例。
否则将会抛出ClassCastException(强制类型转换异常) - 定制排序
TreeSet的自然排序是根据集合元素的大小,TreeSet将它们以升序排序。如果实现定制排序,比如降序,需要通过Comparator接口来实现。在创建TreeSet实例的时候,不在使用TreeSet默认的比较,通过Comparator接口实现自己的比较器实例,将比较器的实例作为参数通过TreeSet的构造器传递给集合,那么在往集合元素中存放数据的时候就会按照我们的指定顺序进行排序。实现Comparator接口的int compare(T t1,T t2)方法,此方法在往集合元素中添加元素对象时被调用,该方法返回一个int类型值,返回正整数,表示t1大于t2,返回负整数,表示t1小于t2,返回0表示,t1等于t2.
3. EnumSet
EnumSet类是枚举集合类,集合中存放的元素都必须是指定枚举类型的枚举值,该值在创建EnumSet时显示或隐式地指定。
EnumSet类没有提供公有属性的构造器来创建该类的实例,程序应该通过EnumSet提供是static方法来创建EnumSet对象。常用的方法如下:
- Static EnumSet allOf(Class elementType):创建一个包含了枚举类中所有枚举值的EnumSet集合。
- Static EnumSet complementOf(EnumSet s):创建一个其元素类型与指定的EnumSet里元素类型相同的EnumSet集合,新的EnumSet集合中包含了原EnumSet集合中所不包含的,剩下的所有枚举值。
- Static EnumSet copyOf(Collection c):使用一个普通集合来创建一个EnumSet集合。普通集合Collection参数不能为空,里面必须含有元素对象。否则抛出java.lang.IllegalArgumentException(参数不合理异常)。
- Static EnumSet copyOf(EnumSet s):创建一个与指定的EnumSet具有相同元素类型、相同集合元素的EnumSet集合。完整的copy一份。
- Static EnumSet noneOf(Class elementType):创建一个元素类型为指定枚举类型的空EnumSet。
Static EnumSet range(E from,E to):创建一个包含了从from开始到to结束的范围内所有的枚举值集合。
源代码:
https://github.com/wolf521/demo/tree/master/src/main/java/com/example/demo/collection