精华内容
下载资源
问答
  • Zookeeper底层原理分析

    千人学习 2019-05-20 14:04:14
    ZooKeeper 是一个 分布式 的,开放源码的分布式 应用程序协调服务 ,本课程主要对ZooKeeper的底层原理进行分析,主要包括Zookeeper原理,Zookeeper是如何解决数据一致性问题以及Zookeeper领导者选举原理等内容。
  • java集合的底层原理及扩充规律

    一、集合大纲

      Java中的集合包含多种数据结构,如链表、队列、哈希表等。从类的继承结构来说,可以分为两大类,一类是继承自Collection接口,这类集合包含List、Set和Queue等集合类。另一类是继承自Map接口,这主要包含了哈希表相关的集合类

    结构图如下

     

    二、常见分类

    Collection 接口的接口 对象的集合(单列集合)
    ├——-List 接口:元素按进入先后有序保存,可重复
    │—————-├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
    │—————-├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
    │—————-└ Vector 接口实现类 数组, 同步, 线程安全
    │ ———————-└ Stack 是Vector类的实现类
    └——-Set 接口: 仅接收一次,不可重复,并做内部排序
    ├—————-└HashSet 使用hash表(数组)存储元素
    │————————└ LinkedHashSet 链表维护元素的插入次序
    └ —————-TreeSet 底层实现为二叉树,元素排好序

    Map 接口 键值对的集合 (双列集合)
    ├———Hashtable 接口实现类, 同步, 线程安全
    ├———HashMap 接口实现类 ,没有同步, 线程不安全-
    │—————–├ LinkedHashMap 双向链表和哈希表实现
    │—————–└ WeakHashMap
    ├ ——–TreeMap 红黑树对所有的key进行排序
    └———IdentifyHashMap
     

     

    三、List实现原理

      3.1 实现的接口

        常用的实现List接口的主要有ArrayList、Vector、LinkedList 三个,

      3.1.1   ArrayList

       特点:ArrayList是List使用中最常用的实现类,它的查询速度快,效率高,但增删慢,线程不安全。

       原理:ArrayList底层实现采用的数据结构是数组,并且数组默认大小为10,所以下面两种方式是等同的

      

    List list = new ArrayList();  //没有指定数组大小,使用默认值(默认大小是10)
    
    List list = new ArrayList(10);  // 指定数组大小为10,传如的参数便是数组的大小,传入为10时,跟默认值相同,所以是等同的

      扩容机制:

    jdk1.8的扩容算法:newCapacity = oldCapacity + ( oldCapacity >> 1 ) ;   // oldCapacity >> 2  移位运算,此处相当于oldCapacity除以2,但是 >> 这种写法更加高效

    jdk1.6的扩容算法:newCapacity = ( oldCapacity * 3 ) / 2 +1 ;

    参数介绍:newCapacity 是扩容后的容量大小,oldCapacity 是扩容前的大小

    查看jdk源码,移位运算需要学习下,换句话说,就是需要学习下二进制,比如:反码、补码,二进制与十进制、十六进制的相互转换。与机器交流的都是0110等,所以挺重要的。

     3.1.2  Vector

       特点:Vector的底层也是通过数组实现的,默认大小也是10。主要特点:查询快,增删慢  , 线程安全,但是效率低

       原理:创建对象与ArrayList类似,但有一点不同,它可以设置扩容是容量增长大小。

    根据Vector的三个构造器就可以很明了的理解 new Vector(); 与 new Vector(10);与 new Vector(10,0); 三个是等同的,很明了就不赘述了

      

    1.无参构造器 public Vector() {
            this(10);
        }
    
    2.传一个参数(容量大小) 容量大小即底层数组大小
    public Vector(int initialCapacity) {
            this(initialCapacity, 0);
        }
    3.传两个参数(容量大小,容量修正) 容量修正即扩容时的增加量
    public Vector(int initialCapacity, int capacityIncrement) {
            super();
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            this.elementData = new Object[initialCapacity];
            this.capacityIncrement = capacityIncrement;
        }

     

      扩容机制:

    jdk1.8的扩容算法:newCapacity = oldCapacity + ( ( capacityIncrement > 0 ) ? capacityIncrement : oldCapacity );

    jdk1.6的扩容算法:newCapacity = ( capacityIncrement > 0 ) ? ( oldCapacity + capacityIncrement ) : (  oldCapacity  * 2 );

    参数介绍:capacityIncrement 是容量修正(即容量新增大小),没有设置,默认为0    ,newCapacity 是扩容后的容量大小,oldCapacity 是扩容前的大小

    一观察,就会发现1.6与1.8的写法变化不大,但是仔细一分析,就会发现jdk1.6中有使用乘法运算,即 oldCapacity  * 2。 在jdk1.8中换成了加法运算,这是因为乘法的效率是低于加法的,这应该算法的优化。


    3.1.3 LinkedList

       特点:LinkedList底层是一个双向链表,它增删快,效率高,但是查询慢,线程不安全

       原理:构造器只有如下两种;

    1.无参构造
    public LinkedList() {
        }
    
    2.有参构造
    public LinkedList(Collection<? extends E> c) {
            this();
            addAll(c);
        }

    由于它的底层实现是链表,所以没有容量大小的定义,只有上个节点,当前节点,下个节点,每个节点都有一个上级节点和一个下级节点。

    新增元素实现代码如下

     

    private void linkFirst(E e) {
            final Node<E> f = first;
            final Node<E> newNode = new Node<>(null, e, f);
            first = newNode;
            if (f == null)
                last = newNode;
            else
                f.prev = newNode;
            size++;
            modCount++;
        }

     

    先获取头部节点元素,判断是否为null,若为null,说明原链表中没有元素,则把 first 和 last 都赋为当前新增节点。 若不为null,说明原链表中有元素,则把first赋为当前新增节点,把原头部节点f的上级节点修改为当前新增节点的下级节点

    尾部新增

    void linkLast(E e) {
            final Node<E> l = last;
            final Node<E> newNode = new Node<>(l, e, null);
            last = newNode;
            if (l == null)
                first = newNode;
            else
                l.next = newNode;
            size++;
            modCount++;
        }

    与头部新增元素类似,不再赘述。

    删除元素:

    删除元素有三种方式,删除第一元素,删除最后一个元素,删除中间部分的某个元素。   现介绍最后一个,最后一个搞懂了,前两个就懂了。

    实现代码:

    E unlink(Node<E> x) {
            // assert x != null;
            final E element = x.item;
            final Node<E> next = x.next;
            final Node<E> prev = x.prev;
    
            if (prev == null) {
                first = next;
            } else {
                prev.next = next;
                x.prev = null;
            }
    
            if (next == null) {
                last = prev;
            } else {
                next.prev = prev;
                x.next = null;
            }
    
            x.item = null;
            size--;
            modCount++;
            return element;
        }

    原理:要删除元素的当前节点x,将当前节点x的上级节点的下级节点设为当前节点x的下级节点,将当前节点x的下级节点的上级节点设为当前节点x的上级节点。

     中间考虑上级节点或下级节点为空的情况,也就是头部删除与尾部删除。

    展开全文
  • java底层原理---ArrayList源码分析

    万次阅读 2020-12-23 11:50:31
    java底层原理—ArrayList源码分析 引言 学习底层是为了更好的选择合适数据结构进行开发,这篇是为了讲解ArrayList底层原理的,同时也是总结一下自己的学习成果。 太多的文字让人看得眼花缭乱,废话不多说,上图解。 ...

    java底层原理—ArrayList源码分析

    引言

    学习底层是为了更好的选择合适数据结构进行开发,这篇是为了讲解ArrayList底层原理的,同时也是总结一下自己的学习成果。

    太多的文字让人看得眼花缭乱,废话不多说,上图解。

    这是ArrayList的属性:

    在这里插入图片描述

    一、创建ArrayList对象,初始化过程

    1. ArrayList<String> list = new ArrayList<>();
      
    2. public ArrayList() {
           //this.当前数组=默认数组
          this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
      }
      
      • 给当前存储数据的数组创建出来,创建完毕。

    二、调用add方法,添加数据过程

    1. list.add("admin");
      
    2. public boolean add(E e) {
          ensureCapacityInternal(size + 1); 
          //add方法把值"admin"传过来就是参数 e ,然后把值放进当前数组的下一个位置,但是我们这个当前数组还并没有被创建,我们就可以看看上面的方法
          elementData[size++] = e;
          return true;
      }
      
    3. 执行ensureCapacityInternal方法

      private void ensureCapacityInternal(int minCapacity) {
          if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
              minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
          }
      
          ensureExplicitCapacity(minCapacity);
      }
      
      • 判断当前数组是否是空的元素数组(一般第一次都是)
      • Math.max()方法是判断两个参数的大小,返回较大的值
      • DEFAULT_CAPACITY是默认容量(10),一般第一次都是会返回默认容量
    4. 执行ensureExplicitCapacity方法

      private void ensureExplicitCapacity(int minCapacity) {
          modCount++;
      
          // overflow-conscious code
          if (minCapacity - elementData.length > 0)
              grow(minCapacity);
      }
      
      • 方法参数是最小容量
      • 如果最小容量(将要开辟的元素空间大小) - 当前数组的长度 > 0 那么就证明空间大小不够,就会执行grow扩容方法
    5. 如果容量不够则执行grow方法

      private void grow(int minCapacity) {
          // overflow-conscious code
          int oldCapacity = elementData.length;
          int newCapacity = oldCapacity + (oldCapacity >> 1);
          if (newCapacity - minCapacity < 0)
              newCapacity = minCapacity;
          if (newCapacity - MAX_ARRAY_SIZE > 0)
              newCapacity = hugeCapacity(minCapacity);
          // minCapacity is usually close to size, so this is a win:
          elementData = Arrays.copyOf(elementData, newCapacity);
      }
      
      • 此方法先是获取到了当前数组的长度大小,然后以 oldCapacity + (oldCapacity >> 1) 的方式每次扩容1.5倍的容量
      • 然后最后将当前数组给copy替换成新容量的数组,至此扩容完毕。

    三、总结

    • ArrayList底层使用数组进行存储数据
    • ArrayList扩容机制每次扩容1.5倍
    展开全文
  • Git 底层原理

    千次阅读 2019-05-17 10:32:01
    文章目录@[toc]一.git 介绍一.git 简介二.git 历史三.集中式与分布式四.git 大致结构二..git 目录...开始从底层入手 git七.git add 命令底层原理八.git add 和 git commit 中间的操作(tree 对象的生成)九.git comm...


    这里有几篇 git 相关的博文推荐

    git 常用命令

    git 常见场景操作

    一.git 介绍

    git 底层原理的讲解中看到一篇非常非常赞的博文,此文中有很多内容摘自下面这篇博文,做了小汇总,强烈推荐

    Yelbosh 大神的 git 博文

    一.git 简介

    目前最先进的开源分布式版本控制系统,来源思想是,代码开发了多个版本,以往的思想是每个版本在电脑中 copy 一份保存,以免以后版本的代码出现问题,可以直接找之前几个版本的代码,这种就好似只有两层多子树的树形结构,git 的思想是自己电脑中不用 copy 下来每个版本,每个版本逻辑上是一个结点,每次更新到下一个版本,结点就自动往后延伸,是一个线性结构,若想恢复到之前哪个版本,也就是恢复到之前哪个结点,可以用 git 相关命令来将版本变为历史版本。git 比其他版本控制优秀在于其跟踪管理是改动而不是文件本身

    二.git 历史

    1991 年 Linus 创建了开源的 Linux,自此 Linux 不断发展成为服务器系统首选,2002 年之前各地开源 Linux 的代码贡献者通过 diff 方式把源代码发给 Linus,然后 Linus 本人通过手工方式合并代码,Linus 那时坚定反对 CSV 和 SVN,因为这些集中式版本控制系统不但速度慢而且需要联网才行,虽然有一些好用的商用版本控制系统,可惜需要付费,这与 Linus 提倡的开源精神不符合,到 2002 年 Linux 代码库已经大到 Linus 很难维护了,社区成员也对此表示不满,于是 Linus 选择使用了商业版本控制系统 BitKeeper,该系统的公司处于人道主义授权 Linux 社区免费使用该版本控制系统,可是在 2005 年的时候,Liunx 社区中的开发 Samba 的安德鲁视图破解 BitKeeper 协议,其实还有社区里的其他人,被 BitKeeper 公司发现,一气之下,公司决定收回 Linux 社区免费授权,之后 Linus 没有选择向 BitKeeper 所有的公司道歉,而是选择自己花了两周左右的时间自己用 C 写了一个分布式版本控制系统,这就是 Git,一个月的之内 Linux 系统源码已经可以被 Git 管理了,接着 Git 就迅速成为最流行的分布式版本控制系统,2008 年的时候,GitHub 上线,无数开源项目通过 Git 存储在 GitHub 中直到现今

    三.集中式与分布式

    • 集中式

      版本库放置于中央服务器,常规操作是先从中央库拉取最新版本信息,之后在自己电脑中修改,再把新版本推送给中央服务器。但需要联网才能操作,速度慢。常见有 SVN,CSV 等

    • 分布式

      每个人电脑里都有个版本库,有个人电脑坏掉,不要紧可以直接从其他人电脑复制一份过来即可,但实际使用中,很少有人在两人之间电脑推送修改,为了方便交换,通常也有个类似中央服务器的电脑,但是其仅仅是为了方便大家代码统一在此处交换

    四.git 大致结构

    git 工作区有个隐藏目录 .git,这是 git 的版本库,其中有暂存区,默认的 master 分支以及指向 master 的 HEAD 指针

    二. .git 目录结构

    img

    进入隐藏的 .git 目录之后可以看到如上图所示结构

    • 核心文件:config,objects,HEAD,index,refs 这 5 个文件夹

      • config:这里存储项目的一些配置信息,比如是否以 bare 方式初始化,remote 信息等。git remote add 添加的远程分支信息就保存在这里
      • objects:这里保存 git 对象,git 中的一些操作以及文件都会以 git 对象形式保存在这里,git 对象分为 BLOBtreecommit 三种类型,比如 git commit 就是 commit 类型变量,各个版本之间通过版本树进行组织,比如 HEAD 指向某个 commit 对象,而 commit 对象又会指向几个 BLOB 对象或者 tree 对象。objects 文件夹中有很多子文件夹,其中 git 对象保存在以其 sha-1 值的前两位为子文件夹后 38 位为文件名的文件中,此外 git 为了节省存储对象所占用的磁盘空间,会定期对 git 对象进行压缩和打包,其中 pack 文件夹用于存放打包压缩的对象,info 文件夹用于从打包的文件中查找 git 对象
      • HEAD:该文件指明了本地的分支结果,如本地分支是 master,那么 HEAD 就指向 master,分支在 refs 中就会表示成refs:refs/heads/master
      • index:该文件 stage 暂存区信息,也就是 add 之后保存到的区域,内容包括它指向的文件的时间戳,文件名,sha1 值等
      • refs:该文件夹保存了指向分支的提交对象也就是 commit 对象的指针,其中的 heads 文件夹存储了本地每一个分支最近一次提交的 sha-1 值,即 commit 对象的 sha-1 值,每个分支一个文件;remotes 文件夹则记录你最后一次和远程仓库的通信,也就是说这里会记录最后一次每个分支推送到远端的值;tags 文件夹存储分支别名
    • sha-1 算法介绍说明:其实 sha-1 算法在两千零几年中国已经被攻破,有人就提出 git 的安全性问题,由于 git 是 linus 在此算法还没被攻破时候创建,linus 现在不以为然,因为他认为没有人会发这么大经理偷偷篡改他人代码树,他认为即使是使用老掉牙的 md5 都是可行,未来 git 中的 sha-1 算法还是有可能被替换,参见 http://www.itxm.cn/post/14240.html

    • 其他文件

      • hooks:这里主要定义了客户端或服务端的 hook 脚本,这些脚本用于在特定命令和操作之前、之后进行特殊处理
      • description:仅供 GitWeb 程序使用
      • logs:记录了本地仓库和远程仓库的每一个分支的提交信息,即所有 commit 对象都会被记录在此,这个文件夹内容应该是我们查看最频繁的,如 git log
      • info:其中保存了一份不希望在 .gitignore 文件中管理的忽略的全局可执行文件
      • COMMIT_EDITMSG:记录了最后一次提交时的注释信息

      我们可以看到 .git 目录中的文件会因为几次提交就成倍的增长,因为其中要生成对象

    三.git add 与 git commit 简单原理

    平时我们在工作区修改文件,没有 add 操作之前我们通过 git status 命令可以查看到有文件被 modified 而且是 not staged,这个时候修改的文件仅仅是在工作区内,之后通过 git add 操作,被修改的文件从工作区提交到暂存区(驿站)也就是 stage 里,再通过 commit 操作把暂存区 stage 中所有的内容全部提交到当前的分支结构当中,即

    工作区(文件修改后 add 前)→ stage 暂存区(add 后 commit 前)→ 本地分支结构(本地 commit 后)

    这样的一种三层结构

    四.创建与合并分支简单原理

    分支被合并可以被 -d 删除,分支没有被合并后 -d 删除会出错,需要 -D 强制删除

    • master分支
      一个分支就是一条时间线,默认有一条时间线master,其中有个指针master,这个master指针是指向提交的,还有个HEAD指针,这个指针是指向当前的指向提交的指针的指针,也就是指向当前分支的指针。每次提交,master指针都会向后移一位,这样不断去提交,master分支就会越来越长。如下图1:
      图1
    • 创建dev新分支
      若创建新分支,如dev分支,git会新建一个dev指针,与master指针功能一样。先是指向和master同样的位置,当checkout切换到dev分支时候,HEAD指针就指向了dev指针了,当在dev分支下提交,master指针不动。如下图2和图3:
      图2
      图3
    • 分支的合并
      分支合并,操作很简单,若将dev分支内容合到master上,就是将master的指针指向dev指针指向的位置即可,如图4:
      图4
    • 删除dev分支
      删除分支就是讲dev指针删除掉,如图5:
      图5

    五.git rebase 简单原理

    把一个分支的修改整合到另一个分支的办法有两种,第一种就是 git merge 操作,另一种就是 git rebase 操作,该命令原理就是回到两个分支最近的共同祖先,根据当前分支(也就是要进行衍合的分支experiment)后续的历次提交对象(这里只有一个 C3),生成一系列文件补丁,然后以基底分支(也就是主干分支master)最后一个提交对象(C4)为新的出发点,逐个应用之前准备好的补丁文件,最后会生成一个新的合并提交对象(C3’),从而改写 experiment 的提交历史,使它成为 master 分支的直接下游。如下图所示:

    img

    在rebase的过程中,也许会出现冲突。在这种情况,Git会停止rebase并会让你去解决冲突;在解决完冲突后,用git add命令去更新这些内容的索引, 然后,你无需执行git-commit,只要执行git rebase –continue,这样git会继续应用(apply)余下的补丁。如果要舍弃本次衍合,只需要git rebase --abort即可。切记,一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行rebase操作

    六.开始从底层入手 git

    git 命令分为 procelain 和 plumbing 命令,前者是基于后者来实现的,若把 git 看成一个操作系统那么 plumbing 命令更像是一个 shell 命令,而 procelain 命令就像是通过利用 shell 命令编写的一系列系统功能或工具,下面会重点讲解 plumbing 命令以及 git 对象

    • plumbing 命令

      git 本质上一套内容寻址(content-addressable)文件系统,寻址无非就是查找,这样的寻址系统对于完成过 linux 系统构建的 linus 肯定不算难事。寻址无非就是查找,git 采用的是 HashTable 的方式进行查找,即 git 是通过简单键值对形式实现内容寻址,键就是文件(头+内容)的哈希值(前面 .git 目录结构中也讲了采用 sha-1 加密方式,40位,点击这里跳转到前面),值是经过压缩后的文件内容,plumbing 操作实际上是 40 位的哈希值来进行压缩包的查找

      git 对象存储方式表示式:

      Key = sha1(file_header + file_content) 
      Value = zlib(file_content)
      
    • git 对象

      前面也讲了 git 对象有 BLOB(binary large object),tree,commit 三种,点击这里跳转到前面,BLOB 存储几乎所有的文件类型,BLOB 大的二进制表示的对象,和数据库中 BLOB 类型,常用来存储数据库中图片视频是一样的;tree 是用来组织 BLOB 对象的一种数据类型,你完全可以理解成二叉树中的树结点,只不过 git 中的可是“多叉树”,commit 对象表示每一次的提交操作,是由 tree 对象衍生出来,通过每次提交,这样所有的 commit 操作便可连成一个提交树,一个 branch 实际上就是这个大树中的一个子树

    七.git add 命令底层原理

    stage 暂存区又叫索引库,因为暂存区信息内容保存在 .git 目录结构的 index 文件夹,git add 就是把工作区 modified 文件添加到 stage 暂存区,那么 git add 底层是如何通过 plumbing 命令完成文件索引操作的?

    • git add 对应着的两个基本 plumbing 命令

      git hash-object #获取指定文件的key,如果带上-w选项,则会将该对象的value进行存储
      git update-index #将指定的object加入索引库,需要带上—add选项
      

      先用第一个命令将需要暂存的文件进行 key-value 转化成 git 对象,进行存储(.git 中的 objects 文件夹中),拿到这些文件的 key,然后通过第二条命令将这些对象加入到 stage 暂存区中暂存(.git 中的 index 文件夹中)

      若还要根据 git 对象的 key 来查看文件信息,需要如下 plumbing 命令

      git cat-file –p/-t key #获取指定key的对象信息,-p打印详细信息,-t打印对象的类型
      

      也就是说 git add 命令本质上就是把工作区修改的文件变成 git 对象并且拿到 sha-1 值放在 objects 文件夹中,然后连同 key 一起转存到另一个 index 文件夹中(暂存区)。实际上 index 库记录是从项目初始化起,每次 add 在这里都会把文件的索引信息(时间戳和大小)更新,也就是说这个库只会越来越大

    八.git add 和 git commit 中间的操作(tree 对象的生成)

    在这里插入图片描述
    git 中所有内容以 BLOB 或者 tree 对象形式存储。如果把 git 看做 unix 系统,那么 tree 对象就好似文件系统中的目录,BLOB 对象就好似 inodes 或文件内容。我们平时操作的 add 和 commit 操作似乎没有涉及到这个 tree 对象的生成,其实有的,tree 对象只是 add 和 commit 中间的一个缓冲步骤,因为 commit 对象要根据 tree 对象来创建,下面创建 tree 对象:

    git write-tree #根据索引库中的信息创建tree对象
    

    这条命令的作用是返回生成 tree 对象的 key 值

    整个工作目录对应一个 tree 对象,并且其下每一个子文件夹都是一个 tree 对象,每次的 commit 对象都对应着根 tree 对象,任何一个对象的改变都会导致其上层所有 tree 对象的重新存储

    img

    九.git commit 命令底层原理

    index 暂存区包括了项目仓库中所有的文件,commit 对象所对应的 tree 对象永远都是工作区根目录所对应的 tree 对象,也就是说每次 commit 之后,commit 对象会依附在这个工作区的 tree 对象上。要是仔细观察目录结构的话,可以发现对象文件夹,子文件夹对应着一个 tree 结点,文件的话对应着一个 BLOB 结点,创建 commit 对象的命令:

    git commit-tree key –p key2 #根据tree对象创建commit对象,-p表示前继commit对象
    

    该命令实现的操作类似于数据结构树中增加结点的操作,在这个命令中若是第一次提交则不需要指定 -p 选项指明父节点


    下一篇

    git 常用命令

    git 常见场景操作

    展开全文
  • TreeSet底层原理

    千次阅读 2020-02-19 21:15:45
    1 前言 本人使用的是jdk1.8版本。 2 List集合继承结构 3 底层实现 ...TreeSet的底层是TreeMap,添加的数据存入了map的key的位置,而value则...具体参考:TreeMap的底层原理。 public class TreeSet<E> ext...

    1 前言

    本人使用的是jdk1.8版本。

    2 List集合继承结构

    3 底层实现

    TreeSet的底层是TreeMap,添加的数据存入了map的key的位置,而value则固定是PRESENT。TreeSet中的元素是有序且不重复的,因为TreeMap中的key是有序且不重复的。具体参考:TreeMap的底层原理

    public class TreeSet<E> extends AbstractSet<E>
        implements NavigableSet<E>, Cloneable, java.io.Serializable{
    
        private transient NavigableMap<E,Object> m;
    
        private static final Object PRESENT = new Object();
    
        public TreeSet() {
            this(new TreeMap<E,Object>());
        }
    }

    4 方法

    4.1 add()

    就是调用TreeMap的put方法。

        public boolean add(E e) {
            return m.put(e, PRESENT)==null;
        }

    4.2 remove()

    就是调用TreeMap的remove方法。

        public boolean remove(Object o) {
            return m.remove(o)==PRESENT;
        }

     

    展开全文
  • Hadoop底层原理

    千次阅读 2019-12-12 08:32:01
    Hadoop底层原理 1.客户端执行hdfs fs put 本地文件系统中的文件路径 hdfs文件系统中的目录路径:hdfs fs put ./a.txt / 发送上传请求给namenode。 2.namenode根据元数据中的文件系统目录树 检测是否存在“该指定的...
  • MySQL MVCC底层原理详解

    千次阅读 2020-07-25 05:46:44
    MySQL MVCC底层原理详解
  • volatile的底层原理与实现

    万次阅读 2020-10-24 13:01:55
    volatile的底层原理 volatile的两个作用: 可见性 防止指令重排序 计算机的组成 下图是一个典型的计算机结构图,计算机的组成主要包括CPU、存储器(内存)、IO(输入输出设备)。 存储器的层次结构 下图是计算机...
  • Python底层原理

    千次阅读 2019-03-15 09:49:44
    Python 底层原理知识 实际开发过程中,了解底层原理是有助于解决现实中遇到的问题的。现将了解到的几点重要的整理下,感谢原博主“吖水的程序路”的整理! 1.Python是如何进行内存管理的? 答:从三个方面来说,一对象...
  • HBase底层原理

    千次阅读 2019-12-13 20:37:57
    HBase底层原理 系统架构: Client: 1 包含访问hbase的接口,client维护着一些cache来加快对hbase的访问,比如regione的位置信息。 Zookeeper: 1、zk的选举机制 保证任何时候,集群中只有一个master 2、 实时监控...
  • String底层原理

    千次阅读 2018-12-11 13:24:08
    我问他 String的底层原理是什么 他思考了一会说不知道。 那么我们在面试的时候有可能会遇到类似的问题,怎么去解答,肯定是要去看String的源码的 public final class String implements java.io.Serializable, ...
  • React底层原理

    2020-07-03 23:35:06
    React底层原理 1.react合成事件 react在事件处理上具有如下特点: 1.几乎所有的事件代理(delegate)到document,达到性能优化的目的 2.对于每种类型的事件,拥有统一的分发函数dispatchEvent 3.事件对象(event)是合成...
  • JSP底层原理

    2019-01-15 21:43:39
    文章目录jsp底层原理新的方式就的生成动态内容的方式1)`&amp;lt;% 代码 %&amp;gt;`2)`&amp;lt;%= 表达式%&amp;gt;`3)`&amp;lt;%! 代码 %&amp;gt;`4)注释 `&amp;lt;%-- 注释内容 --%...
  • Spring Cloud底层原理

    2018-11-08 08:18:01
    [Spring Cloud底层原理!(转)] Spring Cloud底层原理 【转自今日头条】
  • iOS底层原理视频

    千次阅读 热门讨论 2018-11-11 22:40:40
    iOS底层原理班mj视频找了好久终于找到了 链接: https://pan.baidu.com/s/1S5S3QbTdDtFODfjwpKkRPQ 提取码: zf8q
  • 线程池底层原理

    千次阅读 2019-06-24 12:12:49
    线程池底层原理 大厂面试题: 1、请你谈谈对volatile的理解? 2、CAS你知道吗? 3、原子类AtomicInteger的ABA问题谈谈?原子更新引用知道吗? 4、我们都知道ArrayList是线程不安全的,请编码写一个不安全的案例...
  • objc4 源码相关 iOS-底层原理 01:源码探索的三种方式 iOS-底层原理 02:alloc & init & new 源码分析 iOS-底层原理 03:objc4-781 源码编译 & 调试
  • Celery底层原理

    2019-01-27 09:43:00
    Celery的底层原理(透彻一些)? celery是基于python实现的一个异步任务的调度工具,同时还是一个任务队列,主要用于处理耗时的任务。架构如下: celery架构由三个模块组成:消息中间件(message ...
  • Selenium底层原理

    千次阅读 2018-10-24 13:54:27
    也算做了比较久的UI自动化测试了,今天突然有人问我:Selenium的底层原理是什么?我还真的回答不上来,最近一直在思考,如何成为一个更好的测试工程师,我想这就是其中一个原因吧,使用了那么长时间的工具,也没有去...
  • 深入剖析Spring Boot底层原理深入剖析Spring Boot底层原理深入剖析Spring Boot底层原理深入剖析Spring Boot底层原理深入剖析Spring Boot底层原理深入剖析Spring Boot底层原理 转载于:...
  • spring的ioc底层原理

    2019-08-12 10:49:24
    Spring的ioc操作 1.把对象的创建交给spring进行管理 ...1.ioc底层原理使用技术 (1)xml配置文件 (2)dom4j解析xml (3)工厂设计模式 (4)反射 2.分析ioc是实现原理: a. ioc底层原理 ...
  • Synchornize的底层原理

    2020-01-21 17:29:33
    2.底层原理 2.1 底层指令 monitorenter // 逻辑代码对应的指令 monitorexit 每个对象都有一个关联的monitor,比如一个对象实例就有一个monitor,一个类的Class对象也有一个monitor,如果要对这个对象加锁,那么必须...
  • LinkedList底层原理实现

    千次阅读 2019-03-26 19:57:50
    LinkedList底层原理实现 1.底层 1.LinkedList的底层是通过链表来实现的。 2.链表的单元 链表的单元是节点(Node) 链表是由多个节点构成,每个节点都包含三个部分,头部指向上一个节点,中部指向该节点,尾部...
  • Vue中的底层原理

    2020-12-10 16:41:00
    数据驱动 当数据发生改变时,视图也会进行更新,这叫做数据驱动,也就是数据驱动视图 深入响应式原理 数据模型仅仅是普通的 JavaScript 对象...综上: 三者都是应用了同一个底层原理,这个底层原理由es5的 Object.d...
  • Celery的底层原理

    千次阅读 2019-07-16 20:37:34
    一、Celery的底层原理 1、什么是Celery Celery是基于Python实现的一个异步任务调度工具,同时也是一个任务队列。 2、Celery的架构组成 Celery架构由三个模块组成:消息中间件(message broker),任务执行单元...
  • Kingfisher框架底层原理

    2019-06-25 09:46:04
    Kingfisher框架底层原理一, Kingfisher框架概述二,Kingfisher框架流程图 一, Kingfisher框架概述 Kingfisher 是一个异步下载、缓存网络图片的轻量级纯swift库, 作者王巍受著名三方库SDWebImage激励所写,在swift...
  • 多态的底层原理

    2019-01-22 17:37:49
    在上一篇博客中https://blog.csdn.net/Jochebed666/article/details/86596585说明了多态,那么多态的底层原理是什么呢??? 他与虚函数有没有关联??? 虚函数的工作原理 C++规定了虚函数的行为,但将实现方法...
  • AES底层原理实现

    千次阅读 2018-03-19 22:50:25
    这一次,我来了解一下AES算法的底层原理。 小明:老师,上一次你介绍了AES算法的基本概念,这一次可不可以讲讲AES的底层加密解密原理? 老师:没问题,让我们先来回顾一下AES算法整体的关系图。 上一篇我们已经...
  • dubbo的底层原理

    万次阅读 多人点赞 2017-12-03 14:01:37
    RMI协议的Invoker转为Exporter发生在RmiProtocol类的export方法,他通过Spring或Dubbo或JDK来实现服务,通讯细节由JDK底层来实现。 服务消费者消费一个服务的详细过程 上图是服务消费的主过程: 首先...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,390
精华内容 17,756
关键字:

底层原理