Set相关概述
-
Set集合概述及特点
- 概述:无序,无索引,不可重复
- 特点:Set接口方法和Collection方法完全一致,没有任何特性方法.
-
Set与List的区别与联系
-
区别
- List接口
- 有序,有索引,可存储重复值
- 比Collection多了根据索引去add(),addAll(),get(),indexOf(Object o),lastIndexOf(),listIterator()(可以在迭代器中直接添加存储至集合中的对象),remove(),subList()方法.
- 存储针对性:针对于要求存取顺序一致,对数据内容不做限制,并且对数据的查询修改删除操作较多的存储情况
- Set接口
- 无序,无索引,不可以存储重复值
- Set接口方法和Collection方法完全一致,没有任何特性方法.
- 存储针对性:针对于要求不能存储在某种条件下的重复数据,取出数据时按照某种设定进行排序的存储情况.
- List接口
-
联系
- 由于两者均实现了Collection接口,而Collection接口中存在了addAll()方法,因此两者可以通过此方法进行数据的整体传递与转移,可以通过两者的配合去实现更多的需求.
- 都可以通过增强for或迭代器来遍历取出集合中的元素.
-
HashSet的相关概述
-
当往HashSet(TreeSet也是)集合对象容器中存储基本数据类型的包装类数据或String字符串时,它可以自动完成数据的去重,那么当存储自定义对象的时候如何保证元素的唯一性呢?
- 答案是重写hashCode()和equals()方法.
-
HashSet保证元素唯一性的原理
- 我们使用Set集合都是需要去掉重复元素的,如果在存储的时候逐个equals()比较,效率较低,哈希算法提高了去重复的效率,降低了使用equals()方法的次数
- 当HashSet调用add()方法存储对象的时候,先调用对象的hashCode()方法得到一个哈希值,然后在集合中查找是否有哈希值相同的对象
- 如果没有哈希值相同的对象就直接存入集合
- 如果有哈希值相同的对象,就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入,true则不存.
-
HashSet存储无序的原因分析:
- 因为HashSet实现方式也是编程实现的,既然是编程实现那么就有规律,所以HashCode存储无序只是相对而言的,它的存储是和元素的地址值(hashCode)相关的,因此它的存储顺序也与地址值有关,而不是与存储时的先后顺序有关.
LinkedHashSet的相关概述
- LinkedHashSet的特点
- 可以保证怎么存就怎么取(set集合中唯一一个能够保证怎么存就怎么去的实现子类).
TreeSet的相关概述
-
特点
- TreeSet是用来排序的,可以指定一个顺序,对象存入之后会按照指定的顺序排列.
-
使用方式
- 自然顺序(Comparable)
- TreeSet类的add()方法中会把存入的对象提升为Comparable类型.
- 调用对象的compareTo()方法和集合中的对象比较
- 根据compareTo()方法返回的结果进行存储
- 比较器顺序(Comparator)
- 创建TreeSet的时候可以指定一个Comparator(通常在创建TreeSet的时候在其构造器中传入一个Comparator类的匿名对象)
- 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序
- add()方法内部会自动调用Comparator接口中compare()方法排序.
- 调用的对象是compare(T s1,T s2)方法的第一个参数s1,集合中的对象是compare方法的第二个参数s2.
- 两种方式的区别
- TreeSet构造函数什么都不传,默认按照类中Comparable的顺序(没有就报错ClassCastException)
- TreeSet如果传入Comparator,就优先按照Comparator
- 自然顺序(Comparable)
扩展知识: 集合体系中所有的实现类都重写了toString方法,因为它们都直接或间接的继承了AbstractCollection类,而该类对toString方法进行了重写.因此直接调用它的toString()方法就可以看到集合对象中所存储的元素,而数组则没有,因此要遍历才能看到里面的元素. HashSet保证数据的唯一性实现的原理:当往里面添加元素时,先调用hashcode方法,若返回值不一致则直接判断元素不重复,若hashcode返回值一致则再根据equals判断若返回也为true则判定两个元素一致.注意和ArrayList类中的contains()之间的区别,contains()方法在判断时只依赖equals()方法,与hashcode()方法无关.
在javabean中,当重写hashcode时eclipse中自动生成的代码中为什么定义的常量值为31? * 为什么是31?? * 1.31是一个质数,质数是只能被1和自己本身整除的数 * 2.31这个数,既不大也不小 * 3.31这个数好算,2的五次方-1,2向左移动五位再减一
二叉树:两个叉 小的存储在左边(负数),大的存储在右边(正数),相等就不存(0) compareTo方法,在TreeSet集合如何存储元素取决于compareTo方法的返回值: 1,返回0,集合中只有一个元素 2,返回-1集合回将存储的元素倒序 3,返回1集合回怎么存就怎么取
TreeSet存数据时,根据compareTo()方法定义的比较数据大小的顺序往二叉树中存数据,取数据的时候,按照二叉树的数据结构进行取,即按照左中右的顺序进行取值.因此可以按照自己的意愿去对数据进行存储并且排序.当然当TreeSet中存储引用对象时,引用对象类要先实现compareable接口.