什么是HashSet?操作过程是怎么样的?

  1、HashSet底层实际上是一个HashMap,HashMap底层采用了哈希表数据结构

  2、哈希表又叫做散列表,哈希表底层是一个数组,这个数组中每一个元素是一个单向链表,每个单向链表都有一个独一无二的hash值,代表数组的下标。在某个单向链表中的每一个节点上的hash值是相同的。hash值实际上是key调用hashCode方法,再通过"hash function"转换成的值

  3、如何向哈希表中添加元素?

    先调用被存储的key的hashCode方法,经过某个算法得出hash值,如果在这个哈希表中不存在这个hash值,则直接加入元素。如果该hash值已经存在,继续                调用Key之间的equals方法,如果equals方法返回false,则将该元素添加。如果equals方法返回true,则放弃添加该元素

    HashMap和HashSet初始化容量是16,默认加载因子是0.75

HashSet的数据结构

  献上我看视频截的图

  

代码举例

 public class Test{

     public static void main(String[] args) {

         Set set = new HashSet();

         Student stu1 = new Student("1", "JACK");
Student stu2 = new Student("2", "TOM");
Student stu3 = new Student("3", "JIM"); set.add(stu1);
set.add(stu2);
set.add(stu3); System.out.println("size :" + set.size());
} } class Student{
String no;
String name; Student(String no, String name){
this.no = no;
this.name = name;
}
}

  这个的输出结果显而易见是3,因为我们添加了三个元素,但是如果改一下

 Student stu1 = new Student("1", "JACK");
Student stu2 = new Student("1", "JACK");
Student stu3 = new Student("3", "JIM"); System.out.println(stu1.hashCode());
System.out.println(stu2.hashCode());

  可以运行试一下,stu1和stu2的hashCode是不一样的,为什么呢?因为这两个对象是New出来的,引用地址不一样。我们不希望出现这样的情况,那就要重写hashCode和equals方法

 class Student{
String no;
String name; Student(String no, String name){
this.no = no;
this.name = name;
} public boolean equals(Object o){
if(this == o) return true;
if(o instanceof Student){
Student student = (Student) o;
if(student.no.equals(this.no) && student.name.equals(this.name)) return true;
} return false;
} public int hashCode(){
return no.hashCode();
}
}

  再次运行,插入两个数据一样的对象,就不会重复了

TreeSet

  treeset实现了sortedset接口,有个很重要的特点是里面的元素都是有序的

 public class Test{

     public static void main(String[] args) {

         SortedSet set = new TreeSet();

         set.add(1);
set.add(100);
set.add(50); System.out.println(set);
} }

  输出结果:[1, 50, 100]

  那如果我们自定义类可以进行比较吗?

 public class Test{

     public static void main(String[] args) {

         SortedSet set = new TreeSet();

         Student stu1 = new Student(22);
Student stu2 = new Student(11);
Student stu3 = new Student(100); set.add(stu1);
set.add(stu2);
set.add(stu3); System.out.println(set);
} } class Student{
int age; Student(int age){
this.age = age;
}
}

  这样运行会出现一个问题,报ClassCastException,这就需要来看看源码了,底层到底是怎么实现的,为什么自定义类就先不行呢?

  这里可以看到,当我们在创建一个TreeSet的时候,实际上是new了一个TreeMap

  add的时候调用了TreeMap的put方法,来看看TreeMap中的put方法

  可以看到第三个红框那里,会对key进行一个强制类型转换,我们上面的代码肯定是就是在这里装换不成功,Comparable是什么?来看看API

  是一个接口,从翻译就可以看出,只要实现了这个接口,就是可以比较的,下面是实现了这个接口的类

  随便框了几个,上面就有Integer,这个类实现了comparable接口,因此第一个代码是正确的,现在我们是不是只要实现这个接口就好了呢!

 class Student implements Comparable{
int age; Student(int age){
this.age = age;
} //重写接口中的方法
//要重写比较规则
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
int age1 = this.age;
int age2 = ((Student)o).age;
return age2 - age1;
}
}

  这样OK了,再来看看上面有红框的源码,cmp<0,cmp>0,left,right都是什么东西,二叉树!所以底层是通过二叉树来排序的

  如果是自定义类中的String呢,那就return String的compareTo方法就好了

Java Set集合(HashSet、TreeSet)的更多相关文章

  1. Set集合[HashSet,TreeSet,LinkedHashSet],Map集合[HashMap,HashTable,TreeMap]

    ------------ Set ------------------- 有序: 根据添加元素顺序判定, 如果输出的结果和添加元素顺序是一样 无序: 根据添加元素顺序判定,如果输出的结果和添加元素的顺 ...

  2. Java容器---Set: HashSet & TreeSet & LinkedHashSet

    1.Set接口概述        Set 不保存重复的元素(如何判断元素相同呢?).如果你试图将相同对象的多个实例添加到Set中,那么它就会阻止这种重复现象. Set中最常被使用的是测试归属性,你可以 ...

  3. Java基础---集合框架---迭代器、ListIterator、Vector中枚举、LinkedList、ArrayList、HashSet、TreeSet、二叉树、Comparator

    为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 数组和集合类同是容器,有何不同? 数组虽然也可以存储对 ...

  4. Java集合之TreeSet

    TreeSet是一个有序的集合,它的作用是提供有序的Set集合.它继承了AbstractSet抽象类,实现了NavigableSet<E>,Cloneable,Serializable接口 ...

  5. Java集合 HashSet的原理及常用方法

    目录 一. HashSet概述 二. HashSet构造 三. add方法 四. remove方法 五. 遍历 六. 合计合计 先看一下LinkedHashSet 在看一下TreeSet 七. 总结 ...

  6. java数据结构之HashSet和TreeSet以及LinkedHashSet

    一.HashSet源码注释 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cl ...

  7. 集合框架的详解,List(ArrayList,LinkedList,Vector),Set(HashSet,TreeSet)-(14)

    集合详解: /* Collection |--List:元素是有序的,元素可以重复.因为该集合体系有索引. |--ArrayList:底层的数据结构使用的是数组结构.特点:查询速度很快.但是增删稍慢. ...

  8. Set集合——HashSet、TreeSet、LinkedHashSet(2015年07月06日)

    一.Set集合不同于List的是: Set不允许重复 Set是无序集合 Set没有下标索引,所以对Set的遍历要通过迭代器Iterator 二.HashSet 1.HashSet由一个哈希表支持,内部 ...

  9. Java基础知识强化之集合框架笔记47:Set集合之TreeSet保证元素唯一性和比较器排序的原理及代码实现(比较器排序:Comparator)

    1. 比较器排序(定制排序) 前面我们说到的TreeSet的自然排序是根据集合元素的大小,TreeSet将它们以升序排列. 但是如果需要实现定制排序,比如实现降序排序,则要通过比较器排序(定制排序)实 ...

随机推荐

  1. ACM-ICPC 2018 徐州赛区网络预赛 A.Hard to prepare 【规律递推】

    任意门:https://nanti.jisuanke.com/t/31453 A.Hard to prepare After Incident, a feast is usually held in ...

  2. 2018.11.12 Spring事务的实现和原理

    Spring事务用法示例与实现原理 关于事务,简单来说,就是为了保证数据完整性而存在的一种工具,其主要有四大特性:原子性.一致性.隔离性和持久性.对于Spring事务,其最终还是在数据库层面实现的,而 ...

  3. <知识整理>2019清北学堂提高储备D3

    全天动态规划入门到入坑... 一.总概: 动态规划是指解最优化问题的一类算法,考察方式灵活,也常是NOIP难题级别.先明确动态规划里的一些概念: 状态:可看做用动态规划求解问题时操作的对象. 边界条件 ...

  4. 最短路问题:迪杰斯特拉算法(Dijsktra)

    Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Di ...

  5. 课时89.CSS三大特性练习(理解)

    给大家补充一点:通配符是不参与权重计算的,因为通配符的权重是0,而权重只计算id,类,标签,将来还有一种,到后面说. 练习1 直接选中和间接选中的,必然要听直接选中的. 练习2 直接选中一共有两个,直 ...

  6. Django-rest-framework(八)使用技巧(持续补充中)

    当viewset中,多个action对应了不同的serializers的时候 class UserView(viewsets.GenericViewSet): queryset = User.obje ...

  7. 你不知道的javaScript笔记(3)

    对象 对象可以通过两种形式定义: 声明形式和构造形式 声明形式语法: var myObj = {key:value} 构造形式语法: var myObj = new Object(); myObj.k ...

  8. css3 动画应用 animations 和transtions transform在加上JavaScript 可以实现硬件加速动画。

    transitions(过渡) 被应用于元素指定的属性变化时,该属性经过一段时间逐渐的过渡到最终想要的值. 主要包括四个属性: 执行变换的属性:transition-property 变换延续的时间: ...

  9. flexible.js在华某为手机上使用rem时,页面宽度超出手机屏幕宽度

    问题:手机端项目在华为的某款手机上显示时页面内容没有自适应手机宽度,出现横向滚动条 原因:手机获取手机屏幕宽度并计算出rem时出现偏差,明显宽余真实手机屏宽度 解决方案一:在页面里获取页面最外层dom ...

  10. 利用C++中采用面向对象的思想顺序表

    最近在复习数据结构,我用面向对象的思想实现了顺序表,采用C++语言. 首先建立在Visual Studio 2017中建立一个工程,然后新建一个类SqList.然后会生成SqList.h和SqList ...