The reason that treerangemap can be sorted by range is attributed to the storage variable entriesbylowerbound of the internal navigablemap type. Navigablemap is an interface that inherits from the SortedMap interface, so Treerangemap has a sort function. The use of these interfaces can be viewed here for summary
Public Final class treerangemap<K extends comparable, V> Implements RangeMap<K, V> { Private FinalNavigablemap<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> {...}
From the definition of Entriesbylowerbound can realize the ingenious Treerangemap. This structure is based on the cut of lowerbound in range as the key, with the entire rangemapentry as the value, the natural implementation sort.
Then look at the Rangemapentry class, rangemapentry inherit from the abstract class Abstractmapentry, and abstractmapentry inherit from entry interface, seamless structure.
//defined in Treerangemap,Private Static Final class rangemapentry<K extends comparable, V> extends abstractmapentry<Range<K;, V> {...}Abstract class abstractmapentry<K, V> implements Entry< K, V> {...} Defined in Map.java, the most basic record interface Entry<K,V> {...}
Abstractmapentry is used to transition, and there is no data entity internally to implement the Setvalue,equals,hashcode,tostring method.
It is reasonable to design the entry as the internal interface of the map, because entry is a record for the specific implementation of the map. At the same time map is an interface, entry is also an interface, the definition of the most basic structure of the internal interface is worth learning.
With the support of these structures, the treerangemap is able to achieve cutting inserts so that the internal range key does not overlap. Let's take a look at the Put method
public void put (range<k> Range, V value ) { if (!range.isempty ()) {Preconditions.checknotnull (value ); this . Remove (range); //first truncate delete this . Entriesbylowerbound.put (Range.lowerbound, new treerangemap.rangemapentry (range, value )); //then lowerbound to key, rangemapentry to value, insert Entriesbylowerbound in } }
Inserts do not overlap because deletions are truncated before they are inserted. Let's take a look at the remove operation:
The remove operation is divided into two parts, the first part is the truncated rangetoremove low to cover the existing range, the second part is the truncated rangetoremove high point covered to the existing range, the two do not divide the same, explain one of them.
In the case where all if are successful, the entry (mapentrybelowtotruncate) corresponding to the maximum low point that is strictly less than the Rangetoremove low is first taken out. This is done using NAVIGABLEMAP to order the low-point storage in range. Then take out the value of this entry (mapentryabovetotruncate), corresponding to a rangemapentry, The mapentryabovetotruncate contains a range (named R) as key (where key is the key of RangeMap).
- If R contains Rangetoremove lows, R has a portion that overlaps with rangetoremove and needs to be cut; if it does not contain a proof that there is no overlapping part, this part is passed.
Under the premise of inclusion, there are two kinds of situations.
- If R contains Rangetoremove highs, then r needs to be truncated by rangetoremove from the middle waist.
- If R does not contain rangetoremove highs, then R is just the part of the lower and the Rangetoremove overlap, and this section needs to be truncated.
The source code for the truncated low-point section is as follows:
Entry Mapentrybelowtotruncate = This. Entriesbylowerbound. Lowerentry(Rangetoremove. Lowerbound);if (mapentrybelowtotruncate! = null) {Treerangemap. RangemapentryMapentryabovetotruncate = (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());} }
The part that truncates the highs is similar.
Finish
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Brief analysis of TREERANGEMAP structure in guava