一.TreeMap成员变量
- //Comparator比较器接口,接口里面只有两个方法int compare(T o1, T o2);boolean equals(Object obj);
- private final Comparator<? super K> comparator;
- //根节点
- private transient Entry<K,V> root = null;
- private transient int size = 0;
- private transient int modCount = 0;
二.TreeMap的Entry对象
- static final class Entry<K,V> implements Map.Entry<K,V> {
- //构成树的三个属性left,left,parent
- K key;
- V value;
- Entry<K,V> left = null;
- Entry<K,V> right = null;
- Entry<K,V> parent;
- boolean color = BLACK; //该节点红色还是黑色
- }
三.构造函数
- //默认构造函数时comparator为空,则插入到TreeMap里面的key必须实现Comparator接口
- public TreeMap() {
- comparator = null;
- }
- //用户指定Comparator
- public TreeMap(Comparator<? super K> comparator) {
- this.comparator = comparator;
- }
四.取数据
- public V get(Object key) {
- Entry<K,V> p = getEntry(key);
- return (p==null ? null : p.value);
- }
- final Entry<K,V> getEntry(Object key) {
- //如果用户指定了Comparable,用指定的
- if (comparator != null)
- return getEntryUsingComparator(key);
- //get操作key不能为空
- if (key == null)
- throw new NullPointerException();
- //如果用户没指定Comparable,用key作为Comparable
- Comparable<? super K> k = (Comparable<? super K>) key;
- Entry<K,V> p = root;
- //以根节点当前节点开始遍历搜索
- while (p != null) {
- //拿被检索的节点的值和当前节点的值比较
- int cmp = k.compareTo(p.key);
- //如果被检索的节点的值更小,则以当前节点的左子节点作为新的当前节点。
- if (cmp < 0)
- p = p.left;
- //如果被检索的节点的值更大,则以当前节点的右子节点作为新的当前节点。
- else if (cmp > 0)
- p = p.right;
- //被检索的节点的值和当前节点的值相等,则是我们需要的节点
- else
- return p;
- }
- //找不到返回null
- return null;
- }
- //和上面逻辑一样
- final Entry<K,V> getEntryUsingComparator(Object key) {
- K k = (K) key;
- Comparator<? super K> cpr = comparator;
- if (cpr != null) {
- Entry<K,V> p = root;
- while (p != null) {
- int cmp = cpr.compare(k, p.key);
- if (cmp < 0)
- p = p.left;
- else if (cmp > 0)
- p = p.right;
- else
- return p;
- }
- }
- return null;
- }
五.存数据
- //返回被新节点覆盖的节点的值,不存在被覆盖的节点返回null
- public V put(K key, V value) {
- Entry<K,V> t = root;
- if (t == null) {
- // TBD:
- // 5045147: (coll) Adding null to an empty TreeSet should
- // throw NullPointerException
- //
- // compare(key, key); // type check
- //第一次插入节点
- root = new Entry<K,V>(key, value, null);
- size = 1;
- modCount++;
- return null;
- }
- int cmp;
- Entry<K,V> parent;
- // split comparator and comparable paths
- Comparator<? super K> cpr = comparator;
- //用指定的Comparator
- if (cpr != null) {
- //以根节点当前节点t开始搜索,拿被添加的节点的值和当前节点的值比较。
- do {
- //刚开始parent=t
- parent = t;
- cmp = cpr.compare(key, t.key);
- //如果被添加的节点的值更小,则以当前节点的左子节点作为新的当前节点,此时t=pL
- if (cmp < 0)
- t = t.left;
- //如果被添加的节点的值更大,则以当前节点的右子节点作为新的当前节点,此时t=pR
- else if (cmp > 0)
- t = t.right;
- //如果相等,直接覆盖
- else
- return t.setValue(value);
- } while (t != null); //直到新的当前节点为空
- }
- else {
- //put操作key不能为空
- if (key == null)
- throw new NullPointerException();
- //用key作为Comparator,下同
- 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;
- else
- return t.setValue(value);
- } while (t != null);
- }
- //生成一个新节点,父亲为parent
- Entry<K,V> e = new Entry<K,V>(key, value, parent);
- //根据最后一次比较的cmp确定pL位置存放e还是pR存放e
- if (cmp < 0)
- parent.left = e;
- else
- parent.right = e;
- //修复红黑树
- fixAfterInsertion(e);
- size++;
- modCount++;
- //插入一个新节点时返回null
- return null;
- }
六.删数据
- public V remove(Object key) {
- //先找到节点,getEntry(key)key不能为空,所以remove方法key不能为空
- Entry<K,V> p = getEntry(key);
- if (p == null)
- return null;
- //保留一个节点的值
- V oldValue = p.value;
- //删除节点
- deleteEntry(p);
- return oldValue;
- }
- private void deleteEntry(Entry<K,V> p) {
- modCount++;
- size--;
- //若被删除节点 p 的左、右子树均非空
- if (p.left != null && p.right != null) {
- //得到p节点的中序后继s
- Entry<K,V> s = successor (p);
- //用s替代p
- p.key = s.key;
- p.value = s.value;
- p = s;
- }
- //如果p节点的左节点存在,replacement代表左节点,否则代表右节点
- Entry<K,V> replacement = (p.left != null ? p.left : p.right);
- if (replacement != null) {
- replacement.parent = p.parent;
- // 如果 p 没有父节点,则 replacemment 变成父节点
- if (p.parent == null)
- root = replacement;
- // 如果 p 节点是其父节点的左子节点
- else if (p == p.parent.left)
- p.parent.left = replacement;
- // 如果 p 节点是其父节点的右子节点
- else
- p.parent.right = replacement;
- p.left = p.right = p.parent = null;
- // Fix replacement
- if (p.color == BLACK)
- // 修复红黑树
- fixAfterDeletion(replacement);
- // 如果 p 节点没有父节点
- } else if (p.parent == null) { // return if we are the only node.
- root = null;
- } else { // No children. Use self as phantom replacement and unlink.
- if (p.color == BLACK)
- // 修复红黑树
- fixAfterDeletion(p);
- if (p.parent != null) {
- // 如果 p 是其父节点的左子节点
- if (p == p.parent.left)
- p.parent.left = null;
- // 如果 p 是其父节点的右子节点
- else if (p == p.parent.right)
- p.parent.right = null;
- p.parent = null;
- }
- }
- }
七.containsKey containsValue方法
- public boolean containsKey(Object key) {
- return getEntry(key) != null;
- }
- //按中序遍历节点的顺序,把节点和指定value比较
- public boolean containsValue(Object value) {
- for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
- if (valEquals(value, e.value))
- return true;
- return false;
- }
- static final class Entry<K,V> implements Map.Entry<K,V> {
- //找到最小的节点
- final Entry<K,V> getFirstEntry() {
- Entry<K,V> p = root;
- if (p != null)
- while (p.left != null)
- p = p.left;
- return p;
- }
- //找到最大的节点
- final Entry<K,V> getLastEntry() {
- Entry<K,V> p = root;
- if (p != null)
- while (p.right != null)
- p = p.right;
- return p;
- }
- }
- //找到指定节点的后继节点
- static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
- if (t == null)
- return null;
- //如果t有右子数
- else if (t.right != null) {
- Entry<K,V> p = t.right;
- //tRL不为空,tRL就是t的直接后继;tRLL不为空,tRLL就是t的直接后继......
- while (p.left != null)
- p = p.left;
- return p;
- //如果t只有左子数
- } else {
- //如果t=pL,直接返回p
- //如果t=pR,返回p.parent
- Entry<K,V> p = t.parent;
- Entry<K,V> ch = t;
- while (p != null && ch == p.right) {
- ch = p;
- p = p.parent;
- }
- return p;
- }
- }
- //找到指定节点的前驱节点
- static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
- if (t == null)
- return null;
- //如果t有左子数
- else if (t.left != null) {
- Entry<K,V> p = t.left;
- //tLR不为空,tLR就是t的直接后继;tLRR不为空,tLRR就是t的直接后继......
- while (p.right != null)
- p = p.right;
- return p;
- } else {
- //如果t=pR,直接返回p
- //如果t=pL,返回p.parent
- Entry<K,V> p = t.parent;
- Entry<K,V> ch = t;
- while (p != null && ch == p.left) {
- ch = p;
- p = p.parent;
- }
- return p;
- }
- }
八.fixAfterInsertion方法
- // 插入节点后修复红黑树
- private void fixAfterInsertion(Entry<K,V> x)
- {
- x.color = RED;
- // 直到 x 节点的父节点不是根,且 x 的父节点不是红色
- while (x != null && x != root
- && x.parent.color == RED)
- {
- // 如果 x 的父节点是其父节点的左子节点
- if (parentOf(x) == leftOf(parentOf(parentOf(x))))
- {
- // 获取 x 的父节点的兄弟节点
- Entry<K,V> y = rightOf(parentOf(parentOf(x)));
- // 如果 x 的父节点的兄弟节点是红色
- if (colorOf(y) == RED)
- {
- // 将 x 的父节点设为黑色
- setColor(parentOf(x), BLACK);
- // 将 x 的父节点的兄弟节点设为黑色
- setColor(y, BLACK);
- // 将 x 的父节点的父节点设为红色
- setColor(parentOf(parentOf(x)), RED);
- x = parentOf(parentOf(x));
- }
- // 如果 x 的父节点的兄弟节点是黑色
- else
- {
- // 如果 x 是其父节点的右子节点
- if (x == rightOf(parentOf(x)))
- {
- // 将 x 的父节点设为 x
- x = parentOf(x);
- rotateLeft(x);
- }
- // 把 x 的父节点设为黑色
- setColor(parentOf(x), BLACK);
- // 把 x 的父节点的父节点设为红色
- setColor(parentOf(parentOf(x)), RED);
- rotateRight(parentOf(parentOf(x)));
- }
- }
- // 如果 x 的父节点是其父节点的右子节点
- else
- {
- // 获取 x 的父节点的兄弟节点
- Entry<K,V> y = leftOf(parentOf(parentOf(x)));
- // 如果 x 的父节点的兄弟节点是红色
- if (colorOf(y) == RED)
- {
- // 将 x 的父节点设为黑色。
- setColor(parentOf(x), BLACK);
- // 将 x 的父节点的兄弟节点设为黑色
- setColor(y, BLACK);
- // 将 x 的父节点的父节点设为红色
- setColor(parentOf(parentOf(x)), RED);
- // 将 x 设为 x 的父节点的节点
- x = parentOf(parentOf(x));
- }
- // 如果 x 的父节点的兄弟节点是黑色
- else
- {
- // 如果 x 是其父节点的左子节点
- if (x == leftOf(parentOf(x)))
- {
- // 将 x 的父节点设为 x
- x = parentOf(x);
- rotateRight(x);
- }
- // 把 x 的父节点设为黑色
- setColor(parentOf(x), BLACK);
- // 把 x 的父节点的父节点设为红色
- setColor(parentOf(parentOf(x)), RED);
- rotateLeft(parentOf(parentOf(x)));
- }
- }
- }
- // 将根节点设为黑色
- root.color = BLACK;
- }
九.fixAfterDeletion方法
- // 删除节点后修复红黑树
- private void fixAfterDeletion(Entry<K,V> x)
- {
- // 直到 x 不是根节点,且 x 的颜色是黑色
- while (x != root && colorOf(x) == BLACK)
- {
- // 如果 x 是其父节点的左子节点
- if (x == leftOf(parentOf(x)))
- {
- // 获取 x 节点的兄弟节点
- Entry<K,V> sib = rightOf(parentOf(x));
- // 如果 sib 节点是红色
- if (colorOf(sib) == RED)
- {
- // 将 sib 节点设为黑色
- setColor(sib, BLACK);
- // 将 x 的父节点设为红色
- setColor(parentOf(x), RED);
- rotateLeft(parentOf(x));
- // 再次将 sib 设为 x 的父节点的右子节点
- sib = rightOf(parentOf(x));
- }
- // 如果 sib 的两个子节点都是黑色
- if (colorOf(leftOf(sib)) == BLACK
- && colorOf(rightOf(sib)) == BLACK)
- {
- // 将 sib 设为红色
- setColor(sib, RED);
- // 让 x 等于 x 的父节点
- x = parentOf(x);
- }
- else
- {
- // 如果 sib 的只有右子节点是黑色
- if (colorOf(rightOf(sib)) == BLACK)
- {
- // 将 sib 的左子节点也设为黑色
- setColor(leftOf(sib), BLACK);
- // 将 sib 设为红色
- setColor(sib, RED);
- rotateRight(sib);
- sib = rightOf(parentOf(x));
- }
- // 设置 sib 的颜色与 x 的父节点的颜色相同
- setColor(sib, colorOf(parentOf(x)));
- // 将 x 的父节点设为黑色
- setColor(parentOf(x), BLACK);
- // 将 sib 的右子节点设为黑色
- setColor(rightOf(sib), BLACK);
- rotateLeft(parentOf(x));
- x = root;
- }
- }
- // 如果 x 是其父节点的右子节点
- else
- {
- // 获取 x 节点的兄弟节点
- Entry<K,V> sib = leftOf(parentOf(x));
- // 如果 sib 的颜色是红色
- if (colorOf(sib) == RED)
- {
- // 将 sib 的颜色设为黑色
- setColor(sib, BLACK);
- // 将 sib 的父节点设为红色
- setColor(parentOf(x), RED);
- rotateRight(parentOf(x));
- sib = leftOf(parentOf(x));
- }
- // 如果 sib 的两个子节点都是黑色
- if (colorOf(rightOf(sib)) == BLACK
- && colorOf(leftOf(sib)) == BLACK)
- {
- // 将 sib 设为红色
- setColor(sib, RED);
- // 让 x 等于 x 的父节点
- x = parentOf(x);
- }
- else
- {
- // 如果 sib 只有左子节点是黑色
- if (colorOf(leftOf(sib)) == BLACK)
- {
- // 将 sib 的右子节点也设为黑色
- setColor(rightOf(sib), BLACK);
- // 将 sib 设为红色
- setColor(sib, RED);
- rotateLeft(sib);
- sib = leftOf(parentOf(x));
- }
- // 将 sib 的颜色设为与 x 的父节点颜色相同
- setColor(sib, colorOf(parentOf(x)));
- // 将 x 的父节点设为黑色
- setColor(parentOf(x), BLACK);
- // 将 sib 的左子节点设为黑色
- setColor(leftOf(sib), BLACK);
- rotateRight(parentOf(x));
- x = root;
- }
- }
- }
- setColor(x, BLACK);
- }
十.迭代
- /**
- * Base class for TreeMap Iterators
- */
- abstract class PrivateEntryIterator<T> implements Iterator<T> {
- Entry<K,V> next;
- Entry<K,V> lastReturned;
- int expectedModCount;
- PrivateEntryIterator(Entry<K,V> first) {
- expectedModCount = modCount;
- lastReturned = null;
- next = first;
- }
- //后继迭代
- final Entry<K,V> nextEntry() {
- Entry<K,V> e = next;
- if (e == null)
- throw new NoSuchElementException();
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- next = successor(e);
- lastReturned = e;
- return e;
- }
- //前驱迭代
- final Entry<K,V> prevEntry() {
- Entry<K,V> e = next;
- if (e == null)
- throw new NoSuchElementException();
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- next = predecessor(e);
- lastReturned = e;
- return e;
- }
- }
相关推荐
### Java集合容器知识点详解 #### 一、集合容器概述 - **定义**:集合容器是Java平台提供的标准组件,主要用于存储对象。...通过本篇文章的学习,希望读者能够更好地理解和应用Java集合容器,提升编程技能。
总的来说,TreeMap源码的学习可以帮助我们理解红黑树的数据结构和其实现原理,这对于优化和调试涉及大量数据的操作至关重要。同时,掌握TreeMap的内部机制也能提升我们在实际开发中使用Java集合框架的能力。
- 简单易用:通过直观的用户界面调整Flex容器及子元素的属性。 - 实时预览:支持即时查看布局变化,方便调试与优化。 - 文档详尽:提供了详细的文档说明,便于学习与参考。 #### 三、Flexlib - **网址**:...
- 高级容器:TreeSet、TreeMap、LinkedHashMap,它们保证了特定的排序规则。 - CopyOnWriteArrayList和CopyOnWriteArraySet,适用于读多写少的场景。 3. **IO流**: - 字节流(InputStream/OutputStream)和字符...
2. **Tomcat**:不仅可以解析 JSP 动态页面,还可以作为 Servlet 容器。 3. **JBoss**:是一个全面的应用服务器,可以部署各种 Java 应用。 #### 五、GET 与 POST 区别 1. **数据提交方式**: - **GET**:通过 ...
### 五、线程安全的集合类 - **Vector**:线程安全的ArrayList实现。 - **HashTable**:线程安全的HashMap实现。 - **ConcurrentHashMap**:线程安全的哈希表实现,性能更优。 以上总结了Java集合的基础概念、特点...
- **HashMap**、**LinkedHashMap**、**TreeMap**:映射表的不同实现。 - **HashSet**、**LinkedHashSet**、**TreeSet**:集合的不同实现。 **1.2.2 变量类型** - **基本类型**:如int、long等。 - **引用类型**:...
在Java学习笔记中,我们重点关注Java的IO(输入/输出)操作、常用类库以及集合框架。 1. **Java IO**: - **File类**:提供了文件和目录的基本操作,如创建、删除、重命名等。 - **RandomAccessFile**:支持对...
- **TreeMap**:基于红黑树实现,键自然排序。 ### 高并发编程(JUC包) #### 1. 线程安全 - **synchronized关键字**:确保多个线程互斥访问共享资源。 - **volatile关键字**:保证变量在多线程环境下的可见性和...
Java.util 源码分析 Java.util 包是 Java 核心库的重要组成部分,它包含了许多用于日常编程的工具类和接口,如集合框架、日期时间处理、随机数生成、事件处理等。深入理解这个包的源码对于提升Java开发者的技能至关...
本文将详细分析四种常用的`Map`实现类:`HashMap`, `LinkedHashMap`, `TreeMap`以及`HashTable`之间的区别。 #### 1. HashMap `HashMap`是一种基于哈希表实现的`Map`接口,提供了一个非同步的、允许使用`null`键和...
- **Map**:存储key-value对的对象,如HashMap、TreeMap和Hashtable,它们不继承Collection接口,因为它们的元素不是单一对象,而是键值对。 2. **Collection与Collections的区别**: - **Collection**:是集合类...
在Java编程中,Map接口是用于存储键值对的数据结构,而Java提供了多种Map的实现,包括TreeMap、HashMap和ConcurrentSkipListMap。本文主要比较了这三种Map的性能,尤其是在插入和查找操作上的效率。 1. **TreeMap**...
- **TreeMap**:基于红黑树实现,按键排序。 ### 3. Java中接口与抽象类的异同 - **相同点**: - 都不能实例化。 - 都可以包含抽象方法。 - 都可以实现代码复用。 - **不同点**: - **接口**: - 定义行为...
- **选择性学习要点:** - EJB容器管理下的实体Bean和会话Bean。 - JSP的指令、脚本元素、动作元素等。 - Servlet生命周期及其配置。 **1.2 异常处理** - **异常分类:** - **编译时异常(checked exception)...
- **Map的应用:** 掌握HashMap、TreeMap等不同类型的Map容器。 ##### 1.9 JDBC - **JDBC简介:** 介绍JDBC的基本概念及其在Java应用程序中的作用。 - **JDBC的体系结构:** 了解JDBC驱动程序的工作原理。 - **连接...
- **TreeMap**:基于红黑树实现的键值对集合。 以上就是关于JAVA基础的一些重要知识点介绍。掌握这些基础知识对于学习更高级的JAVA技术和框架非常关键。希望通过对这些知识点的学习,可以帮助初学者建立起牢固的...
- **Map**: HashMap、LinkedHashMap和TreeMap的工作机制。 - **泛型**: 限制集合元素类型,提高代码安全性和可读性。 4. **并发编程** - **线程**: 创建线程的方式,如Thread类和Runnable接口。 - **同步机制**...
#### 五、综合案例分析 - **ATM自助系统**:通过模拟实际场景,如账户管理、存款取款等功能,加深对Java基础知识的理解。 以上知识点涵盖了《Java培训班教程》中涉及的核心内容和技术要点,旨在帮助学习者快速掌握...