- 浏览: 661838 次
- 性别:
- 来自: 深圳
博客专栏
-
Hadoop学习
浏览量:251950
文章分类
最新评论
-
leibnitz:
请问,你知道在FSEdigLog#loadFSEdits()时 ...
Hadoop学习二十三:Hadoop-Hdfs FSDirectory 源码 -
jiaqing_blog:
七.等待队列(本是Object里的方法,但影响了线程)noti ...
多线程总结二:线程的状态转换 -
haaarySun:
虽然是三年前的帖子,但还是想回复博主,logger是继承了ca ...
Java日志学习三:Apache Log4j源码浅析 -
annmi_cai:
好好学习,天天向上!
Hadoop学习四:Hadoop-Hdfs NameNode -
emotionText:
楼主你好!我运行报错SLF4J: Class path con ...
Hadoop学习三十:Win7 Eclipse调试Centos Hadoop2.2-Mapreduce
一.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; } }
发表评论
-
容器学习十一:Queue & Stack
2012-10-19 13:31 1143一.Queue类图 整个Queue结构 ... -
容器学习十:Vector & ArrayList & LinkedList
2012-10-15 14:57 1228一.前言 以前对Vector这对象很陌生,用的少,对象 ... -
容器学习九:Comparable & Comparator
2012-10-15 11:26 1653一.前言 本系 ... -
容器学习八:LinkedList源码分析
2012-09-01 12:22 1241一.概述 LinkedList继 ... -
容器学习七:ArrayList源码分析
2012-08-31 17:00 1658一.成员变量 // 在Ab ... -
容器学习六:HashSet & LinkedHashSet & TreeSet源码分析
2012-08-30 22:38 1873一.概述 Set是通过Map来支持的,Set ... -
容器学习四:TreeMap源码分析-排序二叉树和红黑树
2012-08-30 14:55 1633一.排序二叉树 排序二叉树是一种特殊结构的二叉树, ... -
容器学习三:LinkedHashMap源码分析
2012-08-26 21:50 5942一.LinkedHashMap的存储结构 Link ... -
容器学习二:Hashtable源码分析
2012-08-25 13:43 1750一.前言 HashMap和Hashtable大部分算 ... -
容器学习一:HashMap源码分析
2012-08-24 16:09 2995一.HashMap的存储结构 二.HashMap ... -
容器学习
2012-08-24 15:17 1804一.博客传送门 容器学习一:HashMap源码 ...
相关推荐
Java编程语言作为软件开发领域的重要组成部分,对于初学者而言,掌握其...同时,由于资源中提及部分附带源码分析,学习者可以通过实际代码来加深理解,遇到问题还能获得答疑支持,这对于新手来说是一份极其宝贵的资料。
源码分析 ArrayList 是一个基于动态数组实现的 List 实现类。它实现了 RandomAccess 接口,因此支持随机访问。ArrayList 的默认大小为 10,添加元素时使用 ensureCapacityInternal() 方法来保证容量足够,如果不够...
在"java-study-master"这个压缩包中,可能包含了上述知识点的实践示例和详细讲解,包括代码结构、配置文件、源码分析等,可以帮助学习者深入理解Java和SpringBoot的使用。通过系统地学习和实践,开发者可以提升自己...
这些知识点仅仅是Java容器对象的一部分,实际的博客可能会包含更多细节,如源码分析、性能对比和最佳实践。通过阅读博客中的`持有对象.xmind`文件,可以进一步了解博主对这些概念的详细整理和分类。如果你对Java容器...
源码分析有助于掌握数据传输和文件操作的底层机制。 3. **多线程**: Java提供了Thread类和Runnable接口来实现多线程。理解并发控制(如synchronized、volatile、ReentrantLock)和并发工具类(如ExecutorService...
【JAVA复习材料】是针对Java编程语言的一份学习资源,主要涵盖了源码分析和工具使用的相关知识。在Java的学习过程中,源码分析是提升技能的关键步骤,它能帮助我们理解程序内部的工作机制,提高问题解决能力。而工具...
Java容器源码分析 在Java编程中,容器是管理和组织对象的重要工具,它们提供了一种方式来存储和操作一组相关的对象。本项目"Java-basic-notes-sourcecode"包含了学习Java基础知识时涉及的一些源代码示例,涵盖了从...
源码分析有助于我们更好地理解异常的抛出和捕获过程。 6. **反射**:Java.lang.reflect包中的类,如Class、Method、Constructor,提供了运行时访问类和对象的能力。通过源码,我们可以看到如何动态地创建对象、调用...
2. **源码分析** - **容器实现**:这些类的实现通常包括一个内部存储结构(如数组或链表)和一些基本操作,如添加、删除、查找等。例如,ArrayList的`add()`方法会检查容量并根据需要进行扩容,LinkedList的`remove...
10. **源码阅读**:学习和理解一些开源项目的源码,如Apache Commons、Guava等。 这份"java校招学习笔记"应该是一个全面的参考资料,帮助求职者巩固Java知识,提高解决问题的能力,以应对面试中的各种挑战。同时,...
对于初学者来说,这是一个宝贵的学习资源,可以通过阅读和分析代码,提升自己的编程能力。 "Map案例"可能包括各种实际应用场景,如数据库索引、图形渲染、游戏逻辑等,这些案例可以帮助开发者了解Map在实际问题中的...
本文将深入探讨集合框架的使用方法,包括其基本概念、主要类库以及常见操作,同时也会提及一些源码分析和实用工具。 一、集合框架概述 Java集合框架是一个统一的接口体系,它定义了各种数据结构(如列表、队列、...
17. **源码阅读**: 分析开源项目的源代码可以帮助理解Java的最佳实践和高级技术。 18. **持续集成/持续部署(CI/CD)**: Jenkins、Git等工具用于自动化构建、测试和部署,提升开发效率。 19. **Java 8及更新版本的新...
在21号章节中,源码分析可能涉及了HashMap的put、get和resize等核心方法,以及如何通过哈希函数和链地址法处理哈希冲突。 在22号章节,HashMap的内部结构总结可能涵盖了以下内容:HashMap由数组(Entry[] table)和...
### Java进阶知识点详解 #### 第一章:基本语法 ##### 关键字 - **static**:用于定义...以上是对Java进阶知识点的详细解析,覆盖了基本语法、JDK源码分析等多个方面,有助于深入理解Java语言的核心机制及高级特性。
这里我们将深入探讨Java 8集合框架的源码分析,包括新增的流(Stream) API、函数式编程的概念以及对现有集合类的优化。 1. **流(Stream API)** Java 8引入了流的概念,它是一种可以进行聚合操作的数据结构,允许...
《面试大全》这一资源主要聚焦于Java编程语言的面试知识点,涵盖了源码解析和技术工具的使用,对于求职者和开发者来说是一份宝贵的参考资料。通过阅读其中的Java面试题(最全,最新).pdf,我们可以深入理解Java的核心...
- **Struts2**、**Hibernate**与**Spring**的核心源码分析。 - **MyBatis**:探讨其历史背景、数据库处理机制及缓存管理等。 #### 构建工具与日志管理 - **Ant与Maven**:对比两种构建工具的特点与应用场景。 - *...
4. **HashMap和TreeMap**:介绍了存储键值对的容器,HashMap快速但无序,TreeMap有序但稍慢。 5. **泛型**:讲解了泛型的概念,如何使用泛型限定集合元素类型,避免类型转换错误。 6. **枚举类型Enum**:解释了Java...