引言

第三天卡。。。

今天主要看了下java容器方面的知识,很累但是很充实。吃两把鸡去了,休息一下,再战。

开始

-Collection 存储对象的集合;Map 存储键值对的映射表
    -Iterator(迭代器模式)
        -集合访问器,用于循环访问集合中的对象
        -所有实现了Collection接口的容器类都有iterator方法,用于返回一个实现了Iterator接口的对象。Iterator对象称作迭代器,Iterator接口方法能以迭代方式逐个访问集合中

    各个元素,并可以从Collection中除去适当的元素
    -Collection
        -set(特征:无序且不可重复)
            -TreeSet:基于红黑树实现,支持有序性操作,例如根据一个范围查找元素的操作。但是查找效率不如 HashSet,HashSet 查找的时间复杂度为 O(1),TreeSet 则为

     O(logN)。
            -HashSet:基于哈希表实现,支持快速查找,但不支持有序性操作。并且失去了元素的插入顺序信息,也就是说使用 Iterator 遍历 HashSet 得到的结果是不确定的
            -LinkedHashSet:具有 HashSet 的查找效率,且内部使用双向链表维护元素的插入顺序
            -红黑树:漫画看懂红黑树 链接:https://www.sohu.com/a/201923614_466939
        -list(特征:有序且可重复)
            -ArrayList:基于动态数组实现,支持随机访问。
                -概览
                    -实现了 RandomAccess 接口,因此支持随机访问。这是理所当然的,因为 ArrayList 是基于数组实现的,其数组的默认大小为 10。
                -序列化
                    -基于数组实现,并且具有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就没必要全部进行序列
                     transient Object[] A; //transient关键字声明数组默认不会被序列化
                        -为什么定义A数组要用transient关键字修饰,使其默认不被序列化?
                            假如现在实际有了5个元素,而elementData的大小可能是10,那么在序列化时只需要储存5个元素,数组中的最后五个元素是没有实际意义的,不需要储

          存。所以ArrayList的设计者将elementData设计为transient,然后在writeObject方法中手动将其序列化,并且只序列化了实际存储的那些元素,而不是整

          个数组
                    -序列化时需要使用 ObjectOutputStream 的 writeObject() 将对象转换为字节流并输出。而 writeObject() 方法在传入的对象存在 writeObject() 的时候会去反射

        调用该对象的 writeObject() 来实现序列化。反序列化使用的是 ObjectInputStream 的 readObject() 方法,原理类似。
                    -java中序列化的目的:
                        -以某种存储形式使自定义对象持久化;
                        -将对象从一个地方传递到另一个地方。
                        -使程序更具维护性
                -扩容
                    -添加元素时使用 ensureCapacityInternal() 方法来保证容量足够,如果不够时,需要使用 grow() 方法进行扩容,新容量的大小为 oldCapacity + (oldCapacity

        >> 1),也就是旧容量的 1.5 倍
                    -扩容操作需要调用 Arrays.copyOf() 把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作

        的次数
                -删除元素
                    -需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N), ArrayList 删除元素的代价是非常高的。
                -fail-fast
                    -modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元

        素的值不算结构发生变化
                    -在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。
                -fail-fast与fail-safe
                    -fail-fast
                        -fail-fast机制在遍历一个集合时,当集合结构被修改,会抛出ConcurrentModificationException。
                        -java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)。
                    -fail-safe
                        -fail-safe任何对集合结构的修改都会在一个复制的集合上进行修改,不像fail-fast在原集合上修改,因此不会抛出ConcurrentModificationException
                        -java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
                        -优点
                            -避免了ConcurrentModificationException
                        -缺点
                            -需要复制集合,产生大量的无效对象,开销大
                            -无法保证读取的数据是目前原始数据结构中的数据。
                            -迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。
            -Vector:和 ArrayList 类似,但它是线程安全的。
                -它的实现与 ArrayList 类似,但是使用了 synchronized 进行同步。因此是线程安全的
                -与ArrayList比较
                    -Vector 是同步的,因此开销就比 ArrayList 要大,访问速度更慢。最好使用 ArrayList 而不是 Vector,因为同步操作完全可以由程序员自己来控制;
                    -Vector 每次扩容请求其大小的 2 倍空间,而 ArrayList 是 1.5 倍。
            -LinkedList:基于双向链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。不仅如此,LinkedList 还可以用作栈、队列和双向队列。
                -概览
                    -基于双向链表实现,使用 Node 存储链表节点信息。
                      private static class Node<E> {
                            E item;
                            Node<E> next;
                            Node<E> prev;
                        }
                      每个链表存储了 first 和 last 指针
                      transient Node<E> first;
                      transient Node<E> last;
                -与 ArrayList 的比较
                    -ArrayList 基于动态数组实现,LinkedList 基于双向链表实现;
                    -ArrayList 支持随机访问,LinkedList 不支持;
                    -LinkedList 在任意位置添加删除元素更快。
    -Map
        -TreeMap:基于红黑树实现
        -HashMap:基于哈希表实现。
            -存储结构
                -内部包含了一个 Entry 类型的数组 table。
                    transient Entry[] table;
                    Entry 存储着键值对。它包含了四个字段,从 next 字段我们可以看出 Entry 是一个链表。即数组中的每个位置被当成一个桶,一个桶存放一个链表。HashMap 使

      用拉链法来解决冲突,同一个链表中存放哈希值相同的 Entry。
                   

- 拉链法的工作原理
                HashMap<String, String> map = new HashMap<>();
                map.put("K1", "V1");
                map.put("K2", "V2");
                map.put("K3", "V3");
                新建一个 HashMap,默认大小为 16;
                插入 <K1,V1> 键值对,先计算 K1 的 hashCode 为 115,使用除留余数法得到所在的桶下标 115%16=3。
                插入 <K2,V2> 键值对,先计算 K2 的 hashCode 为 118,使用除留余数法得到所在的桶下标 118%16=6。
                插入 <K3,V3> 键值对,先计算 K3 的 hashCode 为 118,使用除留余数法得到所在的桶下标 118%16=6,插在 <K2,V2> 前面。
               
                -应该注意到链表的插入是以头插法方式进行的,例如上面的 <K3,V3> 不是插在 <K2,V2> 后面,而是插入在链表头部。
                -查找需要分成两步进行:
                    -计算键值对所在的桶;
                    -在链表上顺序查找,时间复杂度显然和链表的长度成正比。

-put操作
                -HashMap 允许插入键为 null 的键值对。但是因为无法调用 null 的 hashCode() 方法,也就无法确定该键值对的桶下标,只能通过强制指定一个桶下标来存放。  

      HashMap 使用第 0 个桶存放键为 null 的键值对。
            -确定桶下标
            -扩容
                -基本原理
                -重新计算桶下标
                -计算数组容量
            -链表转红黑树
                -从 JDK 1.8 开始,一个桶存储的链表长度大于 8 时会将链表转换为红黑树
            -与 HashTable 的比较
                HashTable 使用 synchronized 来进行同步。
                HashMap 可以插入键为 null 的 Entry。
                HashMap 的迭代器是 fail-fast 迭代器。
                HashMap 不能保证随着时间的推移 Map 中的元素次序是不变的。
        -HashTable:和 HashMap 类似,但它是线程安全的,这意味着同一时刻多个线程可以同时写入 HashTable 并且不会导致数据不一致。它是遗留类,不应该去使用它。现

    在可以使用 ConcurrentHashMap 来支持线程安全,并且 ConcurrentHashMap 的效率会更高,因为 ConcurrentHashMap 引入了分段锁。
        -LinkedHashMap:使用双向链表来维护元素的顺序,顺序为插入顺序或者最近最少使用(LRU)顺序。

java容器篇的更多相关文章

  1. 菜鸟刷面试题(五、Java容器篇)

    目录: java 容器都有哪些? Collection 和 Collections 有什么区别? List.Set.Map 之间的区别是什么? HashMap 和 Hashtable 有什么区别? 如 ...

  2. Java并发-同步容器篇

    作者:汤圆 个人博客:javalover.cc 前言 官人们好啊,我是汤圆,今天给大家带来的是<Java并发-同步容器篇>,希望有所帮助,谢谢 文章如果有问题,欢迎大家批评指正,在此谢过啦 ...

  3. Java并发容器篇

    作者:汤圆 个人博客:javalover.cc 前言 断断续续一个多月,也写了十几篇原创文章,感觉真的很不一样: 不能说技术有很大的进步,但是想法确实跟以前有所不同: 还没开始的时候,想着要学的东西太 ...

  4. java容器——面试篇

    背景:java容器是面试中基础的基础,所以 有必要对着源码撸一遍. 进行了高度总结,首推: https://github.com/CyC2018/CS-Notes/blob/master/notes/ ...

  5. Java面试题(容器篇)

    容器 18.java 容器都有哪些? 如图:   首先分为Collection.Map: Collection下分为List.Set和Queue: List下分为ArrayList和LinkedLis ...

  6. 【Java心得总结七】Java容器下——Map

    我将容器类库自己平时编程及看书的感受总结成了三篇博文,前两篇分别是:[Java心得总结五]Java容器上——容器初探和[Java心得总结六]Java容器中——Collection,第一篇从宏观整体的角 ...

  7. 【Java心得总结六】Java容器中——Collection

    在[Java心得总结五]Java容器上——容器初探这篇博文中,我对Java容器类库从一个整体的偏向于宏观的角度初步认识了Java容器类库.而在这篇博文中,我想着重对容器类库中的Collection容器 ...

  8. 【Java心得总结五】Java容器上——容器初探

    在数学中我们有集合的概念,所谓的一个集合,就是将数个对象归类而分成为一个或数个形态各异的大小整体. 一般来讲,集合是具有某种特性的事物的整体,或是一些确认对象的汇集.构成集合的事物或对象称作元素或是成 ...

  9. Java提高篇(三三)-----Map总结

    在前面LZ详细介绍了HashMap.HashTable.TreeMap的实现方法,从数据结构.实现原理.源码分析三个方面进行阐述,对这个三个类应该有了比较清晰的了解,下面LZ就Map做一个简单的总结. ...

随机推荐

  1. vue项目中的跨域源请求拦截问题CORS头缺少'Access-Control-Allow-Origin'

    这里使用的是axios发请求出现的. 访问的api接口是: 在不同域之间访问是比较常见,在本地调试访问远程服务器....这就是有域问题. VUE解决通过proxyTable 解决办法: 1.检查请求方 ...

  2. 标准库bufio个人详解

    本文是我有通俗的语言写的如果有误请指出. 先看bufio官方文档 https://studygolang.com/pkgdoc文档地址 主要分三部分Reader.Writer.Scanner 分别是读 ...

  3. elasticsearch安装踩坑记

    ES的安装与启动时问题解决 环境: ​ 系统环境:CentOS7 ​ JDK:jdk-8u131-linux-x64.tar.gz 不可以通过Root用户来启动ES 通过上面的错误提示可以看出,can ...

  4. 万恶之源-python基本数据类型

    万恶之源-基本数据类型(dict) 本节主要内容: 字典的简单介绍 字典增删改查和其他操作 3. 字典的嵌套 ⼀一. 字典的简单介绍 字典(dict)是python中唯⼀一的⼀一个映射类型.他是以{ ...

  5. 【python测试开发栈】python内存管理机制(一)—引用计数

    什么是内存 在开始进入正题之前,我们先来回忆下,计算机基础原理的知识,为什么需要内存.我们都知道计算机的CPU相当于人类的大脑,其运算速度非常的快,而我们平时写的数据,比如:文档.代码等都是存储在磁盘 ...

  6. 《手把手教你》系列练习篇之2-python+ selenium自动化测试(详细教程)

    1. 简介 今天我们还是继续练习练习基本功,各位小伙伴要耐住住性子,要耐得住寂寞啊,不要急躁,后面你会感谢你在前边的不断练习的.到后面也是检验你前边的学习成果的一次很好实践. 本文介绍如何通过link ...

  7. JavaScript笔记十二

    1.DOM对CSS的操作 - 读取和修改内联样式 - 使用style属性来操作元素的内联样式 - 读取内联样式: 语法:元素.style.样式名 - 例子: 元素.style.width 元素.sty ...

  8. day20190904一号店网页HTML+CSS

    1.知识要理一理.梳理.当天讲了什么内容?当天我学习到了什么内容?看懂.所有的学习型从模仿开始.1.看懂代码,看懂思路,学思路,多问自己问题,为什么要这么写?下一步为什么要这么写?因 果.2.多练多敲 ...

  9. 队列&生产者消费者模型

    队列 ipc机制:进程通讯 管道:pipe 基于共享的内存空间 队列:pipe+锁 queue from multiprocessing import Process,Queue ### 案例一 q ...

  10. 形式语言与自动机|DFA识别句子

    实验二 DFA识别句子 一.实验目的 加深对DFA工作原理的理解. 二.实验内容 1.设计固定DFA.也就是说用if-then-else(一般用来实现字母表中只有两个字母的情况).switch(大于两 ...