本篇介绍内容:
- 12.HashSet 和 TreeSet 有什么区别?
- 13.HashSet 的底层实现是什么?
- 14.LinkedHashMap 的实现原理?
- 15.为什么集合类没有实现 Cloneable 和 Serializable 接口?
- 16.什么是迭代器 (Iterator)?
- 17.Iterator 和 ListIterator 的区别是什么?
- 18.数组 (Array) 和列表 (ArrayList) 有什么区别?什么时候应该使用 Array 而不是 ArrayList?
- 19.Java 集合类框架的最佳实践有哪些?
- 20.Comparable 和 Comparator 接口是干什么的?列出它们的区别?
12、HashSet 和 TreeSet 有什么区别?
1)相同点
- 都是单列集合,且数据不可重复
2)不同点
-
数据是否有序
(1)HashSet中的数据是无序的
(2)TreeSet中的数据是自动排好序的 -
是否可以放入null值
(1)HashSet可以放入null,但只能放入一个null
(2)TreeSet不允许放入null值 -
底层储存数据的结构不同
(1)HashSet底层使用的是HashMap哈希表结构储存
(2)TreeSet底层使用的是TreeMap树结构储存 -
储存数据保存唯一方式不同
(1)HashSet是通过复写hashCode()和equals()方法来保证的
(2)TreeSet是通过Compareable接口的compareto方法来保证的
3)存储原理介绍
- TreeSet底层数据结构是一个二叉树,可以对set集合中的元素进行排序,这种结构,可以提高排序性能。根据比较方法的返回值来决定,只要返回的是0,就代表元素重复
- HashSet底层数据结构是哈希表,本质就是哈希值储存。通过判断元素的hashcode方法和equals方法来保证元素的唯一性。当哈希值不同时就直接进行储存。如果相同,会判断一次equals方式是否返回为true,如果是true 则视为用的同一个元素,不用再储存。
4)相关扩展介绍
- HashSet是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,因此HashSet的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成,应该为保存到HashSet中的对象覆盖hashCode()和equals()
- 而TreeSet是基于TreeMap实现的
13、HashSet 的底层实现是什么?
1)HashSet的介绍
- HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变,此类允许使用null元素
2)底层实现
- HashSet的底层依赖HashMap实现的。而HashMap在1.7之前使用的是数组+链表实现,在1.8+使用的数组+链表+红黑树实现。即HashSet的底层实现和HashMap使用的是相同的方式,因为Map是无序的,因此HashSet也无法保证顺序。
- HashSet中的方法,也是借助HashMap的方法来实现的
14、LinkedHashMap 的实现原理?
1)LinkedHashMap 的介绍
- LinkedHashMap是Map接口的哈希表和链表实现,具有可预知的迭代顺序。此实现提供所有可选的映射操作,并允许使用null值和null键。
- LinkedHashMap实现与HashMap的不同之处在于它维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序,而且这种实现不是同步的
2)实现原理
- LinkedHashMap继承与HashMap、底层使用哈希表与双向链表来保存所有元素。其基本操作与父类HashMap相似,它通过重写父类相关的方法,来实现自己的链接列表特性
- LinkedHashMap是Hash表和链表的实现,LinkedHashMap继承于HashMap,在使用父类方法的基础上重新实现了用于维护链表的几个方法函数,这几个函数的作用分别是:节点访问后、节点插入后、节点移除后做的一些事情
3)更多知识点参考
- https://blog.51cto.com/14440216/2436123?source=dra
- https://www.jianshu.com/p/8f4f58b4b8ab
- https://blog.csdn.net/xiaoyao2246/article/details/88836769
15、为什么集合类没有实现 Cloneable 和 Serializable 接口?
1)具体回答
- 克隆(cloning)或者序列化(serialization)的语义和含义是跟具体的实现相关的。因此应该由集合类的具体实现类来决定如何被克隆或者序列化
2)Cloneable接口的介绍
- Cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现这个接口,则会抛出CloneNotSupportedException(克隆不被支持)异常
3)Serializable接口的介绍
- 一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才能被序列化。
(1)序列化:将对象的状态信息转换为可以存储或传输的形式的过程,在序列化期间,对象将其当前状态写入到临时存储区或持久性存储区,之后,便可以通过从存储区中读取或反序列化对象的状态信息,来重新创建该对象
(2)序列化将数据分解成字节流,以便存储在文件中或在网络上传输
(3)反序列化就是打开字节流并重构对象 -
实现Serializable接口的作用
(1)将对象的状态保存在存储媒体中以便可以在以后重写创建出完全相同的副本;按值将对象从一个应用程序域发向另一个应用程序域
(2)实现 Serializable接口的作用就是可以把对象存到字节流,然后可以恢复。如果你的对象没有序列化,怎么才能进行网络传输呢?要网络传输就得转为字节流,所以在分布式应用中,你就得实现序列化。如果你不需要分布式应用,那就没必要实现实现序列化
4)克隆的介绍
- 克隆就是把一个对象里面的属性值,复制给另一个对象。而不是对象引用的复制
16、什么是迭代器 (Iterator)?
1)迭代器的介绍
- 为了方便的处理集合中的元素,Java中出现了一个对象,该对象提供了一些方法专门处理集合中的元素。例如删除和获取集合中的元素,该对象就叫做迭代器(Iterator)
- 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小
2)迭代器的优缺点及Java中的使用介绍
- 优点:Iterator 是可以遍历集合的对象,为各种容器提供了公共的操作接口,隔离对容器的遍历操作和底层实现,从而解耦
- 缺点:增加新的集合类需要对应增加新的迭代器类,迭代器类与集合类成对增加;使用Iterator,就只能向前移动集合;使用Iterator,就无法操纵或修改集合中的元素
- Java中的Iterator功能(只能单向移动)
(1)使用方法iterator()(java.lang.Iterable接口,被Collection继承)要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素
(2)使用next()获得序列中的下一个元素
(3)使用hasNext()检查序列中是否还有元素
(4)使用remove()将迭代器新返回的元素删除
17、Iterator 和 ListIterator 的区别是什么?
- Iterator是ListIterator的父接口
- Iterator是单列集合(Collection)公共取出容器中元素的方式,可以遍历所有集合如Map,List,Set,但只能在向前方向上遍历集合中的元素。而ListIterator,只能遍历List实现的对象,但可以向前和向后遍历集合中的元素
- ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素add(),替换元素set(),获取前一个和后一个元素的索引
18、数组 (Array) 和列表 (ArrayList) 有什么区别?什么时候应该使用 Array 而不是 ArrayList?
1)Array和ArrayList的区别
- Array可以包含基本类型和对象类型,而ArrayList只能包含对象类型
- Array大小是固定的,而ArrayList的大小是动态变化的
- ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。对于基本类型数据,集合使用自动装箱来减少编码工作量。当处理固定大小的基本数据类型的时候,这种方式相对比较慢
- ArrayList可以算是对Array有所取舍的加强版
2)存储内容比较
- Array数组可以包含基本类型和对象类型
- ArrayList却只能包含对象类型
- Array数组在存放的时候一定是同种类型的元素。ArrayList就不一定了,因为ArrayList可以存储Object
3)空间大小比较
- Array的空间大小是固定的,空间不够时也不能再次申请,所以需要事前确定合适的空间大小
- ArrayList的空间是动态增长的,如果空间不够,它会创建一个空间比原空间大约0.5倍的新数组,然后将所有元素复制到新数组中,接着抛弃旧数组。而且,每次添加新的元素的时候都会检查内部数组的空间是否足够
4)方法上的比较
- 相对于Array而言ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等
5)使用场景
- 如果想要保存一些在整个程序运行期间都会存在而且不变的数据,我们可以将它们放进一个全局数组里,但是如果我们单纯只是想要以数组的形式保存数据,而不对数据进行增加等操作,只是方便我们进行查找的话,就选择Array
- 如果我们需要对元素进行频繁的移动或删除,或者是处理的是超大量的数据,那么就使用ArrayList。因为它的效率很低,使用数组进行这样的动作就很麻烦
19、Java 集合类框架的最佳实践有哪些?
本图片转载而来,原作者链接:https://blog.csdn.net/qq_36711757/article/details/80464499
20、Comparable 和 Comparator 接口是干什么的?列出它们的区别?
1)Comparable的介绍
- Comparable 是排序接口。Java提供了只包含一个compareTo()方法的Comparable接口,如果一个类实现了Comparable接口就说明该类支持排序。举个栗子:接口中通过a.compareTo(b)来比较a和b的大小。若返回负数,意味着a比b小;返回零,意味着a等于b;返回正数,意味着a大于b
2)Comparator 的介绍
- Comparator 是比较器接口。Java提供了包含compare()和equals()两个方法的Comparator接口,如果可一个类实现了Comparable接口,然后就可以通过该比较器对类进行排序。举个栗子:compare(T o1, T o2)方法和上面的a.compareTo(b)类似,定义排序规则后返回正数,零和负数分别代表大于,等于和小于
3)两者的比较
-
相同点
(1)他们都是java的一个接口, 并且是用来对自定义的class比较大小的
(2)Comparable和Comparator都是用来实现集合中元素的比较、排序的 -
不同点
(1)Comparable 相当于“内部比较器”,而Comparator相当于“外部比较器”(Comparable 定义在类的内部,位于java.lang下;Comparator 是定义在类的外部的,位于java.util下)
(2)实现Comparable接口需要覆盖compareTo方法,实现Comparator接口需要覆盖compare方法
(3)Comparable接口将比较代码嵌入需要进行比较的类的自身代码中,而Comparator接口在一个独立的类中实现比较
(4)Comparable接口强制进行自然排序,而Comparator接口不强制进行自然排序,可以指定排序顺序
4)更多知识点参考
- https://blog.csdn.net/u010859650/article/details/85009595
- https://blog.csdn.net/nameishg/article/details/88840350