Java-基于红黑树成功-TreeMap底层成功原理 (java基础知识点)
阿里这段期间忙着制订下半年的OKR,其真实制订OKR的时刻就能看出团队里谁是指导的嫡系,谁是团队的边角料。嫡系的OKR都是从指导的外围名目分进去的,而其他人的OKR不会体如今指导的OKR外面,只配给嫡系做打下手的任务。
员工的绩效,在制订OKR的时刻,曾经确定了。
职场失意,摸鱼自得。我还是忧心的降级《解读源码专栏》,在这个系列中,我将手把手带着大家剖析Java外围组件的源码,内容蕴含汇合、线程、线程池、并发、队列等,深化了解其面前的设计思维和成功细节,轻松应答任务面试。这是解读Java源码系列的第六篇,将跟大家一同窗习Java中比拟不凡的数据结构-。
引言
上篇文章讲到
LinkedHashMap
可以保障元素的拔出顺序或许访问顺序,而也能保障元素顺序,不过依照键的顺序启动排序。拔出到中的键值对,会智能依照键的顺序启动排序。
简介
底层结构是基于数组成功的,而底层结构是基于红黑树成功的。应用红黑树的个性成功对键的排序。额外引见一下红黑树的个性:
红黑树是基于平衡二叉树的改良,而平衡二叉树是为了处置二叉搜查树在不凡状况下,退步成链表,查找、拔出效率退步成O(n),规则左右子树高度差不超越1,然而拔出、删除节点的时刻,所做的平衡操作比拟复杂。而红黑树的个性,保障了平衡操作成功相对繁难,树的高度仅比平衡二叉树高了一倍,查找、拔出、删除的期间复杂度是O(logn)。
经常使用示例
应用可以智能对键启动排序的个性,比拟适用一些须要排序的场景,比如排行榜、商品列表等。
Map<Integer,String>map=newTreeMap<>();map.put(1,"One");map.put(3,"Three");map.put(2,"Two");System.out.println(map);//输入:{1=One,2=Two,3=Three}
成功一个繁难的热词排行榜性能:
/***@author一灯架构*@apiNote热词**/publicclassHot{/***热词内容*/Stringword;/***热度*/Integercount;publicHotWord(Stringword,Integercount){this.word=word;this.count=count;}}
importjava.util.Comparator;importjava.util.TreeMap;/***@author一灯架构*@apiNote热词排行榜**/publicclassLeaderboard{/***自定义排序形式,依照热度降序陈列*/privatestaticfinalComparator<HotWord>HOT_WORD_COMPARATOR=newComparator<HotWord>(){@Overridepublicintcompare(HotWordo1,HotWordo2){returnInteger.compare(o2.count,o1.count);//降序陈列}};//经常使用TreeMap存储排行榜数据,key是热词对象,value是热词题目privateTreeMap<HotWord,String>rankMap=newTreeMap<>(HOT_WORD_COMPARATOR);//参与效果publicvoidaddHotWord(Stringname,intscore){rankMap.put(newHotWord(name,score),name);}/***打印排行榜*/publicvoidprintLeaderboard(){System.out.println("热词排行榜:");intrank=1;for(HotWordhotWord:rankMap.keySet()){System.out.println("#"+rank+""+hotWord);rank++;}}publicstaticvoidmn(String[]args){Leaderboardleaderboard=newLeaderboard();leaderboard.addHotWord("闲鱼崩了",90);leaderboard.addHotWord("淘宝崩了",95);leaderboard.addHotWord("闲鱼崩了",85);leaderboard.addHotWord("钉钉崩了",80);leaderboard.printLeaderboard();}}
输入结果:
热词排行榜:#1HotWord(word=淘宝崩了,count=95)#2HotWord(word=闲鱼崩了,count=90)#3HotWord(word=闲鱼崩了,count=85)#4HotWord(word=钉钉崩了,count=80)
类属性
看一下TreeMap的类属性,蕴含哪些字段?
publicclassTreeMap<K,V>extendsAbstractMap<K,V>implementsNavigableMap<K,V>,Cloneable,java.io.Serializable{/***排序形式*/privatefinalComparator<?superK>comparator;/***红黑树根节点*/privatetransientEntry<K,V>root;/***红黑树节点数*/privatetransientintsize=0;/***红黑树的红黑节点示意*/privatestaticfinalbooleanRED=false;privatestaticfinalbooleanBLACK=true;/***红黑树节点对象*/staticfinalclassEntry<K,V>implementsMap.Entry<K,V>{Kkey;Vvalue;Entry<K,V>left;Entry<K,V>right;Entry<K,V>parent;booleancolor=BLACK;/***结构方法*/Entry(Kkey,Vvalue,Entry<K,V>parent){this.key=key;this.value=value;this.parent=parent;}}}
TreeMap类属性比拟繁难,蕴含排序形式comparator、红黑树根节点root、节点个数size等。自定义了一个红黑树节点类Entry,外部属性包括键值对、左右子树、父节点、红黑标志值等。
初始化
TreeMap罕用的初始化形式有上方三个:
/***无参初始化*/Map<Integer,Integer>map1=newTreeMap<>();/***指定排序形式初始化*/Map<Integer,Integer>map2=newTreeMap<>(newComparator<Integer>(){@Overridepublicintcompare(Integero1,Integero2){returno1.compareTo(o2);}});/***将个别Map转换为TreeMap*/Map<Integer,Integer>map3=newTreeMap<>(newHashMap<>());
再看一下对应的源码成功:
/***无参初始化*/publicTreeMap(){comparator=null;}/***指定排序形式初始化*/publicTreeMap(Comparator<?superK>comparator){this.comparator=comparator;}/***将个别Map转换为TreeMap*/publicTreeMap(Map<?extendsK,?extendsV>m){comparator=null;putAll(m);}
方法列表
由于TreeMap存储是依照键的顺序陈列的,所以还可以启动范围查问,上方举一些示例。
importjava.util.Collections;importjava.util.Map;importjava.util.TreeMap;/***@author一灯架构*@apiNoteTreeMap方法测试*/publicclassTreeMapTest{publicstaticvoidmain(String[]args){//1.创立一个热词排行榜(按热度倒序),key是热度,value是热词内容TreeMap<Integer,String>rankMap=newTreeMap<>(Collections.reverrder());rankMap.put(80,"阿里云崩了");rankMap.put(100,"淘宝崩了");rankMap.put(90,"钉钉崩了");rankMap.put(60,"闲鱼崩了");rankMap.put(70,"支付宝崩了");System.out.println("热词排行榜:");for(Map.Entry<Integer,String>entry:rankMap.entrySet()){System.out.println("#"+entry.getKey()+""+entry.getValue());}System.out.println("-----------");//2.失掉排行榜的第一个元素Map.Entry<Integer,String>firstEntry=rankMap.firstEntry();System.out.println("firstEntry:"+firstEntry);//3.失掉排行榜的最后一个元素Map.Entry<Integer,String>lastEntry=rankMap.lastEntry();System.out.println("lastEntry:"+lastEntry);//4.失掉排行榜的大于指定键的最小元素(由于是倒序陈列,所以结果是反的)Map.Entry<Integer,String>higherEntry=rankMap.higherEntry(70);System.out.println("higherEntry:"+higherEntry);//5.失掉排行榜的小于指定键的最大元素Map.Entry<Integer,String>lowerEntry=rankMap.lowerEntry(70);System.out.println("lowerEntry:"+lowerEntry);//6.失掉排行榜的大于等于指定键的最小元素Map.Entry<Integer,String>ceilingEntry=rankMap.ceilingEntry(70);System.out.println("ceilingEntry:"+ceilingEntry);//7.失掉排行榜的小于等于指定键的最大元素Map.Entry<Integer,String>floorEntry=rankMap.floorEntry(70);System.out.println("floorEntry:"+floorEntry);}}
输入结果:
热词排行榜:#100淘宝崩了#90钉钉崩了#80阿里云崩了#70支付宝崩了#60闲鱼崩了-----------firstEntry:100=淘宝崩了lastEntry:60=闲鱼崩了higherEntry:60=闲鱼崩了lowerEntry:80=阿里云崩了ceilingEntry:70=支付宝崩了floorEntry:70=支付宝崩了
其余方法的还包括:
作用 | 方法签名 |
---|---|
失掉第一个键 | KfirstKey() |
失掉最后一个键 | KlastKey() |
失掉大于指定键的最小键 | KhigherKey(Kkey) |
失掉小于指定键的最大键 | KlowerKey(Kkey) |
失掉大于等于指定键的最小键 | KceilingKey(Kkey) |
失掉小于等于指定键的最大键 | KfloorKey(Kkey) |
失掉第一个键值对 | Map.Entry<K,V>firstEntry() |
失掉最后一个键值对 | Map.Entry<K,V>lastEntry() |
失掉并删除第一个键值对 | Map.Entry<K,V>pollFirstEntry() |
失掉并删除最后一个键值对 | Map.Entry<K,V>pollLastEntry() |
失掉大于指定键的最小键值对 | Map.Entry<K,V>higherEntry(Kkey) |
失掉小于指定键的最大键值对 | Map.Entry<K,V>lowerEntry(Kkey) |
失掉大于等于指定键的最小键值对 | Map.Entry<K,V>ceilingEntry(Kkey) |
失掉小于等于指定键的最大键值对 | Map.Entry<K,V>floorEntry(Kkey) |
失掉子map,左闭右开 | SortedMap<K,V>subMap(KfromKey,KtoKey) |
失掉前几个子map,不蕴含指定键 | SortedMap<K,V>headMap(KtoKey) |
失掉前几个子map | NavigableMap<K,V>headMap(KtoKey,booleaninclusive) |
失掉后几个子map,不蕴含指定键 | SortedMap<K,V>tailMap(KfromKey) |
失掉后几个子map | NavigableMap<K,V>tailMap(KfromKey,booleaninclusive) |
失掉其中一段子map | NavigableMap<K,V>subMap(KfromKey,booleanfromInclusive,KtoKey,booleantoInclusive) |
put源码
再看一下的put源码:
/***put源码入口*/publicVput(Kkey,Vvalue){Entry<K,V>t=root;//1.假设根节点为空,则创立根节点if(t==null){compare(key,key);root=newEntry<>(key,value,null);size=1;modCount++;returnnull;}intcmp;Entry<K,V>parent;//2.判别能否传入了排序形式,假设没有则经常使用自动Comparator<?superK>cpr=comparator;if(cpr!=null){//3.假设传入了排序形式,经常使用do-while循环,找到指标值所在位置,并赋值do{parent=t;cmp=cpr.compare(key,t.key);//4.应用红黑树节点左小右大的个性,启动查找if(cmp<0){t=t.left;}elseif(cmp>0){t=t.right;}else{returnt.setValue(value);}}while(t!=null);}else{//5.TreeMap不准许key为nullif(key==null){thrownewNullPointerException();}//6.假设没有传入排序形式,则经常使用Comparable启动比拟Comparable<?superK>k=(Comparable<?superK>)key;//7.跟上方分歧,经常使用do-while循环,应用红黑树节点左小右大的个性,查找指标值所在位置,并赋值do{parent=t;cmp=k.compareTo(t.key);if(cmp<0){t=t.left;}elseif(cmp>0){t=t.right;}else{returnt.setValue(value);}}while(t!=null);}//8.假设没有找到,则创立新节点Entry<K,V>e=newEntry<>(key,value,parent);if(cmp<0){parent.left=e;}else{parent.right=e;}//9.拔出新节点后,须要调整红黑树节点位置,坚持红黑树的个性fixAfterInsertion(e);size++;modCount++;returnnull;}
put源码逻辑比拟繁难:
get源码
再看一下get源码:
/***get源码入口*/publicVget(Objectkey){//调用查找节点的方法Entry<K,V>p=getEntry(key);return(p==null?null:p.value);}/***查找节点方法*/finalEntry<K,V>getEntry(Objectkey){//1.判别假设传入了排序形式,则经常使用排序形式查找节点if(comparator!=null){returngetEntryUsingComparator(key);}if(key==null){thrownewNullPointerException();}//2.否则经常使用自动形式查找Comparable<?superK>k=(Comparable<?superK>)key;Entry<K,V>p=root;//3.应用红黑树节点左小右大的个性,循环查找while(p!=null){intcmp=k.compareTo(p.key);if(cmp<0){p=p.left;}elseif(cmp>0){p=p.right;}else{returnp;}}returnnull;}/***经常使用传入的排序形式,查找节点方法*/finalEntry<K,V>getEntryUsingComparator(Objectkey){Kk=(K)key;Comparator<?superK>cpr=comparator;if(cpr!=null){Entry<K,V>p=root;//3.跟上方相似,应用红黑树节点左小右大的个性,循环查找while(p!=null){intcmp=cpr.compare(k,p.key);if(cmp<0){p=p.left;}elseif(cmp>0){p=p.right;}else{returnp;}}}returnnull;}
get方法源码与put方法逻辑相似,都是应用红黑树的个性遍历红黑树。
总结
是一种有序Map汇合,具备以下个性:
Java 容器详解:使用与案例
深入解析Java的容器世界:探索、实践与案例
Java的容器,如同一个精致的工具箱,承载着数据和对象的管理。与C++的STL类相比,Java Collection Framework (JCF) 提供了更为丰富的功能和灵活性。让我们一起探索这个框架,理解Collection和Map的核心概念,以及它们在实际项目中的应用。
一、Java容器概览
二、设计模式的应用
Java容器巧妙地运用了设计模式,如迭代器模式。Collection接口的iterator()方法生成一个Iterator,让我们能够遍历集合中的元素,从JDK 1.5开始,foreach语句让遍历变得更简洁。
三、源码解析实战
让我们通过ArrayList和Vector的源码,了解它们的内部结构和关键操作,如ArrayList的动态扩容、删除和序列化机制。同时,学习Vector的同步机制和CopyOnWriteArrayList的读写分离特性。
四、容器的内存优化与选择
理解不同容器的内存管理策略,如LinkedList的链表结构、HashMap的拉链法和WeakHashMap的弱引用,对内存敏感和性能要求高的场景尤为重要。CopyOnWriteArrayList在读多写少场景中表现出色,但需要权衡内存消耗和数据一致性。
五、总结与建议
掌握Java容器不仅是入门,深入理解其内部原理和算法是提升编程技能的关键。通过查阅API和源码,亲手实现容器,能让你在实际开发中游刃有余。选择合适的容器,根据项目需求定制数据结构,将极大提升代码质量和效率。
学习Java容器,让我们在数据管理的旅程中更加自信和熟练。
java map容器 哪些排序
一.理论准备Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等。 TreeMap:基于红黑树(Red-Black tree)的 NavigableMap 实现,该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。 HashMap的值是没有顺序的,它是按照key的HashCode来实现的,对于这个无序的HashMap我们要怎么来实现排序呢?参照TreeMap的value排序。 返回Collections视图。 二排序TreeMap默认是升序的,如果我们需要改变排序方式,则需要使用比较器:Comparator。 Comparator可以对集合对象或者数组进行排序的比较器接口,实现该接口的public compare(T o1,To2)方法即可实现排序,如下:import ;import ;import ;import ;import ;public class TreeMapTest {public static void main(String[] args) {Map<String, String> map = new TreeMap<String, String>(new Comparator<String>() {public int compare(String obj1, String obj2) {// 降序排序return (obj1);}});(b, ccccc);(d, aaaaa);(c, bbbbb);(a, ddddd);Set<String> keySet = ();Iterator<String> iter = ();while (()) {String key = ();(key + : + (key));}}}运行结果如下:d:aaaaac:bbbbbb:ccccca:ddddd三排序上面例子是对根据TreeMap的key值来进行排序的,但是有时我们需要根据TreeMap的value来进行排序。 对value排序我们就需要借助于Collections的sort(List<T> list, Comparator<? super T> c)方法,该方法根据指定比较器产生的顺序对指定列表进行排序。 但是有一个前提条件,那就是所有的元素都必须能够根据所提供的比较器来进行比较,如下:import ;import ;import ;import ;import ;import ;import ;public class TreeMapTest {public static void main(String[] args) {Map<String, String> map = new TreeMap<String, String>();(a, ddddd);(c, bbbbb);(d, aaaaa);(b, ccccc);//这里将()转换成listList<<String,String>> list = new ArrayList<<String,String>>(());//然后通过比较器来实现排序(list,new Comparator<<String,String>>() {//升序排序public int compare(Entry<String, String> o1,Entry<String, String> o2) {return ()(());}});for(<String,String> mapping:list){(()+:+());}}}运行结果如下:d:aaaaac:bbbbbb:ccccca:ddddd
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。