当前位置: 首页 > wzjs >正文

公司网站突然打不开了微信企业公众号开发平台

公司网站突然打不开了,微信企业公众号开发平台,建设网站的知识,网站设计与管理的软件今天尝试刨一下TreeMap的祖坟。 底层结构对比 先来看一下与HashMap、LinkedHashMap和TreeMap的对比,同时就当是复习一下: HashMap使用数组存储数据,并使用单向链表结构存储hash冲突数据,同一个冲突桶中数据量大的时候&#xff…

今天尝试刨一下TreeMap的祖坟。

底层结构对比

先来看一下与HashMap、LinkedHashMap和TreeMap的对比,同时就当是复习一下:

  1. HashMap使用数组存储数据,并使用单向链表结构存储hash冲突数据,同一个冲突桶中数据量大的时候(默认超过8)则使用红黑树存储冲突数据。
  2. LinkedHashMap使用数组+双向链表存储数据,冲突数据存储方式同HashMap。
  3. TreeMap使用红黑树存储数据,注意是直接使用红黑树,不使用table数组。

关于排序特性

  1. HashMap无顺序,不能保持顺序。
  2. LinkedHashMap能保持写入的顺序,遍历的时候可以按照写入顺序获取数据。
  3. TreeMap是有序的Map,自动按照key值排序存储,遍历时获取到的是有序数据。

需要注意LinkedHashMap和TreeMap在顺序方面的区别,LinkedHashMap只能保持写入顺序,从“排序”的角度讲,他实际是无序的。

只有TreeMap是可以实现自动排序的。

TreeMap按照什么排序?

TreeMap底层支持两种排序方式:

  1. TreeMap对象实例化时传入comparator对象。
  2. key值对象实现Comparable接口。

如果以上两点都不能满足的话,向TreeMap对象put数据的时候会抛出运行时异常。

比如TreeMap<String,Object>,由于String实现了Comparable接口,所以是没有问题的。

但是如果自定义的对象,没有实现Comparable接口,同时在TreeMap实例化的时候没有设置comparator对象,则该TreeMap对象实际是不可用的。

TreeMap是否可以存储null?

指的是,是否可以存储key为空的数据?我们知道HashMap是可以支持唯一一个null对象的。

很多人都说不可以,但是我觉得有条件可以,但是没做测试(因为感觉则个问题其实有点扯)。

条件是实例化TreeMap对象的时候指定comparator对象,同时,该comparator对象的compare方法可以支持null。

研究TreeMap的put源码,也可以发现对以上说法的支持:

Comparator<? super K> cpr = comparator;if (cpr != null) {do {parent = t;cmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}else {if (key == null)throw new NullPointerException();...省略若干代码

可以发现如果有comparator的话,put方法不会立即抛出异常。但是如果comparator对象的compare方法不能支持null的话,一样会抛出异常。

put方法

由于TreeMap支持自动排序,所以put方法会检查是否满足规则。

不满足排序规则,抛出异常。

否则,按照红黑树算法规则要求,创建红黑树,存储数据。

所以这里就涉及到一个重要的数据结构:红黑树。

二叉树BST & 平衡二叉树AVL

红黑树是树结构的一种,是比二叉树和平衡二叉树更加复杂的一种数据结构。所以我们先从简单的入手,了解一下二叉树。

树结构其实是实现了子排序的一种数据结构,我们说到的树结构一般指的是二叉树、也叫二叉搜索树(BST - Binary Search Tree),定义:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

二叉搜索树的插入、搜索操作所花的时间都和树的高度成正比。因此,如果共有n个元素,那么平均每次操作需要O(logn)的时间。

二叉搜索树的特性并不能保证他是平衡的,也就是说,极端情况下,一颗二叉搜索树从根节点开始,只有左节点、没有右节点(比如一直按照从大到小或者相反顺序插入二叉树),这种情况下,二叉树就蜕变成了链表,查询时间复杂度就会下降为O(n)。

改善二叉树这一缺点的经典数据结构是平衡二叉树AVL(Adelson-Velsky and Landis Tree,以两位发明者命名)。平衡二叉树的特性:

1.本身首先是一棵二叉搜索树。
2.带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。

一颗平衡二叉树在新节点插入之后可能会失衡,包括以下四种场景:

左左失衡LL

插入的数据在左侧不平衡树的左侧,这种情况下需要进行右旋操作再次平衡:
在这里插入图片描述
我们需要记住一个概念:平衡二叉树失衡之后通过旋转动作使得它再次平衡的处理,只是针对失衡的子树、不需要对整个树进行操作。比如上图新的节点1加入之后,导致pivot节点7一侧的树失衡,我们需要处理的是包含pivot节点的root节点的左侧树这一部分子树,右侧节点18下即使有再多的节点,也不需要处理。

右旋操作的实质是:以pivot节点7为支点做顺时针旋转,旋转之后7变为自己原来父节点的父节点、7的左节点不变,7的右节点变为7原来的父节点的左节点。

右右失衡RR

插入的节点在右侧不平衡树的右侧,这种情况下需要左旋:
在这里插入图片描述
左旋操作的实质是:以pivot节点18为支点做逆时针旋转,旋转之后18变为自己原来父节点的父节点、18的右节点不变,18的左节点变为18原来的父节点的右节点。

左右失衡LR

插入的新节点在左侧不平衡树的右侧。先左旋再右旋
在这里插入图片描述

右左失衡LR

插入的节点在右侧不平衡树的左侧,先右旋再左旋:
在这里插入图片描述
平衡二叉树具有:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1 这一特性,这一严格条件会导致每次插入新节点之后总会大概率破坏平衡、从而必须要通过上述的旋转操作使其再次达到平衡,旋转操作会影响数据插入的效率。

红黑树可以解决这一问题。

红黑树

红黑树是一种带颜色(节点是红色或者黑色)的平衡二叉树,具有以下特性:
性质1. 结点是红色或黑色。
性质2. 根结点是黑色。
性质3. 所有叶子都是黑色。(叶子是NIL结点)
性质4. 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)
性质5. 从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。

红黑树新加入节点的颜色默认为黑色,因为根据红黑树性质4,每个红色节点的两个子节点都是黑色。所以,新加入节点如果是黑色的话,可以检查其父节点如果是红色的话,可以自动满足性质4从而减少再平衡操作、提高数据加入的效率。这一点可以通过TreeMap的put方法源码得到验证:

public V put(K key, V value) {Entry<K,V> t = root;if (t == null) {compare(key, key); // type (and possibly null) checkroot = new Entry<>(key, value, null);size = 1;modCount++;return null;}int cmp;Entry<K,V> parent;// split comparator and comparable pathsComparator<? super K> cpr = comparator;if (cpr != null) {do {parent = t;cmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}else {if (key == null)throw new NullPointerException();@SuppressWarnings("unchecked")Comparable<? super K> k = (Comparable<? super K>) key;do {parent = t;cmp = k.compareTo(t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}Entry<K,V> e = new Entry<>(key, value, parent);if (cmp < 0)parent.left = e;elseparent.right = e;fixAfterInsertion(e);size++;modCount++;return null;}

put方法前半部分逻辑比较简单,为新节点找到合适的位置加入,之后会调用fixAfterInsertion检查是否破坏了红黑树的规则从而需要执行再平衡操作:

private void fixAfterInsertion(Entry<K,V> x) {x.color = RED;while (x != null && x != root && x.parent.color == RED) {if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {Entry<K,V> y = rightOf(parentOf(parentOf(x)));if (colorOf(y) == RED) {setColor(parentOf(x), BLACK);setColor(y, BLACK);setColor(parentOf(parentOf(x)), RED);x = parentOf(parentOf(x));} else {if (x == rightOf(parentOf(x))) {x = parentOf(x);rotateLeft(x);}setColor(parentOf(x), BLACK);setColor(parentOf(parentOf(x)), RED);rotateRight(parentOf(parentOf(x)));}} else {Entry<K,V> y = leftOf(parentOf(parentOf(x)));if (colorOf(y) == RED) {setColor(parentOf(x), BLACK);setColor(y, BLACK);setColor(parentOf(parentOf(x)), RED);x = parentOf(parentOf(x));} else {if (x == leftOf(parentOf(x))) {x = parentOf(x);rotateRight(x);}setColor(parentOf(x), BLACK);setColor(parentOf(parentOf(x)), RED);rotateLeft(parentOf(parentOf(x)));}}}root.color = BLACK;}

fixAfterInsertion方法首先判断其父节点是红色的话,则不做任何操作。

get方法

根据红黑树查找算法查找并返回数据,红黑树是平衡二叉树,查询时间复杂度为O(log(n))。

key遍历

比如调用TreeMap.keySet方法,采用遍历二叉树算法,按照从小到大的顺序返回所有key值组成的循环器。

我该使用哪一个?

需要用到Map的时候,到底该使用哪一个的问题:

  1. 我只需要一个存储数据的容器,没有具体要求的话,用HashMap。
  2. 存储数据后,有按照存储顺序获取数据的需求,采用LinkedHashMap。
  3. 希望存储数据的同时,帮助实现自动排序,采用TreeMap。

性能的问题,其实几乎不需要考虑,不过我们还是需要知道:

  1. HashMap和LinkedHashMap查询速度快,理想情况下时间复杂度几乎是O(1)。
  2. HashMap写入速度最快,LinkedHashMap写入速度与HashMap几乎相同,TreeMap写入速度最慢(理论上,实际数据量小的情况下未必慢)。
  3. 遍历速度相差无几,理论上HashMap会慢一点,因为需要遍历空桶。

并发问题尚待研究,但是我们清楚地知道,以上三种均不具备线程安全性。

好梦!


文章转载自:

http://SAOXjHmU.rdkqt.cn
http://hvxcVxvh.rdkqt.cn
http://sNgUHDrb.rdkqt.cn
http://PlHtop6f.rdkqt.cn
http://3xMR2Cwe.rdkqt.cn
http://1KF9tPGC.rdkqt.cn
http://ReSvaFCM.rdkqt.cn
http://rNd1Lt5n.rdkqt.cn
http://6lDJQNUw.rdkqt.cn
http://Lcs03iGh.rdkqt.cn
http://M8VLiqXe.rdkqt.cn
http://4UpdnkyX.rdkqt.cn
http://lr3lcEHe.rdkqt.cn
http://mNWvfyzm.rdkqt.cn
http://9vr15bY0.rdkqt.cn
http://g285r6bx.rdkqt.cn
http://3JNDGHxK.rdkqt.cn
http://a9gNyZGD.rdkqt.cn
http://xIfdYdkZ.rdkqt.cn
http://S1DXhKdd.rdkqt.cn
http://DYgQ5gK7.rdkqt.cn
http://fiVI1Fmm.rdkqt.cn
http://oNI9kHfv.rdkqt.cn
http://efqkyAC7.rdkqt.cn
http://0PUExqnX.rdkqt.cn
http://zUuPrqFo.rdkqt.cn
http://36jvIGTy.rdkqt.cn
http://TaEuL7UJ.rdkqt.cn
http://3p0KnzCs.rdkqt.cn
http://UmVFg6k6.rdkqt.cn
http://www.dtcms.com/wzjs/699738.html

相关文章:

  • 网站有些什么内容app开发流程详细
  • 网站开发信息建站宝盒做的网站
  • 建筑网站设置工资单人换了怎么换怎么做好网站运营
  • 网站开发需要花费秦皇岛和平大街网站建设
  • 东莞手机微信网站百度一下百度首页登录
  • wap 网站 手机网站功能及报价
  • 中石油技术开发公司网站电商网站开发案例
  • 建网站要注意的细节常州做网站企业
  • 山东高端网站建设服务商售后管理系统软件
  • 百度关键词网站怎么做dw制作一个环保网站模板下载
  • 长沙建设品牌网站app开发公司哪家好 上海
  • 网站团队组成wordpress 镜像域名
  • 汝州市城乡建设局网站郑州网站建设讯息
  • 做视频广告在哪个网站能够赚钱界面设计ui
  • 网站建设的流程推广方案为网站做推广
  • 网站制作的流程包括哪些飞沐视觉北京网站建设公司
  • 哪种网站开发简单广州品牌策划公司排行
  • 郑州二七区做网站公司网站开发有哪些
  • 制作网页的网站费用属于资本性支出吗个人做网站备案多少钱
  • 网站上线前要做哪些准备wordpress 文章列表插件
  • 如何做网站seo韩小培网站开发形式
  • 权威网站设计宣传信息网网站规划书
  • 中小企业网站开发韵茵福建百益建设集团有限公司网站
  • 网页设计与网站建设过程洛谷网站中小玉文具怎么做
  • 织梦能不能做门户网站影响网站用户体验
  • 优客逸家网站源码免费网站在线制作
  • 用C语言做网站登录界面重庆市住房和城乡建设网站
  • 网站建设字体我的世界做mc壁纸的网站
  • 潭州教育网站开发南京网站设计开发
  • 都匀网站.asp 网站