Guava中TreeRangeMap结构简析
2015-08-03 17:08
337 查看
TreeRangeMap之所以能实现按照Range进行排序,这要归功于内部NavigableMap类型的存储变量entriesByLowerBound。NavigableMap是一个接口,继承自SortedMap接口,所以TreeRangeMap具有排序功能。这些接口的使用可以查看此处总结
从entriesByLowerBound的定义可以体会到TreeRangeMap的巧妙。这个结构以Range中lowerBound的Cut作为键,以整个RangeMapEntry作为值,很天然的实现排序。
再来看看RangeMapEntry类,RangeMapEntry继承自抽象类AbstractMapEntry,而AbstractMapEntry继承自Entry接口,浑然一体的结构。
AbstractMapEntry用来过渡,内部并没有数据实体,实现setValue,equals,hashCode,toString方法。
将Entry设计成Map的内部接口非常合理,因为Entry针对Map具体实现时候的一条记录。同时Map是一个接口,Entry也是一个接口,定义最基础结构时内部接口的写法值得学习。
有这些结构的支撑,TreeRangeMap能够实现切割插入,以便内部Range键不重叠。先来看看put方法
插入的时候之所以不会重叠,是因为插入前会截断删除。再来看看remove操作:
remove操作分两个部分,第一部分是截断rangeToRemove低点所覆盖已有Range,第二部分是截断rangeToRemove高点所覆盖到已有Range,两个不分差不多,解释其中一个。
在所有if都成功的情况下,先取出严格小于rangeToRemove低点的最大低点对应的Entry(mapEntryBelowToTruncate)。这是利用NavigableMap对Range中低点存储有序进行。然后取出这个Entry的value值(mapEntryAboveToTruncate),对应的是个RangeMapEntry,mapEntryAboveToTruncate里面包含作为Key(这里的Key是RangeMap的Key)的Range(取名r)。
如果r包含rangeToRemove的低点,r有一部分跟rangeToRemove重叠,需要被切割;如果不包含证明没有重叠部分,这一部分通过了。
在包含的前提下,又分两种情况。
如果r包含rangeToRemove高点,那么r需要被rangeToRemove从中间拦腰截断。
如果r不包含rangeToRemove高点,那么r只是靠近低点的部分和rangeToRemove重叠,需要截断这个部分。
截断低点部分的源码如下:
截断高点的部分类似。
(完)
public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K, V> { private final NavigableMap<Cut<K>, TreeRangeMap.RangeMapEntry<K, V>> entriesByLowerBound = Maps.newTreeMap(); ... } public interface NavigableMap<K,V> extends SortedMap<K,V> { ... } public interface SortedMap<K,V> extends Map<K,V> { ... }
从entriesByLowerBound的定义可以体会到TreeRangeMap的巧妙。这个结构以Range中lowerBound的Cut作为键,以整个RangeMapEntry作为值,很天然的实现排序。
再来看看RangeMapEntry类,RangeMapEntry继承自抽象类AbstractMapEntry,而AbstractMapEntry继承自Entry接口,浑然一体的结构。
//定义在TreeRangeMap中, private static final class RangeMapEntry<K extends Comparable, V> extends AbstractMapEntry<Range<K>, V> { ... } abstract class AbstractMapEntry<K, V> implements Entry<K, V> { ... } / /定义在Map.java中,最基础的记录 interface Entry<K,V> { ... }
AbstractMapEntry用来过渡,内部并没有数据实体,实现setValue,equals,hashCode,toString方法。
将Entry设计成Map的内部接口非常合理,因为Entry针对Map具体实现时候的一条记录。同时Map是一个接口,Entry也是一个接口,定义最基础结构时内部接口的写法值得学习。
有这些结构的支撑,TreeRangeMap能够实现切割插入,以便内部Range键不重叠。先来看看put方法
public void put(Range<K> range, V value) { if(!range.isEmpty()) { Preconditions.checkNotNull(value); this.remove(range); //先截断删除 this.entriesByLowerBound.put(range.lowerBound, new TreeRangeMap.RangeMapEntry(range, value)); //然后lowerBound为键,RangeMapEntry为值,插入entriesByLowerBound中 } }
插入的时候之所以不会重叠,是因为插入前会截断删除。再来看看remove操作:
remove操作分两个部分,第一部分是截断rangeToRemove低点所覆盖已有Range,第二部分是截断rangeToRemove高点所覆盖到已有Range,两个不分差不多,解释其中一个。
在所有if都成功的情况下,先取出严格小于rangeToRemove低点的最大低点对应的Entry(mapEntryBelowToTruncate)。这是利用NavigableMap对Range中低点存储有序进行。然后取出这个Entry的value值(mapEntryAboveToTruncate),对应的是个RangeMapEntry,mapEntryAboveToTruncate里面包含作为Key(这里的Key是RangeMap的Key)的Range(取名r)。
如果r包含rangeToRemove的低点,r有一部分跟rangeToRemove重叠,需要被切割;如果不包含证明没有重叠部分,这一部分通过了。
在包含的前提下,又分两种情况。
如果r包含rangeToRemove高点,那么r需要被rangeToRemove从中间拦腰截断。
如果r不包含rangeToRemove高点,那么r只是靠近低点的部分和rangeToRemove重叠,需要截断这个部分。
截断低点部分的源码如下:
Entry mapEntryBelowToTruncate = this.entriesByLowerBound.lowerEntry(rangeToRemove.lowerBound); if(mapEntryBelowToTruncate != null) { TreeRangeMap.RangeMapEntry mapEntryAboveToTruncate = (TreeRangeMap.RangeMapEntry)mapEntryBelowToTruncate.getValue(); if(mapEntryAboveToTruncate.getUpperBound().compareTo(rangeToRemove.lowerBound) > 0) { if(mapEntryAboveToTruncate.getUpperBound().compareTo(rangeToRemove.upperBound) > 0) { this.putRangeMapEntry(rangeToRemove.upperBound, mapEntryAboveToTruncate.getUpperBound(), ((TreeRangeMap.RangeMapEntry)mapEntryBelowToTruncate.getValue()).getValue()); } this.putRangeMapEntry(mapEntryAboveToTruncate.getLowerBound(), rangeToRemove.lowerBound, ((TreeRangeMap.RangeMapEntry)mapEntryBelowToTruncate.getValue()).getValue()); } }
截断高点的部分类似。
(完)
相关文章推荐
- Python's Coding Style
- 利用JS弹出层实现简单的动态提示“正在加载中,请稍等...”
- CSS
- Android高仿微信图片多选功能
- 深入解析C语言声明
- jQuery 效果 - toggle() 方法
- 杭电(hdu)1702 ACboy needs your help again!
- Android Studio中如何引用图片资源
- 文件系统操作与磁盘管理
- 文章标题
- 个人的spring配置的简单记录
- UI_Delegate
- iOS开发UI篇—在UItableview中实现加载更多功能
- android application
- fzu 1752
- 楼主,可否发一份代码给我!QQ....
- 简单的文本处理
- HDU 5335 Walk Out(多校)
- js中substring和substr的用法
- android 遍历本地联系人