乐趣区

关于集合:Java-集合有哪些内容

明天咱们就来简略的理解下 java 中的汇合,有理解过得敌人都晓得,也都用过,比如说做罕用的 List,还有 Set、Map,而且像 List 和 Set 都是用于存储单列数据的汇合,他们的父接口都是 Conllection,List 的特点是存储的值是有序且容许反复的,Set 的特点是存储的元素是惟一、不可反复且无序的,而 Map 的特点则是用于存储双列数据的汇合,存储的数据时无序的,键不能够反复,值能够反复。

接下来咱们就把它们拆出来具体的来聊一聊。

List 接口(通常有些面试官会问这样一个比拟根底的问题:List 是接口还是类?大家感觉呢,有教训的小伙伴必定一下子就能答复进去,然而有一些刚开始学习的小白同学可能会有一些犹豫哦,那这次我都会给大家说说滴,小白同学看完当前有人再问你这样的问题就不会再犹豫啦)

首先咱们要明确:咱们 java 中的汇合分为单列汇合和双列汇合,单列汇合的顶级接口是:Conllection,双列汇合的顶级接口是:Map

而 List 就是属于单列汇合 Conllection 的子接口,List 接口的实现类如下:(所以 List 是接口不是类哦,通过上面能够多理解理解 List 接口的实现类都有哪些):

1.ArrayList(List 接口的实现类):底层数据结构是数组,查问快,增删慢,因为家喻户晓 ArrayList 的底层数据结构是数组,向 ArrayList 中退出元素 add 的时候,有可能会导致 List 的扩容,因为 ArrayList 底层是数组构造,但数组不反对动静扩容,所以 ArrayList 的扩容机制就是再创立一个新数组,把就数组数据迁徙到新数组,而后再退出新元素,这样一个过程下来也就是造成 ArrayList 减少元素慢的外围起因了。

而 ArrayList 在删除元素时底层是将删除索引地位起到最初索引地位完结中所有的元素,一一向前复制一个索引地位,再将最初索引地位元素设置为 null,简略来说就是,假如我当初要删除这个汇合中 0 索引地位上的元素,我将 0 索引地位下面的元素删除之后,并不是将这个地位的元素间接设置为 null,而是前面 1 索引地位到最初索引地位上的所有元素都要走一个一一向前复制一个索引地位过程,直到最初一个索引元素向前复制完结之后,将开端地位上空缺的元素复制为 null,所以也就是说在删除元素的时候会影响其余索引地位上的元素的地位,所以也会升高删除元素的效率。

(ArrayList 汇合删除元素之后其余索引地位上的元素挪动地位的变动过程)了解完增删慢的起因,其实查问快的起因大家就曾经很好了解了,ArrayList 在查问元素时底层是通过拜访数组元素形式进行查问。数组(Array)是一种线性表(线性表就是数据排成像一条线一样的构造。每个线性表上的数据最多只有前和后两个方向)数据结构。

它用一组间断的内存空间,来存储一组具备雷同类型的数据。并且申明一个数组时,会在内存中申请一块间断相邻的内存空间。当要通过索引拜访数组元素时,可通过数组地址值和偏移量,间接计算出要查找元素的内存地址,所以数组反对通过索引间接拜访元素,效率十分高。数组中的元素都是有下标的,所以依据下标就能够很快的找到你要查问的元素了(应用 get()办法,就能够间接取的是数组对应下标中的值)。

2.LinkedList(List 接口的实现类):底层数据结构是链表,查问慢,增删快

LinkedList 之所以查问慢是因为,LinkedList 底层是一个链表,链表必定没有下标的概念,所以他不能像 ArrayList 一样,应用 get()办法,就能够间接取的是数组对应下标中的值,它只能是对总数遍历,而后取循环下标的值,所以如果 LinkedList 链表 size 越大,那么会使 for 循环的次数增多导致遍历的工夫也会越长,查问也就慢了(然而如果大家在编码过程中还是须要思考应用 LinkedList 的话在查问的时候能够应用 getFirst()、getLast() 办法缩小 for 循环的次数来绝对减少查问的速度)。

而 LinkedList 之所以减少元素时快次要是因为,LinkedList 应用 add(E e)间接增加元素或者 add(int index, E e)指定地位增加元素,这两种办法插入元素,绝对与 ArrayList 效率是较高的,因为 ArrayList 减少元素的时候可能须要扩容和元素的拷贝,减少了开销,而 LinkedList 是断开指定地位的链接把新节点增加进来即可,所以整个增加过程中,零碎也只做了两件事件,增加一个新的节点,而后保留该节点和前节点的援用关系,简略来说就是新减少了一个链接而已,所以效率高。

删除元素的时候也是依据 remove(Object o) 删除元素或者 remove(int index)删除指定地位元素这两种办法进行元素的删除,所以简略来说删除效率高次要是因为只须要删除某个链接,再链接新的元素即可,不须要批改列表中残余的元素。

3.Vector(List 接口的实现类):底层数据结构是数组,正因为它的底层是数组所以他的特点跟 ArrayList 一样是查问快,增删慢的特点,这一点能够参考下面 ArrayList 的解释。Set 接口也是单列汇合 Conllection 的子接口,接下来咱们就持续看看他的实现类有哪些吧!

1.HashSet(Set 接口的实现类):底层数据结构是哈希表,它是基于 HashMap 实现的,底层采纳 HashMap 来保留元素,HashSet 就是为了进步查问效率的,意思就是在查问某个值是否存在的时候,ArrayList 须要遍历能力获取到某个值的地位,而 HashSet 能够通过 HashCode 疾速进行定位,而且 HashSet 是依据哈希算法来进行对象的存取的,存取速度很快,当 HashSet 中元素的个数超出数组本来的大小,就会进行扩容,而哈希表其实次要依赖 hashcode()和 equals()这两个办法。简略来讲就是首先通过 hashcode()来判断 hashcode 值是否雷同,如果雷同的话就会执行 equals()来查看他们的返回值是否雷同,如果返回 true 的话,就阐明这两个元素反复,则不进行增加,如果返回是 false 的话,就间接增加到汇合当中。如果 hashcode 值不雷同就能够间接增加到汇合当中,以上就是针对于 HashSet 的特点的简略介绍。

2.LinkedHashSet(Set 接口的实现类):底层数据结构是链表 + 哈希表,由链表保障元素的有序,由哈希表保障元素的惟一,LinkedHashSet 是一个基于 LinkedHashMap 实现的有序去重汇合列表,LinkedHashSet 中的元素没有反复;LinkedHashSet 中的元素有程序,保护了增加程序;LInkedHashSet 能够存储 null 值;这个容器不晓得大家在平时的工作用的多吗,反正我基本上没有用过,所以就是就是我集体针对于他的特点做的简略介绍。

3.TreeSet(Set 接口的实现类):底层数据结构是红黑树,特点是元素惟一,且有序,由天然排序和比拟器排序来保障有序的特点,依据返回值是否是 0 来判断元素是否惟一。TreeSet 是有序的 Set 汇合,因而反对 add、remove、get 等办法,TreeSet 不反对疾速随机遍历,只能通过迭代器进行遍历,如果想把自定义类的对象存入 TreeSet 进行排序, 那么必须实现 Comparable 接口,或者实现一个比拟器,在类上 implements Comparable,重写 compareTo()办法,在办法内定义比拟算法, 依据大小关系, 返回负数正数或零,在应用 TreeSet 存储对象的时候, add()办法外部就会主动调用 compareTo()办法进行比拟, 依据比拟后果应用二叉树模式进行存储。

简略写了一个排序大家能够粗鲁看看

这是排序的一个运行后果图,遍历两次是因为应用了两种不同的遍历形式接下来就该说说双列汇合 Map 了,大家能够看看他的实现类有哪些。

1.HashMap(Map 接口的实现类):底层数据结构是数组 + 链表,基于哈希表的 Map 接口的实现。并容许应用 null 值和 null 键,是以 key-value 存储模式存在,每一个键值对也叫做一个 Entry,依据键的 hashCode 值存储数据,大多数状况下能够间接定位到它的值,键 key 为 null 的记录至少只容许呈现一条,值 value 为 null 的记录能够有多条,HashMap 的实现不是同步的,这意味着它不是线程平安的,HashMap 是由数组 + 链表 + 红黑树(JDK1.8 后减少了红黑树局部,链表长度超过阈值(8)时会将链表转换为红黑树)实现的。对于 HashMap 常常会有面试官问 HashSet 和 HashMap 的区别?其实针对于这个问题,大家通过上述 HashSet 的解释也能总结进去了,

相同点:

1. 都是采纳的 Hash 散列算法调配的数据,

2. 都是线程不平安的,

3. 数据查问是无序的;

不同点:

1. 继承的父类不同

2.set 的单键,而 hashmap 是能够存键值对

3.hashmap 是能够存不同的 value 然而 hashset 不反对雷同 value 数据。

以上就是针对于 HashMap 特点的简略介绍,如果大家想理解对于源码的解释能够自行学习理解,以上只是做一个简略的入门理解。2.LinkedHashMap(Map 接口的实现类):LinkedHashMap 继承了 HashMap 类,默认状况下会应用 entryset 来获取的汇合程序与节点的插入程序统一的。

除去 hashmap 的逻辑之外,咱们都晓得,LinkedHashMap 中还保护了一个双向链表,当新建待插入的 Entry 时,咱们要晓得 LinkedHashMap 中的 Entry 类继承了 HashMap 中的 Node 类,而 entry 中新加了两个指针属性别离是 before、after,它们别离指向之前和之后插入的节点。

同时 LinkedHashMap 中多了 3 个参数,head、tail,accessOrder,双向链表默认是依照插入的程序来进行排列的,最先插入的节点 (也就是指最老的节点) 为 head,最新插入的节点为 tail。accessOrder 参数示意双向列表的排列程序是依照节点的插入程序还是拜访程序,默认是 false 即插入程序,true 代表的是拜访程序。当排列模式是按拜访程序时,如果调用了 get 或 put 办法且 key 存在时,会调用 afterNodeAccess 办法,将最近被拜访的节点移至双向队列的队尾。

其实最重要的一点咱们要分明 LinkedHashMap 通过特有底层双向链表的反对,使得 LinkedHashMap 能够保留元素之间的程序,例如插入程序或者拜访程序,而 HashMap 因为没有双向链表的反对,所以就不能放弃这种程序,所以它的拜访就是随机的了,和 HashMap 一样,还是通过数组存储元素的。

3.TreeMap(Map 接口的实现类):它是一个有序的 key-value 汇合,次要通过红黑树来实现,它最大的特点是遍历时是有程序的,依据 key 的排序规定来。TreeMap 继承 AbstractMap(因为 TreeMap 继承于 AbstractMap,所以它是一个 Map,即一个 key-value 汇合),实现 NavigableMap、Cloneable、Serializable 三个接口。

其中 AbstractMap 表明 TreeMap 为一个 Map 即反对 key-value 的汇合,NavigableMap 则意味着它反对一系列的导航办法(比方返回有序的 key 汇合),具备针对给定搜寻指标返回最靠近匹配项的导航办法。而且因为它是基于红黑树,所以它蕴含几个重要的成员变量:root(root 是红黑数的根节点)、size(是红黑数中节点的个数)、comparator(比拟器,红黑数排序时,依据 Entry 中的 key 进行排序)。当然在面试过程中可能会有面试官问你这样的问题,例如:TreeMap 和 HashMap 的区别是什么?依据这个问题,能够给大家简略总结一下。

相同点:

两者均是线程不平安的;

增删改查操作的;

两者插入节点时,key 反复后都会笼罩旧值。

不同点:

底层数据结构不同。HashMap 是基于数组 + 链表 + 红黑树的数据结构,TreeMap 是基于红黑树的数据结构;

HashMap 是无序的,TreeMap 是有序的;HashMap 容许存储 null,TreeMap 的键不容许存储 null,然而值能够为 null;

TreeMap 要求 key 必须实现 Comparable 接口,或者初始化时传入 Comparator 比拟器。

好啦以上就是给大家简略总结的 java 汇合,心愿对大家有点帮忙哦!次要的几张图中都给大家反馈进去了具体 java 汇合都有哪些,大家能够作为参考持续学习哦!

退出移动版