集合—— Set
Posted blogforvi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了集合—— Set相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
一、什么是Set?
Set接口是Collection接口的子接口,是一种不允许重复元素的集合。
二、HashSet
- HashSet是Set的一个典型实现类,无序,不可重复,允许加入NULL,大多数时候使用Set就是使用这个类,HashSet按照Hash算法来存储元素,因此具备很好的存取和查找性能。
- 其底层其实是一个数组,存在的意义是加快查询速度,我们知道一般的数组,元素在其中的索引位置都是随机的,元素的取值和位置之间没有关联关系,因此,在数组中查找特定的元素时,只能逐个比较,查找速度取决于比较的次数。但是在HashSet底层的数组中,索引和值之间存在确定的关系:index=hash(value),因此通过这个关系可以快速的找到元素或者索引。
- 当在HashSet中存储元素时,首先调用该对象的hashCode()方法,获取hashCode值,根据这个值,找到对应位置,HashSet中不允许重复,判断方法是:先比较hashCode是否相同,不同就认为是不同对象,相同的话再比较equals方法,根据结果判断。
- 每一个存储到哈希表中的对象,都要提供equals方法和hashCode方法实现,以判断是否是相同对象,对于HashSet,我们应该保证如果两个对象通过equals方法返回true,hashCode值也相同。
三、LinkedHashSet
LinkedHashSet是有序,不允许重复,允许加入NULL的集合。
它也是以HashCode值来决定元素的存储位置,同时还使用了链表来维护元素的顺序,这就使得它按照插入的顺序有序排列。相比Hashset多维护了链表,因此性能略低于HashSet。
四、TreeSet
TreeSet是有序,不允许重复,不允许NULL的集合。底层使用红黑树算法,擅长范围查询。
- 如果使用TreeSet的无参构造器新建一个TreeSet对象,要求存储其中的元素实现Comparable接口,所以在其中不能存入NULL
- 必须存入相同类型的对象(默认会进行排序),否则会出现类型转换异常!一般使用泛型来进行限制。
- 自然排序:要求被添加的参数对象必须实现Comparable接口,并且覆盖了compareTo(Object obj)方法:
如果 this>obj ,返回1,
如果 this=obj ,返回0,
如果 this<obj ,返回-1。
通过该方法定义的规则比较之后,按照升序排列。
- 定制排序:创建TreeSet对象时,传入实现了Compartor接口的实现类,通过compare方法定义的规则进行定制排序(如倒序),要求该实现类的compare方法和equals方法具有一致性,即:compare方法中,两个对象相等时应该return 0。
如下,按照money多少降序排列:
1 package com.vi.collection.set; 2 3 import java.util.Comparator; 4 import java.util.TreeSet; 5 6 public class TreeSetDemo 7 public static void main(String[] args) 8 Man m1 = new Man(1000); 9 Man m2 = new Man(2000); 10 Man m3 = new Man(3000); 11 Man m4 = new Man(2500); 12 TreeSet<Man> ts = new TreeSet<>(new Man(0)); 13 ts.add(m1); 14 ts.add(m2); 15 ts.add(m3); 16 ts.add(m4); 17 System.out.println(ts); 18 19 20 21 class Man implements Comparator<Man> 22 double money; 23 24 public int compare(Man m1, Man m2) 25 if (m2.money > m1.money) 26 return 1; 27 if (m2.money == m1.money) 28 return 0; 29 return -1; 30 31 32 public Man(double money) 33 this.money = money; 34 35 36 public String toString() 37 return money+" "; 38 39 40
五、对以上三种Set进行比较
共同点:
1.都不允许存入重复值
2.都是线程不安全的(解决办法:使用Collections.synchronizedSet()方法)
不同点:
1.TreeSet不允许NULL值,HashSet和LinkedList可以存入空值
2.HashSet是无序的底层采用哈希表算法,查询效率高,通过equals()和hashCode()共同判断对象是否相等,即要求存入的对象重写equals()和hashCode()保持一致性;
LinkedList底层采用了哈希表和链表的结构,既保证了元素的添加顺序,也保证了查询效率,性能略低于HashSet;
TreeSet不保证元素的添加顺序,但是会按照自然排序或定制规则对集合中元素进行排序,底层采用了红黑树算法(树结构比较适合范围查询)。
以上是关于集合—— Set的主要内容,如果未能解决你的问题,请参考以下文章
JavaSE学习总结(十三)Set集合HashSet集合LinkedHashSet集合TreeSet集合比较器的使用利用Set集合实现去重