ope电竞下载_ope体育在线投注_ope体育app下载中文版
ope电竞下载

甘草,天津地图-ope电竞下载_ope体育在线投注_ope体育app下载中文版

admin admin ⋅ 2019-05-21 07:09:30

第1部分 TreeMap介绍

TreeMap 简介

TreeMap 是一个有序的key-value调集,它是经过红黑树完成的。

TreeMap 承继于AbstractMap,所以它是一个Map,即一个ke苹果床戏y-value调集。

TreeMap 完成了NavigableMap接口,意味着它支撑一系列的导航办法。比方回来有序的key调集。

TreeMap 完成了Cloneable接口周子瑜美貌韩国点评,意味着它能被克隆

TreeMap 完成了java.io.Serializable接口,意味着它支撑序列化

TreeMap依据红黑树(Red-Black tree)完成。该映射依据其键的天然次序进行排序,或许依据创立映射时供给的 Comparator 进行排序,具体取决于运用的结构办法。

TreeMap的根本操作 containsKey、get、put 和 remove 的时刻复杂度是 log(n) 。

别的,TreeMap是非同步的。 它的iterator 办法回来的迭代器是fail-fastl的。

TreeMap的结构函数

// 默许结构函数。运用该结构函数,TreeMap中的元素依照天然排序进行摆放。
TreeMap()
// 创立的TreeMap包含Map
TreeMap(Map copyFrom)
// 指定Tree的比较器
TreeMap(Comparator comparator)
// 创立的TreeSet包含copyFrom
TreeMap(SortedMap copyFrom)

TreeMap的API

Entry ceilingEntry(K key)
K ceilingKey(K key)
void clear()
Object clone()
Comparator comparator()
boolean containsKey(Object key)
NavigableSet descendingKeySet()
NavigableMap descendingMap()
Set> entrySet()
Entry firstEntry()
K firstKey()
Entry floorEntry(K key)
K floorKey(K key)
V get(Object key)
NavigableMap headMap(K to, boolean inclusive)
SortedMap headMap(K toExclusive)
Entry higherEntry(K key)
K higherKey(K key)
boolean isEmpty(乱乱)
Set keySet()
Entry lastEntry()
K lastKey()
Entry lowerEntry(K key)
K lowerKey(K key)
NavigableSet navigableKeyS驱房有术et()
Entry pollFirstEntry()
Entry pollLastEntry()
V put(K key, V value)
V remove(Object key)
int size()
SortedMap subMap(K fromInclusive, K toExclusive)
NavigableMap subMap(K from, boolean fromInclusive, K to, boolean toInclusive)
NavigableMap tailMap(K from, boolean inclusive)
SortedMap tailMap(K fromInclusive)

第2部分 TreeMap数据结构

TreeMap的承继联系

java.lang.Object
↳ java.util.AbstractMap
↳ java.util.TreeMap
public class TreeMap
extends AbstractMap
implements NavigableMap, Cloneable, java.io.Serializable {}

TreeMap与Map联系如下图:

从图中能够看出:

(01) TreeMap完成承继于AbstractMap,并且完成了NavigableMap接口。

(02) TreeMap的实质是R-B Tree(红黑树),它包含几个重要的成员变量: root, size, comparator。

root 是红黑数的根节点。它是Entry类型,Entry是红黑数的节点,它包含了红黑数的6个根本组成成分:key(键)、value(值)、left(左孩子)、right(右孩子)、parent(父节点)、color(色彩)。Entry节点依据key进行排序,Entry节点包含的内容为value。

红黑数排序时,依据Entry中的key进行排序;Entry中的key比较巨细是依据比较器comp神州虫新浪博客arator来进行判别的。

size是红黑数中节点的个数。

关于红黑数的具体算法,请参阅"红黑树(一) 原理和算法具体介绍"。

第3部分 TreeMap源码解析(依据JDK1.6.0_45)

为了更了解TreeMap的原理,下面临TreeMap源码代码作出剖析。咱们先给出源码内容,后边再对源码进行具体阐明,当然,源码内容中也包含了具体的代码注释。读者阅览的时分,主张先看后边的阐明,先树立一个全体形象;之后再阅览源码。

View Code

阐明:

在具体介绍TreeMap的代码之前,咱们先树立一个全体概念。

TreeMap是经过红黑树完成的,TreeMap存储的是key-value键值对,TreeMap的排序是依据对key的排序。

TreeMap供给了操作“key”、“key-value”、“value”等办法,也供给了对TreeMap这颗树进行全体操作的办法,如获取子树、反向树。

后边的阐明内容分为几部分,

首要,介绍TreeMap的中心,即红黑树相关部分

然后,介绍TreeMap的首要函数

再次,介绍TreeMap完成的几个接口

终究,弥补介绍TreeMap的其它内容

TreeMap实质上是一颗红黑树。要完全了解TreeMap,主张读者先了解红黑树。关于红黑树的原理,能够参阅:红黑树(一) 原理和算法具体介绍

第3.1部分 TreeMap的红黑树相关内容

TreeMap中于红黑树相关的首要函数有:

1 数据结构

1.1 红黑树的节点色彩--赤色

private static final boolean RED = false;

1.2 红黑树的节点色彩--黑色

private static final boolean BLACK = true;

1.3 “红黑树的节点”对应的类。

static final class Entry implements Map.Entry { ... }

Entry包含了6个部分内容:key(键)、value(值)、left(左孩子)、right(右孩子)、parent(父节点)、color(色彩)

Entry节点依据key进行排序,Entry节点包含的内容为value。

2 相关操作

2.1 左旋

private void rotateLeft(Entry p) { ... }

2.2 右旋

private void rotateRight(Ent亿馍通ry p) { ... }

2.3 刺进操作

public V put(K key, V value) { ... }

2.4 刺进批改操作

红黑树履行刺进操作之后,要履行“刺进批改操作”。

意图是:保红黑树在进行刺进节点之后,仍然是一颗红黑树

private void fixAfterInsertion(Entry x) { ... }

2.5 删去操作

private void deleteEntry(Entry p) { ... }

2.6 删去批改操作

红黑树履行删去之后,要履行“删去批改操作”。

意图是确保:红黑树删去节点之后,仍然是一颗红黑树

private void fixAfterDeletion(Entry x) { ... }

关于红黑树部分,这儿首要是指出了TreeMap中那些是红黑树的首要相关内容。具体的红黑树相关操作API,这儿没有具体阐明,因为它们仅仅只是将算法翻译成代码。读者能够参阅“红黑树(一) 原理和算法具体介绍”进行了解。

第3.2部分 TreeMap的结构函数

1 默许结构函数

运用默许结构函数结构TreeMap时,运用java的默许的比较器比较Key的巨细,从而对TreeMap进行排序。

public TreeMap() {
comparator = null;
}

2 带比较器的结构函数

public TreeMap(Comparator comparator) {
this.comparator = com甘草,天津地图-ope电竞下载_ope体育在线投注_ope体育app下载中文版parator;
}

3 带Map的结构函数,Map会成为TreeMap的子集

public TreeMap(Map m) {
comparator = null;
putAll(m);
}

该结构函数会调用p怜情utAll()将m中的一切元素增加到T少女暑假就医回忆录reeMap中。putAll()源码如下:

public void putAll(Map m) {
for (Map.Entry e : m.entrySet())
put(e.getKey(), e.getValue());
}

从中,咱们能够看出putAll()便是将m中的key-value逐一的增加到TreeMap中

4 带SortedMap的结构函数,SortedMap会成为TreeMap的子集

public TreeMap(SortedMap m) {
comparator = m.comparator();
try {
buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
} catch (java.io.IOException cannotHappen) {
} catch (ClassNotFoundException cannotHappen) {
}
}

该结构函数不同于上一个结构函数,在上一个结构函数中传入的参数是Map,Map不是有序的,所以要逐一增加。

而该结构函数的参数是SortedMap是一个有序的Map,咱们经过buildFromSorted()来创立对应的Map。

buildFromSorted涉及到的代码如下:

View Code

要了解buildFromSorted,要点阐明以下几点:

榜首,buildFromSorted是经过递归将SortedMap中的元素逐一相关

第二,buildFromSorted回来middle节点(中心节点)作为root。

第三,buildFromSorted增加到红黑树中时,只将level == redLevel的节点设为赤色。第level级节点,实际上是buildFromSorted转换成红黑树后的最底端(假定根节点在最上方)的节点;只将红黑树最底端的阶段上色为赤色,其他都是黑色。

第3.3部分 TreeMap的Entry相关函数

TreeMap的 firstEntry()、 lastEntry()、 lowerEntry()、 higherEntry()、 floorEntry()、 ceilingEntry()、 pollFirstEntry() 、 pollLastEntry() 原理都是相似的;下面以firstEntry()来进行具体阐明

咱们先看看firstEntry()和getFirstEntry()的代码:

public Map.Entry firstEntry() {
return exportEntry(getFirstEntry());
}
final Entry getFirstEntry() {
Entry p = root;
if (p != null)
while (p.left != null)
p = p.left;
return p;
}

从中,咱们能够看出 firstEntry() 和 getFirstEntry() 都是用于获取榜首个节点。

可是,firstEntry() 是对外接口; getFirstEntry() 是内部接口。并且,firstEntry() 是经过 getFirstEntry() 来完成的。那为什么外界不能直接调用 getFirstEntry(),而需求多此一举的调用 firstEntry() 呢?

先通知咱们原因,再进行具体阐明。这么做的意图是:避免用户修正回来的Entry。getFirstEntry()回来的Entry是能够被修正的,可是经过firstEntry()回来的Entry不能被修正,只能够读取Entry的key值和value值。下面咱们看看到底是怎么完成的。

(01) getFirstEntry()回来的是Entry节点,而Entry是红黑树的节点,它的源码如下:

// 回来“红黑树的榜首个节点”
final Entry getFirstEntry() {
Entry p = root;
if (p != null)
while (p.left != null)
p = p.left;
return p;
}

从中,咱们能够调用Entry的getKey()、getValue()来获取key和value值,以及调用setValue()来修正value的值。

(02) firstEntry()回来的是exportEntry(getFirstEntry())。下面咱们看看exportEntry()干了些什么?

static  Map.Entry exportEntry(TreeMap.Entry e) {
return e == null? null :
new AbstractMap.SimpleImmutableEntry(e);
}

实际上,exportEntry() 是新建一个AbstractMap.SimpleImmutableEntry类型的目标,并回来。

SimpleImmutableEntry的完成在AbstractMap.java中,下面咱们看看AbstractMap.SimpleImmutableEntry是怎么完成的,代码如下:

View Code

从中,咱们能够看出SimpleImmutableEntry实际上是简化的key-value节点。

它只供给了getKey()、getValue()办法类获取节点的值;但不能修正value的值,因为调用 setValue() 会抛出反常UnsupportedOperationException();

再回到咱们之前的问题:那为什么外界不能直接调用 getFirstEntry(),而需求多此一举的调用 firstEntry() 呢?

现在咱们明晰的了解到:

(01) firstEntry()是对外接口,而getFirstEntry()是内部接口。

(02) 对firstEntry()回来的Entry目标只能进行getKey()、getValue()等读取操作;而对getFirstEntry()回来的目标除了能够进行读取操作之后,还能够经过setValue()修正值。

第3.4部分 TreeMap的key相关函数

TreeMap的firstKey()、las掘地重工tKey()、lowerKey()、higherKey()、floorKey()低端人口、ceilingKey()原理都是相似的;下面以ceilingKey()来进行具体阐明

ceilingKey(K key)的效果是“回来大于/等于key的最小的键值对所对应的KEY,没有的话回来null”,它的代码如下:

public K ceilingKey(K key) {
return keyOrNull(getCeilingEntry(key));
}

ceilingKey()是经过getCeilingEntry()完成的。keyOrNull()的代码很简略,它是获取节点的key,没有的话,回来null。

sta巴兹公式tic  K keyOrNull(TreeMap.Entry e) {
return e == null? null : e.key;
}

getCeilingEntry(K key)的效果是“获取TreeMap中大于/等于key的最小的节点,若不存在(即TreeMap中一切节点的键都比key大),就回来甘草,天津地图-ope电竞下载_ope体育在线投注_ope体育app下载中文版null”。它的完成代码如下:

View Code

第3.5部分 TreeMap的values()函数

values() 回来“TreeMa甘草,天津地图-ope电竞下载_ope体育在线投注_ope体育app下载中文版p中值的调集”

values()的完成代码如下:

public Collection values() {
Collection vs = values;
return (vs != null) ? vs : (v甘草,天津地图-ope电竞下载_ope体育在线投注_ope体育app下载中文版alues = new Values());
}

阐明:从中,咱们能够发现values()是经过 new Values() 来完成 “回来TreeMap中值的调集”。

那么Values()是怎么完成的呢? 没错!因为回来的是值的调集,那么Values()必定回来一个调集;而Values()正好是调集类Value的结构函数。Values承继于AbstractCollection,它的代码如下:

View Code

阐明:从中,咱们能够知道Values类便是一个调集。而 AbstractCollection 完成了除 size() 和 iterator() 之外的其它函数,因而只需求在Values类中完成这两个函数即可。

size() 的完成十分简略,Values调集中元素的个数=该TreeMap的元素个数。(TreeMap每一个元素都有一个值嘛!)

iterator() 则回来一个迭代器,用于遍历Values。下面,咱们一同能够看看iterator()的完成:

public Iterator iterator() {
return new ValueIterator(getFirstEntry());
}

阐明: iterator() 是经过ValueIterator() 回来迭代器的,ValueIterator是一个类。代码如下:

final class ValueIterator extends PrivateEntryIterator {
ValueIterator(Entry first) {
super(first);
}
public V next() {
return nextEntry().value;
}
}

阐明:ValueIterator的代码很简略,它的首要完成应该在它的父类PrivateEntryIterator中。下面咱们一同看看PrivateEntryIterator的代码:

View Code

阐明:PrivateEntryIterator是一个笼统类,它的完成很简略,只只完成了Iterator的remove()和hasNext()接口,没有完成next()接口。

而咱们在ValueIterator中现已完成的next()接口。

至此,咱们就了解了iterator()的完好完成了。

第3.6部分 TreeMap的entrySet()函数

entrySet() 回来“键值对调集”。望文生义,它回来的是一个调集,调集的元素是“键值对”。

下面,咱们看看它是怎么完成的?entrySet() 的完成代码如下:

public Set> entrySet() {
EntrySet es = entrySet;
return (es != null) ? es : (entrySet = new EntrySet());
}

阐明:entrySet()回来的是一个EntrySet目标。

下面咱们看看EntrySet的代码:

View Code

阐明:

EntrySet是“TreeMap的一切键值对组成的调集”,并且它单位是单个“键值对”。

EntrySet是一个调集,它承继于AbstractSet。而AbstractSet完成了除size() 和 iterator() 之外的其它函数,因而,咱们要点了解一下EntrySet的size() 和 iterator() 函数

size() 的完成十分简略,Abst尹传柱ractSet调集中元素的个数=该TreeMap的元素个数。

iterator() 则回来一个迭代器,用于遍历AbstractSet。从上面的甘草,天津地图-ope电竞下载_ope体育在线投注_ope体育app下载中文版源码中,咱们能够发现iterator() 是经过EntryIterator完成的;下面咱们看看EntryIterator的源码:

final class EntryIterator extends PrivateEntryIterator> {
EntryIterator(Entry first) {
super(first);
}
public Map.Entry next() {
return nextEntry();
}
}

阐明:和Values类相同,EntryIterator也承继于PrivateEntryIterator类。

第3.7部分 TreeMap完成的Cloneable接口

TreeMap蔡盛坤完成了Cloneable接口,即完成了clone()办法。

clone()办法的效果很简略,便是克隆一个TreeMap目标并回来。

View Code

第3.8部分 TreeMap完成的Serializable接口

TreeMap完成java.io.Serializable,别离完成了串行读取、写入功用。

串行写入函数是writeObject(),它的效果是将TreeMap的“容量,一切的Entry”都写入到输出流中。

而串行读取函数是readObject(),它的效果是将TreeMap的“容量、一切的Entry”顺次读出。

readObject() 和 writeObject() 正好是一对,经过它们,我能完成TreeMap的串行传输。

View Code

提到这儿,就趁便说一下“关键字transient”的效果

transient是Java言语的关键字,它被用来表明一个域不是该目标串行化的一部分。

Java的serialization供给了一种耐久化目标实例的机制。当耐久化目标时,可能有一个特别的目标数据成员,咱们不想用serialization机制来保存它。为了在一个特定目标的一个域上封闭serialization,能够在这个域前加上关键字transient。

当一个目标被串行化的时分,transient型变量的值不包含在串行化的表明中,然而非transient型的变量是被包含进去的。

第3.9部分 TreeMap完成的NavigableMap接口

firstKey()、lastKey()、lowerKey()、higherKey()、ceilingKey()、floorKey();

firstEntry()、 lastEntry()、 lowerEntry()、 higherEntry()、 floorEntry()、 ceilingEntry()、 pollFirstEntry() 、 pollLastEntry();

上面现已解说过这些API了,下面临其它的API进行阐明。

1 反向TreeMap

descendingMap() 的效果是回来当时TreeMap的反向的TreeMap。所谓反向,便是排序次序和原始的次序相反。

咱们现已知道TreeMap是一颗红黑树,而红黑树是有序的。

TreeMap的排序方法是经过比较器,在创立TreeMap的时分,若指定了比较器,则运用该比较器;不然,就运用Java的默许比较器。

而获取TreeMap的反向TreeMap的原理便是将比较器反向即可!

了解了descendingMap()的反向原理之后,再解说一下descendingMap()的代码。

// 获取TreeMap的降序Map
public NavigableMap descendingMap() {
NavigableMap km = descendingMap;
return (km != null) ? km :
(descendingMap = new DescendingSubMap(this,
true, null, true,
true, null, true));
}

从中,咱们看出descendingMap()实际上是甘草,天津地图-ope电竞下载_ope体育在线投注_ope体育app下载中文版回来DescendingSubMap类的目标。下面,看看DescendingSubMap的源码:

View Code

从中,咱们看出DescendingSubMap是降序的SubMap,它的完成机制是将“SubMap的比较器回转”。

它承继于NavigableSubMap。而NavigableSubMap是一个承继于AbstractMap的笼统类;它包含2个子类——"(升序)AscendingSubMap"和"(降序)DescendingSubMap"。NavigableSubMap为它的两个子类完成了许多公共API。

下面看看NavigableSubMap的源码。

View Code

NavigableSubMap源码许多,但不难了解;读者能够经过源码和注释进行了解。

其实,读完NavigableSubMap的源码后,咱们能够得出它的中心思维是:它是一个笼统调集类,为2个子类——"(升序)AscendingSubMap"和"(降序)DescendingSubMap"而服务;因为NavigableSubMap完成了许多公共API。它的终究意图是完成下面的一系列函数:

headMap(K toKey, boolean inclusive) 
headMap(K toKey)
subMap(K fromKey, K toKey)
subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclus甘草,天津地图-ope电竞下载_ope体育在线投注_ope体育app下载中文版ive)
tailMap(K fromKey)
tailMap(K fromKey, boolean inclusive)
navigableKeySet()
descendingKeySet()

第3.10部分 TreeMap其它函数

1 次序遍历和逆序遍历

TreeMap的次序遍历和逆序遍历原理十分简略。

因为TreeMap中的元素是从小到大的次序摆放的。因而,次序遍历,便是从榜首个元素开端,逐一向后遍历;而倒序遍历则恰恰相反,它是从终究一个元素开端,逐一往前遍历。

咱们能够经过 keyIterator() 和 descendingKeyIterator()来阐明!

keyIterator()的效果是回来次序的KEY的调集,

descendingKeyIterator()的效果是回来逆序的KEY的调集。

keyIterat女人体油画or() 的代码如下:

Iterator keyIterator() {
return new KeyIterator(getFirstEntry());
}

阐明:从中咱们能够看出keyIterator() 是回来以“榜首个节点(getFirstEntry)” 为其实元素的迭代器。

KeyIterator的代码如下:

final class KeyIterator extends PrivateEntryIterator {
KeyIterator(Entry first) 刘光基{
super(first);
}
public K next() {
return nextEntry().key;
}
}

阐明:KeyIterator承继于PrivateEntryIterator。当咱们经过next()不断获取下一个元素的时分,便是履行的次序遍历了。

descendingKeyIterator()的代码如下:

Iterator descendingKeyIterator() {
return new DescendingKeyIterator(getLastEntry());
}

阐明:从中咱们能够看出descendingKeyIterator() 是回来以“终究一个节点(getLastEntry)” 为其实元素的迭代器。

再看看DescendingKeyIterator的代码:

final class DescendingKeyIterator extends PrivateEntryIterator {
DescendingKeyIterator(Entry first) {
super(first悦楽之胤);
}
public K next() {
return prevEntry().key;
}
}

阐明:DescendingKeyIterator承继于PrivateEntryIterator。当咱们经过next()不断获取下一个元素的时分,实际上调用的是prevEntry()获取的上一个节点,这样它实际上履行的是逆序遍历了。

至此,TreeMap的相关内容就悉数介绍结束了。若有过错或疏忽的当地,欢迎纠正!

第4部分 TreeMap遍历方法

4.1 遍历TreeMap的键值对

榜首步:依据entrySet()获取TreeMap的“键值对”的Set调集。

第二步:经过Iterator迭代器遍历“榜首步”得到的调集。

// 假定map是TreeMap目标
// map中的key是String类型,value是Integer类型
Integer integ = null;
Iterator ite美观的道德r = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
// 获取key
key = (String)entry.getKey();
// 获取value
integ = (Integer)entry.getValue();
}

4.2 遍历TreeMap的键

榜首步:依据keySet()获取TreeMap的“键”的Set调集。

第二步:经过Iterator迭代器遍历“榜首步”得到的调集。

// 假定map是TreeMap目标
// map中的key是String类型,value是Integer类型
String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
// 获取key
key = (String)iter.next();
// 依据key,获取value
integ = (Integer)map.get(key);
}

4.3 遍历TreeMap的值

榜首步:依据value()获取TreeMap的“值”的调集。

第二步:经过Iterator迭代器遍历“榜首步”得到的调集。

// 假定map是TreeMap目标
// map中的key残隼是String类型,value是Integer类型
Integer value = null;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}

TreeMap遍历测验程序如下:

View Code

第5部分 TreeMap示例

下面经过实例来学习怎么运用TreeMap

View Code

运转成果

{one=8, three=4, two=2}
next : one - 8
next : three - 4
next : two - 2
size: 3
contains key two : true9c8922
contains key five : false
contains value 0 : false
tmap:{one=8, two=2}
tmap is empty

相关新闻

admin

admin

TA太懒了...暂时没有任何简介

精彩新闻