set 是 Collection 子接口,模拟了数学上集合的概念
Set 只包含从 Collection 集成的方法,不过 Set 无法记住添加的顺序,不允许包含重复的元素,当视图添加两个相同元素进 Set 集合,添加操作失败,即 add() 方法返回 false。
Set 判断两个对象是否相等用 equals,而不是用 == ,也就是说两个对象 equals 比较返回 true 的情况下,Set 集合是不会接受这两个对象的。
HashSet 是 Set 接口最常用的实现类,顾名思义,底层采用了哈希表(散列/hash)算法,其底层其实也是一个数组,存在的意义是提供查询速度,插入速度也比较快,但是适用于少量数据的插入操作。
在 HashSet 中如何判断两个对象是否相同:
两个对象的 equals 比较相等,返回 true,则说明是相同对象
两个对象的 hashCode 方法返回值相等
ps : 二者缺一不可。
存储在哈希表中的对象,都应该覆盖 equals 方法和 hashCode 方法,并且保证equals 相等的时候,hashCode 也应该相等。
各类型 hashCode 算法
类型 | HashCode 值 |
Boolean | hashCode = (f ? 0 : 1) |
整数类型(byte、short、int、char) | hashCode = (int)f |
long | hashCode = (int)(f ^ (f >>> 32)) |
float | hashCode = Float.floatToIntBits(f) |
double | long l = Double.doubleToLongBits(f) hashCode = (int)(l ^ (l >>> 32)) |
普通引用类型 | hashCode = f.hashCode() |
TreeSet 集合是底层采用红黑树(R-B Tree)算法,会对存储的元素默认使用自然排序(从小到大)。
注:必须保证 TreeSet 集合中的元素对象是相同的数组类型,否则报错。
TreeSet的排序规则:
自然排序:TreeSet 调用集合元素的 compareTo 方法来比较元素的大小关系,然后将集合元素按照升序排列,要求 TreeSet 集合中元素得实现 java.util.Comparable 接口。
定制排序:在 TreeSet 构造器传递 java.lang.Comparator 对象,并覆盖 public int compare(Object o1,Object o2),再编写比较规则。
TreeSet 调用集合元素的 compareTo 方法来比较元素的大小关系,然后将集合元素按照升序排序(从小到大)
注:要求 TreeSet 集合中元素得实现 java.util.Comparable 接口。
BigDecinal,BigInteger,Byte,Double,Float,Integet,Long,Short:按数字大小排序。
Character 按字符的 Unicode 值的数字大小排序
String 按字符中字符的 Unicode 值排序
java.util.Comparable 接口 — >> 比较接口
覆盖 public int compareTo(Object o); 方法,在该方法中编写比较规则。
在该方法中,比较当前对象(this)和参数对象 o 做比较(严格上说比较的是对象中的数据):
this>0;返回正整数:1
this<0;返回负整数:-1
this==0;返回0,此时认为两个对象为同一个对象。
在 TreeSet 的自然排序中,认为如果两个对象做比较的 compareTo 方法返回的是 0,则以为是同一个对象。
定制排序:(从大到校,按照字符串长短等)
对于 TreeSet 集合而言,要么使用自然排序,要么使用定制排序。
Set接口的实现类
共同的特点:
都不允许元素重复。
都不是线程安全的类。
解决方案:Set s = Collections.synchronizedSet(Set 对象)
HashSet :
不保证元素的先后添加顺序,底层采用的是哈希表算法,查询效率较高。
判断两个对象是否相等的规则:
equals比较为true
hashCode值相同
要求:存在在哈希表中的对象元素都得覆盖 equals 和 hashCode 方法
LinkedHashSet :
HashSet 的子类,底层也采用的是哈希表算法,但是也使用了链表算法来维持元素的先后添加顺序,判断两个对象是否相等的规则和 HashSet 相同。因为需要多使用一个链表来记录元素的顺序,所以性能相对于 HashSet 较低,一般少用,如果要求一个集合既要包子元素不重复,又需要记录添加先后顺序,才选择使用 LinkedHashSet。
TreeSet :
不保证元素的先后添加顺序,但是会对集合中的元素做排序操作。底层采用红黑树算法(树结构,比较擅长做范围查询)。
TreeSet 要么采用自然排序,要么定制排序。
自然排序:要求在 TreeSet 集合中的对象必须实现 java.lang.Comparable 接口,并覆盖 compareTo 方法。
定制排序:要求在构建 TreeSet 对象的时候,传入一个比较器对象(必须实现 java.lang.Comparator接口)在比较器中覆盖 compare 方法,并编写比较规则。
HashSet 做等值查询效率高,TreeSet 做范围查询效率高。
而更多的情况,都是做等值查询,在数据库的索引中做范围查询较多,所以树结构主要用于做索引,用来提高查询效率。