emul/compact/src/main/java/java/util/TreeMap.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 07 Sep 2013 13:51:24 +0200
branchjdk7-b147
changeset 1258 724f3e1ea53e
permissions -rw-r--r--
Additional set of classes to make porting of lookup library more easier
jaroslav@1258
     1
/*
jaroslav@1258
     2
 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
jaroslav@1258
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jaroslav@1258
     4
 *
jaroslav@1258
     5
 * This code is free software; you can redistribute it and/or modify it
jaroslav@1258
     6
 * under the terms of the GNU General Public License version 2 only, as
jaroslav@1258
     7
 * published by the Free Software Foundation.  Oracle designates this
jaroslav@1258
     8
 * particular file as subject to the "Classpath" exception as provided
jaroslav@1258
     9
 * by Oracle in the LICENSE file that accompanied this code.
jaroslav@1258
    10
 *
jaroslav@1258
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
jaroslav@1258
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jaroslav@1258
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jaroslav@1258
    14
 * version 2 for more details (a copy is included in the LICENSE file that
jaroslav@1258
    15
 * accompanied this code).
jaroslav@1258
    16
 *
jaroslav@1258
    17
 * You should have received a copy of the GNU General Public License version
jaroslav@1258
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
jaroslav@1258
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jaroslav@1258
    20
 *
jaroslav@1258
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jaroslav@1258
    22
 * or visit www.oracle.com if you need additional information or have any
jaroslav@1258
    23
 * questions.
jaroslav@1258
    24
 */
jaroslav@1258
    25
jaroslav@1258
    26
package java.util;
jaroslav@1258
    27
jaroslav@1258
    28
/**
jaroslav@1258
    29
 * A Red-Black tree based {@link NavigableMap} implementation.
jaroslav@1258
    30
 * The map is sorted according to the {@linkplain Comparable natural
jaroslav@1258
    31
 * ordering} of its keys, or by a {@link Comparator} provided at map
jaroslav@1258
    32
 * creation time, depending on which constructor is used.
jaroslav@1258
    33
 *
jaroslav@1258
    34
 * <p>This implementation provides guaranteed log(n) time cost for the
jaroslav@1258
    35
 * {@code containsKey}, {@code get}, {@code put} and {@code remove}
jaroslav@1258
    36
 * operations.  Algorithms are adaptations of those in Cormen, Leiserson, and
jaroslav@1258
    37
 * Rivest's <em>Introduction to Algorithms</em>.
jaroslav@1258
    38
 *
jaroslav@1258
    39
 * <p>Note that the ordering maintained by a tree map, like any sorted map, and
jaroslav@1258
    40
 * whether or not an explicit comparator is provided, must be <em>consistent
jaroslav@1258
    41
 * with {@code equals}</em> if this sorted map is to correctly implement the
jaroslav@1258
    42
 * {@code Map} interface.  (See {@code Comparable} or {@code Comparator} for a
jaroslav@1258
    43
 * precise definition of <em>consistent with equals</em>.)  This is so because
jaroslav@1258
    44
 * the {@code Map} interface is defined in terms of the {@code equals}
jaroslav@1258
    45
 * operation, but a sorted map performs all key comparisons using its {@code
jaroslav@1258
    46
 * compareTo} (or {@code compare}) method, so two keys that are deemed equal by
jaroslav@1258
    47
 * this method are, from the standpoint of the sorted map, equal.  The behavior
jaroslav@1258
    48
 * of a sorted map <em>is</em> well-defined even if its ordering is
jaroslav@1258
    49
 * inconsistent with {@code equals}; it just fails to obey the general contract
jaroslav@1258
    50
 * of the {@code Map} interface.
jaroslav@1258
    51
 *
jaroslav@1258
    52
 * <p><strong>Note that this implementation is not synchronized.</strong>
jaroslav@1258
    53
 * If multiple threads access a map concurrently, and at least one of the
jaroslav@1258
    54
 * threads modifies the map structurally, it <em>must</em> be synchronized
jaroslav@1258
    55
 * externally.  (A structural modification is any operation that adds or
jaroslav@1258
    56
 * deletes one or more mappings; merely changing the value associated
jaroslav@1258
    57
 * with an existing key is not a structural modification.)  This is
jaroslav@1258
    58
 * typically accomplished by synchronizing on some object that naturally
jaroslav@1258
    59
 * encapsulates the map.
jaroslav@1258
    60
 * If no such object exists, the map should be "wrapped" using the
jaroslav@1258
    61
 * {@link Collections#synchronizedSortedMap Collections.synchronizedSortedMap}
jaroslav@1258
    62
 * method.  This is best done at creation time, to prevent accidental
jaroslav@1258
    63
 * unsynchronized access to the map: <pre>
jaroslav@1258
    64
 *   SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));</pre>
jaroslav@1258
    65
 *
jaroslav@1258
    66
 * <p>The iterators returned by the {@code iterator} method of the collections
jaroslav@1258
    67
 * returned by all of this class's "collection view methods" are
jaroslav@1258
    68
 * <em>fail-fast</em>: if the map is structurally modified at any time after
jaroslav@1258
    69
 * the iterator is created, in any way except through the iterator's own
jaroslav@1258
    70
 * {@code remove} method, the iterator will throw a {@link
jaroslav@1258
    71
 * ConcurrentModificationException}.  Thus, in the face of concurrent
jaroslav@1258
    72
 * modification, the iterator fails quickly and cleanly, rather than risking
jaroslav@1258
    73
 * arbitrary, non-deterministic behavior at an undetermined time in the future.
jaroslav@1258
    74
 *
jaroslav@1258
    75
 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
jaroslav@1258
    76
 * as it is, generally speaking, impossible to make any hard guarantees in the
jaroslav@1258
    77
 * presence of unsynchronized concurrent modification.  Fail-fast iterators
jaroslav@1258
    78
 * throw {@code ConcurrentModificationException} on a best-effort basis.
jaroslav@1258
    79
 * Therefore, it would be wrong to write a program that depended on this
jaroslav@1258
    80
 * exception for its correctness:   <em>the fail-fast behavior of iterators
jaroslav@1258
    81
 * should be used only to detect bugs.</em>
jaroslav@1258
    82
 *
jaroslav@1258
    83
 * <p>All {@code Map.Entry} pairs returned by methods in this class
jaroslav@1258
    84
 * and its views represent snapshots of mappings at the time they were
jaroslav@1258
    85
 * produced. They do <strong>not</strong> support the {@code Entry.setValue}
jaroslav@1258
    86
 * method. (Note however that it is possible to change mappings in the
jaroslav@1258
    87
 * associated map using {@code put}.)
jaroslav@1258
    88
 *
jaroslav@1258
    89
 * <p>This class is a member of the
jaroslav@1258
    90
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
jaroslav@1258
    91
 * Java Collections Framework</a>.
jaroslav@1258
    92
 *
jaroslav@1258
    93
 * @param <K> the type of keys maintained by this map
jaroslav@1258
    94
 * @param <V> the type of mapped values
jaroslav@1258
    95
 *
jaroslav@1258
    96
 * @author  Josh Bloch and Doug Lea
jaroslav@1258
    97
 * @see Map
jaroslav@1258
    98
 * @see HashMap
jaroslav@1258
    99
 * @see Hashtable
jaroslav@1258
   100
 * @see Comparable
jaroslav@1258
   101
 * @see Comparator
jaroslav@1258
   102
 * @see Collection
jaroslav@1258
   103
 * @since 1.2
jaroslav@1258
   104
 */
jaroslav@1258
   105
jaroslav@1258
   106
public class TreeMap<K,V>
jaroslav@1258
   107
    extends AbstractMap<K,V>
jaroslav@1258
   108
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
jaroslav@1258
   109
{
jaroslav@1258
   110
    /**
jaroslav@1258
   111
     * The comparator used to maintain order in this tree map, or
jaroslav@1258
   112
     * null if it uses the natural ordering of its keys.
jaroslav@1258
   113
     *
jaroslav@1258
   114
     * @serial
jaroslav@1258
   115
     */
jaroslav@1258
   116
    private final Comparator<? super K> comparator;
jaroslav@1258
   117
jaroslav@1258
   118
    private transient Entry<K,V> root = null;
jaroslav@1258
   119
jaroslav@1258
   120
    /**
jaroslav@1258
   121
     * The number of entries in the tree
jaroslav@1258
   122
     */
jaroslav@1258
   123
    private transient int size = 0;
jaroslav@1258
   124
jaroslav@1258
   125
    /**
jaroslav@1258
   126
     * The number of structural modifications to the tree.
jaroslav@1258
   127
     */
jaroslav@1258
   128
    private transient int modCount = 0;
jaroslav@1258
   129
jaroslav@1258
   130
    /**
jaroslav@1258
   131
     * Constructs a new, empty tree map, using the natural ordering of its
jaroslav@1258
   132
     * keys.  All keys inserted into the map must implement the {@link
jaroslav@1258
   133
     * Comparable} interface.  Furthermore, all such keys must be
jaroslav@1258
   134
     * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw
jaroslav@1258
   135
     * a {@code ClassCastException} for any keys {@code k1} and
jaroslav@1258
   136
     * {@code k2} in the map.  If the user attempts to put a key into the
jaroslav@1258
   137
     * map that violates this constraint (for example, the user attempts to
jaroslav@1258
   138
     * put a string key into a map whose keys are integers), the
jaroslav@1258
   139
     * {@code put(Object key, Object value)} call will throw a
jaroslav@1258
   140
     * {@code ClassCastException}.
jaroslav@1258
   141
     */
jaroslav@1258
   142
    public TreeMap() {
jaroslav@1258
   143
        comparator = null;
jaroslav@1258
   144
    }
jaroslav@1258
   145
jaroslav@1258
   146
    /**
jaroslav@1258
   147
     * Constructs a new, empty tree map, ordered according to the given
jaroslav@1258
   148
     * comparator.  All keys inserted into the map must be <em>mutually
jaroslav@1258
   149
     * comparable</em> by the given comparator: {@code comparator.compare(k1,
jaroslav@1258
   150
     * k2)} must not throw a {@code ClassCastException} for any keys
jaroslav@1258
   151
     * {@code k1} and {@code k2} in the map.  If the user attempts to put
jaroslav@1258
   152
     * a key into the map that violates this constraint, the {@code put(Object
jaroslav@1258
   153
     * key, Object value)} call will throw a
jaroslav@1258
   154
     * {@code ClassCastException}.
jaroslav@1258
   155
     *
jaroslav@1258
   156
     * @param comparator the comparator that will be used to order this map.
jaroslav@1258
   157
     *        If {@code null}, the {@linkplain Comparable natural
jaroslav@1258
   158
     *        ordering} of the keys will be used.
jaroslav@1258
   159
     */
jaroslav@1258
   160
    public TreeMap(Comparator<? super K> comparator) {
jaroslav@1258
   161
        this.comparator = comparator;
jaroslav@1258
   162
    }
jaroslav@1258
   163
jaroslav@1258
   164
    /**
jaroslav@1258
   165
     * Constructs a new tree map containing the same mappings as the given
jaroslav@1258
   166
     * map, ordered according to the <em>natural ordering</em> of its keys.
jaroslav@1258
   167
     * All keys inserted into the new map must implement the {@link
jaroslav@1258
   168
     * Comparable} interface.  Furthermore, all such keys must be
jaroslav@1258
   169
     * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw
jaroslav@1258
   170
     * a {@code ClassCastException} for any keys {@code k1} and
jaroslav@1258
   171
     * {@code k2} in the map.  This method runs in n*log(n) time.
jaroslav@1258
   172
     *
jaroslav@1258
   173
     * @param  m the map whose mappings are to be placed in this map
jaroslav@1258
   174
     * @throws ClassCastException if the keys in m are not {@link Comparable},
jaroslav@1258
   175
     *         or are not mutually comparable
jaroslav@1258
   176
     * @throws NullPointerException if the specified map is null
jaroslav@1258
   177
     */
jaroslav@1258
   178
    public TreeMap(Map<? extends K, ? extends V> m) {
jaroslav@1258
   179
        comparator = null;
jaroslav@1258
   180
        putAll(m);
jaroslav@1258
   181
    }
jaroslav@1258
   182
jaroslav@1258
   183
    /**
jaroslav@1258
   184
     * Constructs a new tree map containing the same mappings and
jaroslav@1258
   185
     * using the same ordering as the specified sorted map.  This
jaroslav@1258
   186
     * method runs in linear time.
jaroslav@1258
   187
     *
jaroslav@1258
   188
     * @param  m the sorted map whose mappings are to be placed in this map,
jaroslav@1258
   189
     *         and whose comparator is to be used to sort this map
jaroslav@1258
   190
     * @throws NullPointerException if the specified map is null
jaroslav@1258
   191
     */
jaroslav@1258
   192
    public TreeMap(SortedMap<K, ? extends V> m) {
jaroslav@1258
   193
        comparator = m.comparator();
jaroslav@1258
   194
        try {
jaroslav@1258
   195
            buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
jaroslav@1258
   196
        } catch (java.io.IOException cannotHappen) {
jaroslav@1258
   197
        } catch (ClassNotFoundException cannotHappen) {
jaroslav@1258
   198
        }
jaroslav@1258
   199
    }
jaroslav@1258
   200
jaroslav@1258
   201
jaroslav@1258
   202
    // Query Operations
jaroslav@1258
   203
jaroslav@1258
   204
    /**
jaroslav@1258
   205
     * Returns the number of key-value mappings in this map.
jaroslav@1258
   206
     *
jaroslav@1258
   207
     * @return the number of key-value mappings in this map
jaroslav@1258
   208
     */
jaroslav@1258
   209
    public int size() {
jaroslav@1258
   210
        return size;
jaroslav@1258
   211
    }
jaroslav@1258
   212
jaroslav@1258
   213
    /**
jaroslav@1258
   214
     * Returns {@code true} if this map contains a mapping for the specified
jaroslav@1258
   215
     * key.
jaroslav@1258
   216
     *
jaroslav@1258
   217
     * @param key key whose presence in this map is to be tested
jaroslav@1258
   218
     * @return {@code true} if this map contains a mapping for the
jaroslav@1258
   219
     *         specified key
jaroslav@1258
   220
     * @throws ClassCastException if the specified key cannot be compared
jaroslav@1258
   221
     *         with the keys currently in the map
jaroslav@1258
   222
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   223
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   224
     *         does not permit null keys
jaroslav@1258
   225
     */
jaroslav@1258
   226
    public boolean containsKey(Object key) {
jaroslav@1258
   227
        return getEntry(key) != null;
jaroslav@1258
   228
    }
jaroslav@1258
   229
jaroslav@1258
   230
    /**
jaroslav@1258
   231
     * Returns {@code true} if this map maps one or more keys to the
jaroslav@1258
   232
     * specified value.  More formally, returns {@code true} if and only if
jaroslav@1258
   233
     * this map contains at least one mapping to a value {@code v} such
jaroslav@1258
   234
     * that {@code (value==null ? v==null : value.equals(v))}.  This
jaroslav@1258
   235
     * operation will probably require time linear in the map size for
jaroslav@1258
   236
     * most implementations.
jaroslav@1258
   237
     *
jaroslav@1258
   238
     * @param value value whose presence in this map is to be tested
jaroslav@1258
   239
     * @return {@code true} if a mapping to {@code value} exists;
jaroslav@1258
   240
     *         {@code false} otherwise
jaroslav@1258
   241
     * @since 1.2
jaroslav@1258
   242
     */
jaroslav@1258
   243
    public boolean containsValue(Object value) {
jaroslav@1258
   244
        for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
jaroslav@1258
   245
            if (valEquals(value, e.value))
jaroslav@1258
   246
                return true;
jaroslav@1258
   247
        return false;
jaroslav@1258
   248
    }
jaroslav@1258
   249
jaroslav@1258
   250
    /**
jaroslav@1258
   251
     * Returns the value to which the specified key is mapped,
jaroslav@1258
   252
     * or {@code null} if this map contains no mapping for the key.
jaroslav@1258
   253
     *
jaroslav@1258
   254
     * <p>More formally, if this map contains a mapping from a key
jaroslav@1258
   255
     * {@code k} to a value {@code v} such that {@code key} compares
jaroslav@1258
   256
     * equal to {@code k} according to the map's ordering, then this
jaroslav@1258
   257
     * method returns {@code v}; otherwise it returns {@code null}.
jaroslav@1258
   258
     * (There can be at most one such mapping.)
jaroslav@1258
   259
     *
jaroslav@1258
   260
     * <p>A return value of {@code null} does not <em>necessarily</em>
jaroslav@1258
   261
     * indicate that the map contains no mapping for the key; it's also
jaroslav@1258
   262
     * possible that the map explicitly maps the key to {@code null}.
jaroslav@1258
   263
     * The {@link #containsKey containsKey} operation may be used to
jaroslav@1258
   264
     * distinguish these two cases.
jaroslav@1258
   265
     *
jaroslav@1258
   266
     * @throws ClassCastException if the specified key cannot be compared
jaroslav@1258
   267
     *         with the keys currently in the map
jaroslav@1258
   268
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   269
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   270
     *         does not permit null keys
jaroslav@1258
   271
     */
jaroslav@1258
   272
    public V get(Object key) {
jaroslav@1258
   273
        Entry<K,V> p = getEntry(key);
jaroslav@1258
   274
        return (p==null ? null : p.value);
jaroslav@1258
   275
    }
jaroslav@1258
   276
jaroslav@1258
   277
    public Comparator<? super K> comparator() {
jaroslav@1258
   278
        return comparator;
jaroslav@1258
   279
    }
jaroslav@1258
   280
jaroslav@1258
   281
    /**
jaroslav@1258
   282
     * @throws NoSuchElementException {@inheritDoc}
jaroslav@1258
   283
     */
jaroslav@1258
   284
    public K firstKey() {
jaroslav@1258
   285
        return key(getFirstEntry());
jaroslav@1258
   286
    }
jaroslav@1258
   287
jaroslav@1258
   288
    /**
jaroslav@1258
   289
     * @throws NoSuchElementException {@inheritDoc}
jaroslav@1258
   290
     */
jaroslav@1258
   291
    public K lastKey() {
jaroslav@1258
   292
        return key(getLastEntry());
jaroslav@1258
   293
    }
jaroslav@1258
   294
jaroslav@1258
   295
    /**
jaroslav@1258
   296
     * Copies all of the mappings from the specified map to this map.
jaroslav@1258
   297
     * These mappings replace any mappings that this map had for any
jaroslav@1258
   298
     * of the keys currently in the specified map.
jaroslav@1258
   299
     *
jaroslav@1258
   300
     * @param  map mappings to be stored in this map
jaroslav@1258
   301
     * @throws ClassCastException if the class of a key or value in
jaroslav@1258
   302
     *         the specified map prevents it from being stored in this map
jaroslav@1258
   303
     * @throws NullPointerException if the specified map is null or
jaroslav@1258
   304
     *         the specified map contains a null key and this map does not
jaroslav@1258
   305
     *         permit null keys
jaroslav@1258
   306
     */
jaroslav@1258
   307
    public void putAll(Map<? extends K, ? extends V> map) {
jaroslav@1258
   308
        int mapSize = map.size();
jaroslav@1258
   309
        if (size==0 && mapSize!=0 && map instanceof SortedMap) {
jaroslav@1258
   310
            Comparator c = ((SortedMap)map).comparator();
jaroslav@1258
   311
            if (c == comparator || (c != null && c.equals(comparator))) {
jaroslav@1258
   312
                ++modCount;
jaroslav@1258
   313
                try {
jaroslav@1258
   314
                    buildFromSorted(mapSize, map.entrySet().iterator(),
jaroslav@1258
   315
                                    null, null);
jaroslav@1258
   316
                } catch (java.io.IOException cannotHappen) {
jaroslav@1258
   317
                } catch (ClassNotFoundException cannotHappen) {
jaroslav@1258
   318
                }
jaroslav@1258
   319
                return;
jaroslav@1258
   320
            }
jaroslav@1258
   321
        }
jaroslav@1258
   322
        super.putAll(map);
jaroslav@1258
   323
    }
jaroslav@1258
   324
jaroslav@1258
   325
    /**
jaroslav@1258
   326
     * Returns this map's entry for the given key, or {@code null} if the map
jaroslav@1258
   327
     * does not contain an entry for the key.
jaroslav@1258
   328
     *
jaroslav@1258
   329
     * @return this map's entry for the given key, or {@code null} if the map
jaroslav@1258
   330
     *         does not contain an entry for the key
jaroslav@1258
   331
     * @throws ClassCastException if the specified key cannot be compared
jaroslav@1258
   332
     *         with the keys currently in the map
jaroslav@1258
   333
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   334
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   335
     *         does not permit null keys
jaroslav@1258
   336
     */
jaroslav@1258
   337
    final Entry<K,V> getEntry(Object key) {
jaroslav@1258
   338
        // Offload comparator-based version for sake of performance
jaroslav@1258
   339
        if (comparator != null)
jaroslav@1258
   340
            return getEntryUsingComparator(key);
jaroslav@1258
   341
        if (key == null)
jaroslav@1258
   342
            throw new NullPointerException();
jaroslav@1258
   343
        Comparable<? super K> k = (Comparable<? super K>) key;
jaroslav@1258
   344
        Entry<K,V> p = root;
jaroslav@1258
   345
        while (p != null) {
jaroslav@1258
   346
            int cmp = k.compareTo(p.key);
jaroslav@1258
   347
            if (cmp < 0)
jaroslav@1258
   348
                p = p.left;
jaroslav@1258
   349
            else if (cmp > 0)
jaroslav@1258
   350
                p = p.right;
jaroslav@1258
   351
            else
jaroslav@1258
   352
                return p;
jaroslav@1258
   353
        }
jaroslav@1258
   354
        return null;
jaroslav@1258
   355
    }
jaroslav@1258
   356
jaroslav@1258
   357
    /**
jaroslav@1258
   358
     * Version of getEntry using comparator. Split off from getEntry
jaroslav@1258
   359
     * for performance. (This is not worth doing for most methods,
jaroslav@1258
   360
     * that are less dependent on comparator performance, but is
jaroslav@1258
   361
     * worthwhile here.)
jaroslav@1258
   362
     */
jaroslav@1258
   363
    final Entry<K,V> getEntryUsingComparator(Object key) {
jaroslav@1258
   364
        K k = (K) key;
jaroslav@1258
   365
        Comparator<? super K> cpr = comparator;
jaroslav@1258
   366
        if (cpr != null) {
jaroslav@1258
   367
            Entry<K,V> p = root;
jaroslav@1258
   368
            while (p != null) {
jaroslav@1258
   369
                int cmp = cpr.compare(k, p.key);
jaroslav@1258
   370
                if (cmp < 0)
jaroslav@1258
   371
                    p = p.left;
jaroslav@1258
   372
                else if (cmp > 0)
jaroslav@1258
   373
                    p = p.right;
jaroslav@1258
   374
                else
jaroslav@1258
   375
                    return p;
jaroslav@1258
   376
            }
jaroslav@1258
   377
        }
jaroslav@1258
   378
        return null;
jaroslav@1258
   379
    }
jaroslav@1258
   380
jaroslav@1258
   381
    /**
jaroslav@1258
   382
     * Gets the entry corresponding to the specified key; if no such entry
jaroslav@1258
   383
     * exists, returns the entry for the least key greater than the specified
jaroslav@1258
   384
     * key; if no such entry exists (i.e., the greatest key in the Tree is less
jaroslav@1258
   385
     * than the specified key), returns {@code null}.
jaroslav@1258
   386
     */
jaroslav@1258
   387
    final Entry<K,V> getCeilingEntry(K key) {
jaroslav@1258
   388
        Entry<K,V> p = root;
jaroslav@1258
   389
        while (p != null) {
jaroslav@1258
   390
            int cmp = compare(key, p.key);
jaroslav@1258
   391
            if (cmp < 0) {
jaroslav@1258
   392
                if (p.left != null)
jaroslav@1258
   393
                    p = p.left;
jaroslav@1258
   394
                else
jaroslav@1258
   395
                    return p;
jaroslav@1258
   396
            } else if (cmp > 0) {
jaroslav@1258
   397
                if (p.right != null) {
jaroslav@1258
   398
                    p = p.right;
jaroslav@1258
   399
                } else {
jaroslav@1258
   400
                    Entry<K,V> parent = p.parent;
jaroslav@1258
   401
                    Entry<K,V> ch = p;
jaroslav@1258
   402
                    while (parent != null && ch == parent.right) {
jaroslav@1258
   403
                        ch = parent;
jaroslav@1258
   404
                        parent = parent.parent;
jaroslav@1258
   405
                    }
jaroslav@1258
   406
                    return parent;
jaroslav@1258
   407
                }
jaroslav@1258
   408
            } else
jaroslav@1258
   409
                return p;
jaroslav@1258
   410
        }
jaroslav@1258
   411
        return null;
jaroslav@1258
   412
    }
jaroslav@1258
   413
jaroslav@1258
   414
    /**
jaroslav@1258
   415
     * Gets the entry corresponding to the specified key; if no such entry
jaroslav@1258
   416
     * exists, returns the entry for the greatest key less than the specified
jaroslav@1258
   417
     * key; if no such entry exists, returns {@code null}.
jaroslav@1258
   418
     */
jaroslav@1258
   419
    final Entry<K,V> getFloorEntry(K key) {
jaroslav@1258
   420
        Entry<K,V> p = root;
jaroslav@1258
   421
        while (p != null) {
jaroslav@1258
   422
            int cmp = compare(key, p.key);
jaroslav@1258
   423
            if (cmp > 0) {
jaroslav@1258
   424
                if (p.right != null)
jaroslav@1258
   425
                    p = p.right;
jaroslav@1258
   426
                else
jaroslav@1258
   427
                    return p;
jaroslav@1258
   428
            } else if (cmp < 0) {
jaroslav@1258
   429
                if (p.left != null) {
jaroslav@1258
   430
                    p = p.left;
jaroslav@1258
   431
                } else {
jaroslav@1258
   432
                    Entry<K,V> parent = p.parent;
jaroslav@1258
   433
                    Entry<K,V> ch = p;
jaroslav@1258
   434
                    while (parent != null && ch == parent.left) {
jaroslav@1258
   435
                        ch = parent;
jaroslav@1258
   436
                        parent = parent.parent;
jaroslav@1258
   437
                    }
jaroslav@1258
   438
                    return parent;
jaroslav@1258
   439
                }
jaroslav@1258
   440
            } else
jaroslav@1258
   441
                return p;
jaroslav@1258
   442
jaroslav@1258
   443
        }
jaroslav@1258
   444
        return null;
jaroslav@1258
   445
    }
jaroslav@1258
   446
jaroslav@1258
   447
    /**
jaroslav@1258
   448
     * Gets the entry for the least key greater than the specified
jaroslav@1258
   449
     * key; if no such entry exists, returns the entry for the least
jaroslav@1258
   450
     * key greater than the specified key; if no such entry exists
jaroslav@1258
   451
     * returns {@code null}.
jaroslav@1258
   452
     */
jaroslav@1258
   453
    final Entry<K,V> getHigherEntry(K key) {
jaroslav@1258
   454
        Entry<K,V> p = root;
jaroslav@1258
   455
        while (p != null) {
jaroslav@1258
   456
            int cmp = compare(key, p.key);
jaroslav@1258
   457
            if (cmp < 0) {
jaroslav@1258
   458
                if (p.left != null)
jaroslav@1258
   459
                    p = p.left;
jaroslav@1258
   460
                else
jaroslav@1258
   461
                    return p;
jaroslav@1258
   462
            } else {
jaroslav@1258
   463
                if (p.right != null) {
jaroslav@1258
   464
                    p = p.right;
jaroslav@1258
   465
                } else {
jaroslav@1258
   466
                    Entry<K,V> parent = p.parent;
jaroslav@1258
   467
                    Entry<K,V> ch = p;
jaroslav@1258
   468
                    while (parent != null && ch == parent.right) {
jaroslav@1258
   469
                        ch = parent;
jaroslav@1258
   470
                        parent = parent.parent;
jaroslav@1258
   471
                    }
jaroslav@1258
   472
                    return parent;
jaroslav@1258
   473
                }
jaroslav@1258
   474
            }
jaroslav@1258
   475
        }
jaroslav@1258
   476
        return null;
jaroslav@1258
   477
    }
jaroslav@1258
   478
jaroslav@1258
   479
    /**
jaroslav@1258
   480
     * Returns the entry for the greatest key less than the specified key; if
jaroslav@1258
   481
     * no such entry exists (i.e., the least key in the Tree is greater than
jaroslav@1258
   482
     * the specified key), returns {@code null}.
jaroslav@1258
   483
     */
jaroslav@1258
   484
    final Entry<K,V> getLowerEntry(K key) {
jaroslav@1258
   485
        Entry<K,V> p = root;
jaroslav@1258
   486
        while (p != null) {
jaroslav@1258
   487
            int cmp = compare(key, p.key);
jaroslav@1258
   488
            if (cmp > 0) {
jaroslav@1258
   489
                if (p.right != null)
jaroslav@1258
   490
                    p = p.right;
jaroslav@1258
   491
                else
jaroslav@1258
   492
                    return p;
jaroslav@1258
   493
            } else {
jaroslav@1258
   494
                if (p.left != null) {
jaroslav@1258
   495
                    p = p.left;
jaroslav@1258
   496
                } else {
jaroslav@1258
   497
                    Entry<K,V> parent = p.parent;
jaroslav@1258
   498
                    Entry<K,V> ch = p;
jaroslav@1258
   499
                    while (parent != null && ch == parent.left) {
jaroslav@1258
   500
                        ch = parent;
jaroslav@1258
   501
                        parent = parent.parent;
jaroslav@1258
   502
                    }
jaroslav@1258
   503
                    return parent;
jaroslav@1258
   504
                }
jaroslav@1258
   505
            }
jaroslav@1258
   506
        }
jaroslav@1258
   507
        return null;
jaroslav@1258
   508
    }
jaroslav@1258
   509
jaroslav@1258
   510
    /**
jaroslav@1258
   511
     * Associates the specified value with the specified key in this map.
jaroslav@1258
   512
     * If the map previously contained a mapping for the key, the old
jaroslav@1258
   513
     * value is replaced.
jaroslav@1258
   514
     *
jaroslav@1258
   515
     * @param key key with which the specified value is to be associated
jaroslav@1258
   516
     * @param value value to be associated with the specified key
jaroslav@1258
   517
     *
jaroslav@1258
   518
     * @return the previous value associated with {@code key}, or
jaroslav@1258
   519
     *         {@code null} if there was no mapping for {@code key}.
jaroslav@1258
   520
     *         (A {@code null} return can also indicate that the map
jaroslav@1258
   521
     *         previously associated {@code null} with {@code key}.)
jaroslav@1258
   522
     * @throws ClassCastException if the specified key cannot be compared
jaroslav@1258
   523
     *         with the keys currently in the map
jaroslav@1258
   524
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   525
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   526
     *         does not permit null keys
jaroslav@1258
   527
     */
jaroslav@1258
   528
    public V put(K key, V value) {
jaroslav@1258
   529
        Entry<K,V> t = root;
jaroslav@1258
   530
        if (t == null) {
jaroslav@1258
   531
            compare(key, key); // type (and possibly null) check
jaroslav@1258
   532
jaroslav@1258
   533
            root = new Entry<>(key, value, null);
jaroslav@1258
   534
            size = 1;
jaroslav@1258
   535
            modCount++;
jaroslav@1258
   536
            return null;
jaroslav@1258
   537
        }
jaroslav@1258
   538
        int cmp;
jaroslav@1258
   539
        Entry<K,V> parent;
jaroslav@1258
   540
        // split comparator and comparable paths
jaroslav@1258
   541
        Comparator<? super K> cpr = comparator;
jaroslav@1258
   542
        if (cpr != null) {
jaroslav@1258
   543
            do {
jaroslav@1258
   544
                parent = t;
jaroslav@1258
   545
                cmp = cpr.compare(key, t.key);
jaroslav@1258
   546
                if (cmp < 0)
jaroslav@1258
   547
                    t = t.left;
jaroslav@1258
   548
                else if (cmp > 0)
jaroslav@1258
   549
                    t = t.right;
jaroslav@1258
   550
                else
jaroslav@1258
   551
                    return t.setValue(value);
jaroslav@1258
   552
            } while (t != null);
jaroslav@1258
   553
        }
jaroslav@1258
   554
        else {
jaroslav@1258
   555
            if (key == null)
jaroslav@1258
   556
                throw new NullPointerException();
jaroslav@1258
   557
            Comparable<? super K> k = (Comparable<? super K>) key;
jaroslav@1258
   558
            do {
jaroslav@1258
   559
                parent = t;
jaroslav@1258
   560
                cmp = k.compareTo(t.key);
jaroslav@1258
   561
                if (cmp < 0)
jaroslav@1258
   562
                    t = t.left;
jaroslav@1258
   563
                else if (cmp > 0)
jaroslav@1258
   564
                    t = t.right;
jaroslav@1258
   565
                else
jaroslav@1258
   566
                    return t.setValue(value);
jaroslav@1258
   567
            } while (t != null);
jaroslav@1258
   568
        }
jaroslav@1258
   569
        Entry<K,V> e = new Entry<>(key, value, parent);
jaroslav@1258
   570
        if (cmp < 0)
jaroslav@1258
   571
            parent.left = e;
jaroslav@1258
   572
        else
jaroslav@1258
   573
            parent.right = e;
jaroslav@1258
   574
        fixAfterInsertion(e);
jaroslav@1258
   575
        size++;
jaroslav@1258
   576
        modCount++;
jaroslav@1258
   577
        return null;
jaroslav@1258
   578
    }
jaroslav@1258
   579
jaroslav@1258
   580
    /**
jaroslav@1258
   581
     * Removes the mapping for this key from this TreeMap if present.
jaroslav@1258
   582
     *
jaroslav@1258
   583
     * @param  key key for which mapping should be removed
jaroslav@1258
   584
     * @return the previous value associated with {@code key}, or
jaroslav@1258
   585
     *         {@code null} if there was no mapping for {@code key}.
jaroslav@1258
   586
     *         (A {@code null} return can also indicate that the map
jaroslav@1258
   587
     *         previously associated {@code null} with {@code key}.)
jaroslav@1258
   588
     * @throws ClassCastException if the specified key cannot be compared
jaroslav@1258
   589
     *         with the keys currently in the map
jaroslav@1258
   590
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   591
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   592
     *         does not permit null keys
jaroslav@1258
   593
     */
jaroslav@1258
   594
    public V remove(Object key) {
jaroslav@1258
   595
        Entry<K,V> p = getEntry(key);
jaroslav@1258
   596
        if (p == null)
jaroslav@1258
   597
            return null;
jaroslav@1258
   598
jaroslav@1258
   599
        V oldValue = p.value;
jaroslav@1258
   600
        deleteEntry(p);
jaroslav@1258
   601
        return oldValue;
jaroslav@1258
   602
    }
jaroslav@1258
   603
jaroslav@1258
   604
    /**
jaroslav@1258
   605
     * Removes all of the mappings from this map.
jaroslav@1258
   606
     * The map will be empty after this call returns.
jaroslav@1258
   607
     */
jaroslav@1258
   608
    public void clear() {
jaroslav@1258
   609
        modCount++;
jaroslav@1258
   610
        size = 0;
jaroslav@1258
   611
        root = null;
jaroslav@1258
   612
    }
jaroslav@1258
   613
jaroslav@1258
   614
    /**
jaroslav@1258
   615
     * Returns a shallow copy of this {@code TreeMap} instance. (The keys and
jaroslav@1258
   616
     * values themselves are not cloned.)
jaroslav@1258
   617
     *
jaroslav@1258
   618
     * @return a shallow copy of this map
jaroslav@1258
   619
     */
jaroslav@1258
   620
    public Object clone() {
jaroslav@1258
   621
        TreeMap<K,V> clone = null;
jaroslav@1258
   622
        try {
jaroslav@1258
   623
            clone = (TreeMap<K,V>) super.clone();
jaroslav@1258
   624
        } catch (CloneNotSupportedException e) {
jaroslav@1258
   625
            throw new InternalError();
jaroslav@1258
   626
        }
jaroslav@1258
   627
jaroslav@1258
   628
        // Put clone into "virgin" state (except for comparator)
jaroslav@1258
   629
        clone.root = null;
jaroslav@1258
   630
        clone.size = 0;
jaroslav@1258
   631
        clone.modCount = 0;
jaroslav@1258
   632
        clone.entrySet = null;
jaroslav@1258
   633
        clone.navigableKeySet = null;
jaroslav@1258
   634
        clone.descendingMap = null;
jaroslav@1258
   635
jaroslav@1258
   636
        // Initialize clone with our mappings
jaroslav@1258
   637
        try {
jaroslav@1258
   638
            clone.buildFromSorted(size, entrySet().iterator(), null, null);
jaroslav@1258
   639
        } catch (java.io.IOException cannotHappen) {
jaroslav@1258
   640
        } catch (ClassNotFoundException cannotHappen) {
jaroslav@1258
   641
        }
jaroslav@1258
   642
jaroslav@1258
   643
        return clone;
jaroslav@1258
   644
    }
jaroslav@1258
   645
jaroslav@1258
   646
    // NavigableMap API methods
jaroslav@1258
   647
jaroslav@1258
   648
    /**
jaroslav@1258
   649
     * @since 1.6
jaroslav@1258
   650
     */
jaroslav@1258
   651
    public Map.Entry<K,V> firstEntry() {
jaroslav@1258
   652
        return exportEntry(getFirstEntry());
jaroslav@1258
   653
    }
jaroslav@1258
   654
jaroslav@1258
   655
    /**
jaroslav@1258
   656
     * @since 1.6
jaroslav@1258
   657
     */
jaroslav@1258
   658
    public Map.Entry<K,V> lastEntry() {
jaroslav@1258
   659
        return exportEntry(getLastEntry());
jaroslav@1258
   660
    }
jaroslav@1258
   661
jaroslav@1258
   662
    /**
jaroslav@1258
   663
     * @since 1.6
jaroslav@1258
   664
     */
jaroslav@1258
   665
    public Map.Entry<K,V> pollFirstEntry() {
jaroslav@1258
   666
        Entry<K,V> p = getFirstEntry();
jaroslav@1258
   667
        Map.Entry<K,V> result = exportEntry(p);
jaroslav@1258
   668
        if (p != null)
jaroslav@1258
   669
            deleteEntry(p);
jaroslav@1258
   670
        return result;
jaroslav@1258
   671
    }
jaroslav@1258
   672
jaroslav@1258
   673
    /**
jaroslav@1258
   674
     * @since 1.6
jaroslav@1258
   675
     */
jaroslav@1258
   676
    public Map.Entry<K,V> pollLastEntry() {
jaroslav@1258
   677
        Entry<K,V> p = getLastEntry();
jaroslav@1258
   678
        Map.Entry<K,V> result = exportEntry(p);
jaroslav@1258
   679
        if (p != null)
jaroslav@1258
   680
            deleteEntry(p);
jaroslav@1258
   681
        return result;
jaroslav@1258
   682
    }
jaroslav@1258
   683
jaroslav@1258
   684
    /**
jaroslav@1258
   685
     * @throws ClassCastException {@inheritDoc}
jaroslav@1258
   686
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   687
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   688
     *         does not permit null keys
jaroslav@1258
   689
     * @since 1.6
jaroslav@1258
   690
     */
jaroslav@1258
   691
    public Map.Entry<K,V> lowerEntry(K key) {
jaroslav@1258
   692
        return exportEntry(getLowerEntry(key));
jaroslav@1258
   693
    }
jaroslav@1258
   694
jaroslav@1258
   695
    /**
jaroslav@1258
   696
     * @throws ClassCastException {@inheritDoc}
jaroslav@1258
   697
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   698
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   699
     *         does not permit null keys
jaroslav@1258
   700
     * @since 1.6
jaroslav@1258
   701
     */
jaroslav@1258
   702
    public K lowerKey(K key) {
jaroslav@1258
   703
        return keyOrNull(getLowerEntry(key));
jaroslav@1258
   704
    }
jaroslav@1258
   705
jaroslav@1258
   706
    /**
jaroslav@1258
   707
     * @throws ClassCastException {@inheritDoc}
jaroslav@1258
   708
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   709
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   710
     *         does not permit null keys
jaroslav@1258
   711
     * @since 1.6
jaroslav@1258
   712
     */
jaroslav@1258
   713
    public Map.Entry<K,V> floorEntry(K key) {
jaroslav@1258
   714
        return exportEntry(getFloorEntry(key));
jaroslav@1258
   715
    }
jaroslav@1258
   716
jaroslav@1258
   717
    /**
jaroslav@1258
   718
     * @throws ClassCastException {@inheritDoc}
jaroslav@1258
   719
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   720
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   721
     *         does not permit null keys
jaroslav@1258
   722
     * @since 1.6
jaroslav@1258
   723
     */
jaroslav@1258
   724
    public K floorKey(K key) {
jaroslav@1258
   725
        return keyOrNull(getFloorEntry(key));
jaroslav@1258
   726
    }
jaroslav@1258
   727
jaroslav@1258
   728
    /**
jaroslav@1258
   729
     * @throws ClassCastException {@inheritDoc}
jaroslav@1258
   730
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   731
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   732
     *         does not permit null keys
jaroslav@1258
   733
     * @since 1.6
jaroslav@1258
   734
     */
jaroslav@1258
   735
    public Map.Entry<K,V> ceilingEntry(K key) {
jaroslav@1258
   736
        return exportEntry(getCeilingEntry(key));
jaroslav@1258
   737
    }
jaroslav@1258
   738
jaroslav@1258
   739
    /**
jaroslav@1258
   740
     * @throws ClassCastException {@inheritDoc}
jaroslav@1258
   741
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   742
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   743
     *         does not permit null keys
jaroslav@1258
   744
     * @since 1.6
jaroslav@1258
   745
     */
jaroslav@1258
   746
    public K ceilingKey(K key) {
jaroslav@1258
   747
        return keyOrNull(getCeilingEntry(key));
jaroslav@1258
   748
    }
jaroslav@1258
   749
jaroslav@1258
   750
    /**
jaroslav@1258
   751
     * @throws ClassCastException {@inheritDoc}
jaroslav@1258
   752
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   753
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   754
     *         does not permit null keys
jaroslav@1258
   755
     * @since 1.6
jaroslav@1258
   756
     */
jaroslav@1258
   757
    public Map.Entry<K,V> higherEntry(K key) {
jaroslav@1258
   758
        return exportEntry(getHigherEntry(key));
jaroslav@1258
   759
    }
jaroslav@1258
   760
jaroslav@1258
   761
    /**
jaroslav@1258
   762
     * @throws ClassCastException {@inheritDoc}
jaroslav@1258
   763
     * @throws NullPointerException if the specified key is null
jaroslav@1258
   764
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   765
     *         does not permit null keys
jaroslav@1258
   766
     * @since 1.6
jaroslav@1258
   767
     */
jaroslav@1258
   768
    public K higherKey(K key) {
jaroslav@1258
   769
        return keyOrNull(getHigherEntry(key));
jaroslav@1258
   770
    }
jaroslav@1258
   771
jaroslav@1258
   772
    // Views
jaroslav@1258
   773
jaroslav@1258
   774
    /**
jaroslav@1258
   775
     * Fields initialized to contain an instance of the entry set view
jaroslav@1258
   776
     * the first time this view is requested.  Views are stateless, so
jaroslav@1258
   777
     * there's no reason to create more than one.
jaroslav@1258
   778
     */
jaroslav@1258
   779
    private transient EntrySet entrySet = null;
jaroslav@1258
   780
    private transient KeySet<K> navigableKeySet = null;
jaroslav@1258
   781
    private transient NavigableMap<K,V> descendingMap = null;
jaroslav@1258
   782
jaroslav@1258
   783
    /**
jaroslav@1258
   784
     * Returns a {@link Set} view of the keys contained in this map.
jaroslav@1258
   785
     * The set's iterator returns the keys in ascending order.
jaroslav@1258
   786
     * The set is backed by the map, so changes to the map are
jaroslav@1258
   787
     * reflected in the set, and vice-versa.  If the map is modified
jaroslav@1258
   788
     * while an iteration over the set is in progress (except through
jaroslav@1258
   789
     * the iterator's own {@code remove} operation), the results of
jaroslav@1258
   790
     * the iteration are undefined.  The set supports element removal,
jaroslav@1258
   791
     * which removes the corresponding mapping from the map, via the
jaroslav@1258
   792
     * {@code Iterator.remove}, {@code Set.remove},
jaroslav@1258
   793
     * {@code removeAll}, {@code retainAll}, and {@code clear}
jaroslav@1258
   794
     * operations.  It does not support the {@code add} or {@code addAll}
jaroslav@1258
   795
     * operations.
jaroslav@1258
   796
     */
jaroslav@1258
   797
    public Set<K> keySet() {
jaroslav@1258
   798
        return navigableKeySet();
jaroslav@1258
   799
    }
jaroslav@1258
   800
jaroslav@1258
   801
    /**
jaroslav@1258
   802
     * @since 1.6
jaroslav@1258
   803
     */
jaroslav@1258
   804
    public NavigableSet<K> navigableKeySet() {
jaroslav@1258
   805
        KeySet<K> nks = navigableKeySet;
jaroslav@1258
   806
        return (nks != null) ? nks : (navigableKeySet = new KeySet(this));
jaroslav@1258
   807
    }
jaroslav@1258
   808
jaroslav@1258
   809
    /**
jaroslav@1258
   810
     * @since 1.6
jaroslav@1258
   811
     */
jaroslav@1258
   812
    public NavigableSet<K> descendingKeySet() {
jaroslav@1258
   813
        return descendingMap().navigableKeySet();
jaroslav@1258
   814
    }
jaroslav@1258
   815
jaroslav@1258
   816
    /**
jaroslav@1258
   817
     * Returns a {@link Collection} view of the values contained in this map.
jaroslav@1258
   818
     * The collection's iterator returns the values in ascending order
jaroslav@1258
   819
     * of the corresponding keys.
jaroslav@1258
   820
     * The collection is backed by the map, so changes to the map are
jaroslav@1258
   821
     * reflected in the collection, and vice-versa.  If the map is
jaroslav@1258
   822
     * modified while an iteration over the collection is in progress
jaroslav@1258
   823
     * (except through the iterator's own {@code remove} operation),
jaroslav@1258
   824
     * the results of the iteration are undefined.  The collection
jaroslav@1258
   825
     * supports element removal, which removes the corresponding
jaroslav@1258
   826
     * mapping from the map, via the {@code Iterator.remove},
jaroslav@1258
   827
     * {@code Collection.remove}, {@code removeAll},
jaroslav@1258
   828
     * {@code retainAll} and {@code clear} operations.  It does not
jaroslav@1258
   829
     * support the {@code add} or {@code addAll} operations.
jaroslav@1258
   830
     */
jaroslav@1258
   831
    public Collection<V> values() {
jaroslav@1258
   832
        Collection<V> vs = values;
jaroslav@1258
   833
        return (vs != null) ? vs : (values = new Values());
jaroslav@1258
   834
    }
jaroslav@1258
   835
jaroslav@1258
   836
    /**
jaroslav@1258
   837
     * Returns a {@link Set} view of the mappings contained in this map.
jaroslav@1258
   838
     * The set's iterator returns the entries in ascending key order.
jaroslav@1258
   839
     * The set is backed by the map, so changes to the map are
jaroslav@1258
   840
     * reflected in the set, and vice-versa.  If the map is modified
jaroslav@1258
   841
     * while an iteration over the set is in progress (except through
jaroslav@1258
   842
     * the iterator's own {@code remove} operation, or through the
jaroslav@1258
   843
     * {@code setValue} operation on a map entry returned by the
jaroslav@1258
   844
     * iterator) the results of the iteration are undefined.  The set
jaroslav@1258
   845
     * supports element removal, which removes the corresponding
jaroslav@1258
   846
     * mapping from the map, via the {@code Iterator.remove},
jaroslav@1258
   847
     * {@code Set.remove}, {@code removeAll}, {@code retainAll} and
jaroslav@1258
   848
     * {@code clear} operations.  It does not support the
jaroslav@1258
   849
     * {@code add} or {@code addAll} operations.
jaroslav@1258
   850
     */
jaroslav@1258
   851
    public Set<Map.Entry<K,V>> entrySet() {
jaroslav@1258
   852
        EntrySet es = entrySet;
jaroslav@1258
   853
        return (es != null) ? es : (entrySet = new EntrySet());
jaroslav@1258
   854
    }
jaroslav@1258
   855
jaroslav@1258
   856
    /**
jaroslav@1258
   857
     * @since 1.6
jaroslav@1258
   858
     */
jaroslav@1258
   859
    public NavigableMap<K, V> descendingMap() {
jaroslav@1258
   860
        NavigableMap<K, V> km = descendingMap;
jaroslav@1258
   861
        return (km != null) ? km :
jaroslav@1258
   862
            (descendingMap = new DescendingSubMap(this,
jaroslav@1258
   863
                                                  true, null, true,
jaroslav@1258
   864
                                                  true, null, true));
jaroslav@1258
   865
    }
jaroslav@1258
   866
jaroslav@1258
   867
    /**
jaroslav@1258
   868
     * @throws ClassCastException       {@inheritDoc}
jaroslav@1258
   869
     * @throws NullPointerException if {@code fromKey} or {@code toKey} is
jaroslav@1258
   870
     *         null and this map uses natural ordering, or its comparator
jaroslav@1258
   871
     *         does not permit null keys
jaroslav@1258
   872
     * @throws IllegalArgumentException {@inheritDoc}
jaroslav@1258
   873
     * @since 1.6
jaroslav@1258
   874
     */
jaroslav@1258
   875
    public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
jaroslav@1258
   876
                                    K toKey,   boolean toInclusive) {
jaroslav@1258
   877
        return new AscendingSubMap(this,
jaroslav@1258
   878
                                   false, fromKey, fromInclusive,
jaroslav@1258
   879
                                   false, toKey,   toInclusive);
jaroslav@1258
   880
    }
jaroslav@1258
   881
jaroslav@1258
   882
    /**
jaroslav@1258
   883
     * @throws ClassCastException       {@inheritDoc}
jaroslav@1258
   884
     * @throws NullPointerException if {@code toKey} is null
jaroslav@1258
   885
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   886
     *         does not permit null keys
jaroslav@1258
   887
     * @throws IllegalArgumentException {@inheritDoc}
jaroslav@1258
   888
     * @since 1.6
jaroslav@1258
   889
     */
jaroslav@1258
   890
    public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
jaroslav@1258
   891
        return new AscendingSubMap(this,
jaroslav@1258
   892
                                   true,  null,  true,
jaroslav@1258
   893
                                   false, toKey, inclusive);
jaroslav@1258
   894
    }
jaroslav@1258
   895
jaroslav@1258
   896
    /**
jaroslav@1258
   897
     * @throws ClassCastException       {@inheritDoc}
jaroslav@1258
   898
     * @throws NullPointerException if {@code fromKey} is null
jaroslav@1258
   899
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   900
     *         does not permit null keys
jaroslav@1258
   901
     * @throws IllegalArgumentException {@inheritDoc}
jaroslav@1258
   902
     * @since 1.6
jaroslav@1258
   903
     */
jaroslav@1258
   904
    public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
jaroslav@1258
   905
        return new AscendingSubMap(this,
jaroslav@1258
   906
                                   false, fromKey, inclusive,
jaroslav@1258
   907
                                   true,  null,    true);
jaroslav@1258
   908
    }
jaroslav@1258
   909
jaroslav@1258
   910
    /**
jaroslav@1258
   911
     * @throws ClassCastException       {@inheritDoc}
jaroslav@1258
   912
     * @throws NullPointerException if {@code fromKey} or {@code toKey} is
jaroslav@1258
   913
     *         null and this map uses natural ordering, or its comparator
jaroslav@1258
   914
     *         does not permit null keys
jaroslav@1258
   915
     * @throws IllegalArgumentException {@inheritDoc}
jaroslav@1258
   916
     */
jaroslav@1258
   917
    public SortedMap<K,V> subMap(K fromKey, K toKey) {
jaroslav@1258
   918
        return subMap(fromKey, true, toKey, false);
jaroslav@1258
   919
    }
jaroslav@1258
   920
jaroslav@1258
   921
    /**
jaroslav@1258
   922
     * @throws ClassCastException       {@inheritDoc}
jaroslav@1258
   923
     * @throws NullPointerException if {@code toKey} is null
jaroslav@1258
   924
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   925
     *         does not permit null keys
jaroslav@1258
   926
     * @throws IllegalArgumentException {@inheritDoc}
jaroslav@1258
   927
     */
jaroslav@1258
   928
    public SortedMap<K,V> headMap(K toKey) {
jaroslav@1258
   929
        return headMap(toKey, false);
jaroslav@1258
   930
    }
jaroslav@1258
   931
jaroslav@1258
   932
    /**
jaroslav@1258
   933
     * @throws ClassCastException       {@inheritDoc}
jaroslav@1258
   934
     * @throws NullPointerException if {@code fromKey} is null
jaroslav@1258
   935
     *         and this map uses natural ordering, or its comparator
jaroslav@1258
   936
     *         does not permit null keys
jaroslav@1258
   937
     * @throws IllegalArgumentException {@inheritDoc}
jaroslav@1258
   938
     */
jaroslav@1258
   939
    public SortedMap<K,V> tailMap(K fromKey) {
jaroslav@1258
   940
        return tailMap(fromKey, true);
jaroslav@1258
   941
    }
jaroslav@1258
   942
jaroslav@1258
   943
    // View class support
jaroslav@1258
   944
jaroslav@1258
   945
    class Values extends AbstractCollection<V> {
jaroslav@1258
   946
        public Iterator<V> iterator() {
jaroslav@1258
   947
            return new ValueIterator(getFirstEntry());
jaroslav@1258
   948
        }
jaroslav@1258
   949
jaroslav@1258
   950
        public int size() {
jaroslav@1258
   951
            return TreeMap.this.size();
jaroslav@1258
   952
        }
jaroslav@1258
   953
jaroslav@1258
   954
        public boolean contains(Object o) {
jaroslav@1258
   955
            return TreeMap.this.containsValue(o);
jaroslav@1258
   956
        }
jaroslav@1258
   957
jaroslav@1258
   958
        public boolean remove(Object o) {
jaroslav@1258
   959
            for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) {
jaroslav@1258
   960
                if (valEquals(e.getValue(), o)) {
jaroslav@1258
   961
                    deleteEntry(e);
jaroslav@1258
   962
                    return true;
jaroslav@1258
   963
                }
jaroslav@1258
   964
            }
jaroslav@1258
   965
            return false;
jaroslav@1258
   966
        }
jaroslav@1258
   967
jaroslav@1258
   968
        public void clear() {
jaroslav@1258
   969
            TreeMap.this.clear();
jaroslav@1258
   970
        }
jaroslav@1258
   971
    }
jaroslav@1258
   972
jaroslav@1258
   973
    class EntrySet extends AbstractSet<Map.Entry<K,V>> {
jaroslav@1258
   974
        public Iterator<Map.Entry<K,V>> iterator() {
jaroslav@1258
   975
            return new EntryIterator(getFirstEntry());
jaroslav@1258
   976
        }
jaroslav@1258
   977
jaroslav@1258
   978
        public boolean contains(Object o) {
jaroslav@1258
   979
            if (!(o instanceof Map.Entry))
jaroslav@1258
   980
                return false;
jaroslav@1258
   981
            Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
jaroslav@1258
   982
            V value = entry.getValue();
jaroslav@1258
   983
            Entry<K,V> p = getEntry(entry.getKey());
jaroslav@1258
   984
            return p != null && valEquals(p.getValue(), value);
jaroslav@1258
   985
        }
jaroslav@1258
   986
jaroslav@1258
   987
        public boolean remove(Object o) {
jaroslav@1258
   988
            if (!(o instanceof Map.Entry))
jaroslav@1258
   989
                return false;
jaroslav@1258
   990
            Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
jaroslav@1258
   991
            V value = entry.getValue();
jaroslav@1258
   992
            Entry<K,V> p = getEntry(entry.getKey());
jaroslav@1258
   993
            if (p != null && valEquals(p.getValue(), value)) {
jaroslav@1258
   994
                deleteEntry(p);
jaroslav@1258
   995
                return true;
jaroslav@1258
   996
            }
jaroslav@1258
   997
            return false;
jaroslav@1258
   998
        }
jaroslav@1258
   999
jaroslav@1258
  1000
        public int size() {
jaroslav@1258
  1001
            return TreeMap.this.size();
jaroslav@1258
  1002
        }
jaroslav@1258
  1003
jaroslav@1258
  1004
        public void clear() {
jaroslav@1258
  1005
            TreeMap.this.clear();
jaroslav@1258
  1006
        }
jaroslav@1258
  1007
    }
jaroslav@1258
  1008
jaroslav@1258
  1009
    /*
jaroslav@1258
  1010
     * Unlike Values and EntrySet, the KeySet class is static,
jaroslav@1258
  1011
     * delegating to a NavigableMap to allow use by SubMaps, which
jaroslav@1258
  1012
     * outweighs the ugliness of needing type-tests for the following
jaroslav@1258
  1013
     * Iterator methods that are defined appropriately in main versus
jaroslav@1258
  1014
     * submap classes.
jaroslav@1258
  1015
     */
jaroslav@1258
  1016
jaroslav@1258
  1017
    Iterator<K> keyIterator() {
jaroslav@1258
  1018
        return new KeyIterator(getFirstEntry());
jaroslav@1258
  1019
    }
jaroslav@1258
  1020
jaroslav@1258
  1021
    Iterator<K> descendingKeyIterator() {
jaroslav@1258
  1022
        return new DescendingKeyIterator(getLastEntry());
jaroslav@1258
  1023
    }
jaroslav@1258
  1024
jaroslav@1258
  1025
    static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {
jaroslav@1258
  1026
        private final NavigableMap<E, Object> m;
jaroslav@1258
  1027
        KeySet(NavigableMap<E,Object> map) { m = map; }
jaroslav@1258
  1028
jaroslav@1258
  1029
        public Iterator<E> iterator() {
jaroslav@1258
  1030
            if (m instanceof TreeMap)
jaroslav@1258
  1031
                return ((TreeMap<E,Object>)m).keyIterator();
jaroslav@1258
  1032
            else
jaroslav@1258
  1033
                return (Iterator<E>)(((TreeMap.NavigableSubMap)m).keyIterator());
jaroslav@1258
  1034
        }
jaroslav@1258
  1035
jaroslav@1258
  1036
        public Iterator<E> descendingIterator() {
jaroslav@1258
  1037
            if (m instanceof TreeMap)
jaroslav@1258
  1038
                return ((TreeMap<E,Object>)m).descendingKeyIterator();
jaroslav@1258
  1039
            else
jaroslav@1258
  1040
                return (Iterator<E>)(((TreeMap.NavigableSubMap)m).descendingKeyIterator());
jaroslav@1258
  1041
        }
jaroslav@1258
  1042
jaroslav@1258
  1043
        public int size() { return m.size(); }
jaroslav@1258
  1044
        public boolean isEmpty() { return m.isEmpty(); }
jaroslav@1258
  1045
        public boolean contains(Object o) { return m.containsKey(o); }
jaroslav@1258
  1046
        public void clear() { m.clear(); }
jaroslav@1258
  1047
        public E lower(E e) { return m.lowerKey(e); }
jaroslav@1258
  1048
        public E floor(E e) { return m.floorKey(e); }
jaroslav@1258
  1049
        public E ceiling(E e) { return m.ceilingKey(e); }
jaroslav@1258
  1050
        public E higher(E e) { return m.higherKey(e); }
jaroslav@1258
  1051
        public E first() { return m.firstKey(); }
jaroslav@1258
  1052
        public E last() { return m.lastKey(); }
jaroslav@1258
  1053
        public Comparator<? super E> comparator() { return m.comparator(); }
jaroslav@1258
  1054
        public E pollFirst() {
jaroslav@1258
  1055
            Map.Entry<E,Object> e = m.pollFirstEntry();
jaroslav@1258
  1056
            return (e == null) ? null : e.getKey();
jaroslav@1258
  1057
        }
jaroslav@1258
  1058
        public E pollLast() {
jaroslav@1258
  1059
            Map.Entry<E,Object> e = m.pollLastEntry();
jaroslav@1258
  1060
            return (e == null) ? null : e.getKey();
jaroslav@1258
  1061
        }
jaroslav@1258
  1062
        public boolean remove(Object o) {
jaroslav@1258
  1063
            int oldSize = size();
jaroslav@1258
  1064
            m.remove(o);
jaroslav@1258
  1065
            return size() != oldSize;
jaroslav@1258
  1066
        }
jaroslav@1258
  1067
        public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
jaroslav@1258
  1068
                                      E toElement,   boolean toInclusive) {
jaroslav@1258
  1069
            return new KeySet<>(m.subMap(fromElement, fromInclusive,
jaroslav@1258
  1070
                                          toElement,   toInclusive));
jaroslav@1258
  1071
        }
jaroslav@1258
  1072
        public NavigableSet<E> headSet(E toElement, boolean inclusive) {
jaroslav@1258
  1073
            return new KeySet<>(m.headMap(toElement, inclusive));
jaroslav@1258
  1074
        }
jaroslav@1258
  1075
        public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
jaroslav@1258
  1076
            return new KeySet<>(m.tailMap(fromElement, inclusive));
jaroslav@1258
  1077
        }
jaroslav@1258
  1078
        public SortedSet<E> subSet(E fromElement, E toElement) {
jaroslav@1258
  1079
            return subSet(fromElement, true, toElement, false);
jaroslav@1258
  1080
        }
jaroslav@1258
  1081
        public SortedSet<E> headSet(E toElement) {
jaroslav@1258
  1082
            return headSet(toElement, false);
jaroslav@1258
  1083
        }
jaroslav@1258
  1084
        public SortedSet<E> tailSet(E fromElement) {
jaroslav@1258
  1085
            return tailSet(fromElement, true);
jaroslav@1258
  1086
        }
jaroslav@1258
  1087
        public NavigableSet<E> descendingSet() {
jaroslav@1258
  1088
            return new KeySet(m.descendingMap());
jaroslav@1258
  1089
        }
jaroslav@1258
  1090
    }
jaroslav@1258
  1091
jaroslav@1258
  1092
    /**
jaroslav@1258
  1093
     * Base class for TreeMap Iterators
jaroslav@1258
  1094
     */
jaroslav@1258
  1095
    abstract class PrivateEntryIterator<T> implements Iterator<T> {
jaroslav@1258
  1096
        Entry<K,V> next;
jaroslav@1258
  1097
        Entry<K,V> lastReturned;
jaroslav@1258
  1098
        int expectedModCount;
jaroslav@1258
  1099
jaroslav@1258
  1100
        PrivateEntryIterator(Entry<K,V> first) {
jaroslav@1258
  1101
            expectedModCount = modCount;
jaroslav@1258
  1102
            lastReturned = null;
jaroslav@1258
  1103
            next = first;
jaroslav@1258
  1104
        }
jaroslav@1258
  1105
jaroslav@1258
  1106
        public final boolean hasNext() {
jaroslav@1258
  1107
            return next != null;
jaroslav@1258
  1108
        }
jaroslav@1258
  1109
jaroslav@1258
  1110
        final Entry<K,V> nextEntry() {
jaroslav@1258
  1111
            Entry<K,V> e = next;
jaroslav@1258
  1112
            if (e == null)
jaroslav@1258
  1113
                throw new NoSuchElementException();
jaroslav@1258
  1114
            if (modCount != expectedModCount)
jaroslav@1258
  1115
                throw new ConcurrentModificationException();
jaroslav@1258
  1116
            next = successor(e);
jaroslav@1258
  1117
            lastReturned = e;
jaroslav@1258
  1118
            return e;
jaroslav@1258
  1119
        }
jaroslav@1258
  1120
jaroslav@1258
  1121
        final Entry<K,V> prevEntry() {
jaroslav@1258
  1122
            Entry<K,V> e = next;
jaroslav@1258
  1123
            if (e == null)
jaroslav@1258
  1124
                throw new NoSuchElementException();
jaroslav@1258
  1125
            if (modCount != expectedModCount)
jaroslav@1258
  1126
                throw new ConcurrentModificationException();
jaroslav@1258
  1127
            next = predecessor(e);
jaroslav@1258
  1128
            lastReturned = e;
jaroslav@1258
  1129
            return e;
jaroslav@1258
  1130
        }
jaroslav@1258
  1131
jaroslav@1258
  1132
        public void remove() {
jaroslav@1258
  1133
            if (lastReturned == null)
jaroslav@1258
  1134
                throw new IllegalStateException();
jaroslav@1258
  1135
            if (modCount != expectedModCount)
jaroslav@1258
  1136
                throw new ConcurrentModificationException();
jaroslav@1258
  1137
            // deleted entries are replaced by their successors
jaroslav@1258
  1138
            if (lastReturned.left != null && lastReturned.right != null)
jaroslav@1258
  1139
                next = lastReturned;
jaroslav@1258
  1140
            deleteEntry(lastReturned);
jaroslav@1258
  1141
            expectedModCount = modCount;
jaroslav@1258
  1142
            lastReturned = null;
jaroslav@1258
  1143
        }
jaroslav@1258
  1144
    }
jaroslav@1258
  1145
jaroslav@1258
  1146
    final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> {
jaroslav@1258
  1147
        EntryIterator(Entry<K,V> first) {
jaroslav@1258
  1148
            super(first);
jaroslav@1258
  1149
        }
jaroslav@1258
  1150
        public Map.Entry<K,V> next() {
jaroslav@1258
  1151
            return nextEntry();
jaroslav@1258
  1152
        }
jaroslav@1258
  1153
    }
jaroslav@1258
  1154
jaroslav@1258
  1155
    final class ValueIterator extends PrivateEntryIterator<V> {
jaroslav@1258
  1156
        ValueIterator(Entry<K,V> first) {
jaroslav@1258
  1157
            super(first);
jaroslav@1258
  1158
        }
jaroslav@1258
  1159
        public V next() {
jaroslav@1258
  1160
            return nextEntry().value;
jaroslav@1258
  1161
        }
jaroslav@1258
  1162
    }
jaroslav@1258
  1163
jaroslav@1258
  1164
    final class KeyIterator extends PrivateEntryIterator<K> {
jaroslav@1258
  1165
        KeyIterator(Entry<K,V> first) {
jaroslav@1258
  1166
            super(first);
jaroslav@1258
  1167
        }
jaroslav@1258
  1168
        public K next() {
jaroslav@1258
  1169
            return nextEntry().key;
jaroslav@1258
  1170
        }
jaroslav@1258
  1171
    }
jaroslav@1258
  1172
jaroslav@1258
  1173
    final class DescendingKeyIterator extends PrivateEntryIterator<K> {
jaroslav@1258
  1174
        DescendingKeyIterator(Entry<K,V> first) {
jaroslav@1258
  1175
            super(first);
jaroslav@1258
  1176
        }
jaroslav@1258
  1177
        public K next() {
jaroslav@1258
  1178
            return prevEntry().key;
jaroslav@1258
  1179
        }
jaroslav@1258
  1180
    }
jaroslav@1258
  1181
jaroslav@1258
  1182
    // Little utilities
jaroslav@1258
  1183
jaroslav@1258
  1184
    /**
jaroslav@1258
  1185
     * Compares two keys using the correct comparison method for this TreeMap.
jaroslav@1258
  1186
     */
jaroslav@1258
  1187
    final int compare(Object k1, Object k2) {
jaroslav@1258
  1188
        return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
jaroslav@1258
  1189
            : comparator.compare((K)k1, (K)k2);
jaroslav@1258
  1190
    }
jaroslav@1258
  1191
jaroslav@1258
  1192
    /**
jaroslav@1258
  1193
     * Test two values for equality.  Differs from o1.equals(o2) only in
jaroslav@1258
  1194
     * that it copes with {@code null} o1 properly.
jaroslav@1258
  1195
     */
jaroslav@1258
  1196
    static final boolean valEquals(Object o1, Object o2) {
jaroslav@1258
  1197
        return (o1==null ? o2==null : o1.equals(o2));
jaroslav@1258
  1198
    }
jaroslav@1258
  1199
jaroslav@1258
  1200
    /**
jaroslav@1258
  1201
     * Return SimpleImmutableEntry for entry, or null if null
jaroslav@1258
  1202
     */
jaroslav@1258
  1203
    static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
jaroslav@1258
  1204
        return (e == null) ? null :
jaroslav@1258
  1205
            new AbstractMap.SimpleImmutableEntry<>(e);
jaroslav@1258
  1206
    }
jaroslav@1258
  1207
jaroslav@1258
  1208
    /**
jaroslav@1258
  1209
     * Return key for entry, or null if null
jaroslav@1258
  1210
     */
jaroslav@1258
  1211
    static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) {
jaroslav@1258
  1212
        return (e == null) ? null : e.key;
jaroslav@1258
  1213
    }
jaroslav@1258
  1214
jaroslav@1258
  1215
    /**
jaroslav@1258
  1216
     * Returns the key corresponding to the specified Entry.
jaroslav@1258
  1217
     * @throws NoSuchElementException if the Entry is null
jaroslav@1258
  1218
     */
jaroslav@1258
  1219
    static <K> K key(Entry<K,?> e) {
jaroslav@1258
  1220
        if (e==null)
jaroslav@1258
  1221
            throw new NoSuchElementException();
jaroslav@1258
  1222
        return e.key;
jaroslav@1258
  1223
    }
jaroslav@1258
  1224
jaroslav@1258
  1225
jaroslav@1258
  1226
    // SubMaps
jaroslav@1258
  1227
jaroslav@1258
  1228
    /**
jaroslav@1258
  1229
     * Dummy value serving as unmatchable fence key for unbounded
jaroslav@1258
  1230
     * SubMapIterators
jaroslav@1258
  1231
     */
jaroslav@1258
  1232
    private static final Object UNBOUNDED = new Object();
jaroslav@1258
  1233
jaroslav@1258
  1234
    /**
jaroslav@1258
  1235
     * @serial include
jaroslav@1258
  1236
     */
jaroslav@1258
  1237
    abstract static class NavigableSubMap<K,V> extends AbstractMap<K,V>
jaroslav@1258
  1238
        implements NavigableMap<K,V>, java.io.Serializable {
jaroslav@1258
  1239
        /**
jaroslav@1258
  1240
         * The backing map.
jaroslav@1258
  1241
         */
jaroslav@1258
  1242
        final TreeMap<K,V> m;
jaroslav@1258
  1243
jaroslav@1258
  1244
        /**
jaroslav@1258
  1245
         * Endpoints are represented as triples (fromStart, lo,
jaroslav@1258
  1246
         * loInclusive) and (toEnd, hi, hiInclusive). If fromStart is
jaroslav@1258
  1247
         * true, then the low (absolute) bound is the start of the
jaroslav@1258
  1248
         * backing map, and the other values are ignored. Otherwise,
jaroslav@1258
  1249
         * if loInclusive is true, lo is the inclusive bound, else lo
jaroslav@1258
  1250
         * is the exclusive bound. Similarly for the upper bound.
jaroslav@1258
  1251
         */
jaroslav@1258
  1252
        final K lo, hi;
jaroslav@1258
  1253
        final boolean fromStart, toEnd;
jaroslav@1258
  1254
        final boolean loInclusive, hiInclusive;
jaroslav@1258
  1255
jaroslav@1258
  1256
        NavigableSubMap(TreeMap<K,V> m,
jaroslav@1258
  1257
                        boolean fromStart, K lo, boolean loInclusive,
jaroslav@1258
  1258
                        boolean toEnd,     K hi, boolean hiInclusive) {
jaroslav@1258
  1259
            if (!fromStart && !toEnd) {
jaroslav@1258
  1260
                if (m.compare(lo, hi) > 0)
jaroslav@1258
  1261
                    throw new IllegalArgumentException("fromKey > toKey");
jaroslav@1258
  1262
            } else {
jaroslav@1258
  1263
                if (!fromStart) // type check
jaroslav@1258
  1264
                    m.compare(lo, lo);
jaroslav@1258
  1265
                if (!toEnd)
jaroslav@1258
  1266
                    m.compare(hi, hi);
jaroslav@1258
  1267
            }
jaroslav@1258
  1268
jaroslav@1258
  1269
            this.m = m;
jaroslav@1258
  1270
            this.fromStart = fromStart;
jaroslav@1258
  1271
            this.lo = lo;
jaroslav@1258
  1272
            this.loInclusive = loInclusive;
jaroslav@1258
  1273
            this.toEnd = toEnd;
jaroslav@1258
  1274
            this.hi = hi;
jaroslav@1258
  1275
            this.hiInclusive = hiInclusive;
jaroslav@1258
  1276
        }
jaroslav@1258
  1277
jaroslav@1258
  1278
        // internal utilities
jaroslav@1258
  1279
jaroslav@1258
  1280
        final boolean tooLow(Object key) {
jaroslav@1258
  1281
            if (!fromStart) {
jaroslav@1258
  1282
                int c = m.compare(key, lo);
jaroslav@1258
  1283
                if (c < 0 || (c == 0 && !loInclusive))
jaroslav@1258
  1284
                    return true;
jaroslav@1258
  1285
            }
jaroslav@1258
  1286
            return false;
jaroslav@1258
  1287
        }
jaroslav@1258
  1288
jaroslav@1258
  1289
        final boolean tooHigh(Object key) {
jaroslav@1258
  1290
            if (!toEnd) {
jaroslav@1258
  1291
                int c = m.compare(key, hi);
jaroslav@1258
  1292
                if (c > 0 || (c == 0 && !hiInclusive))
jaroslav@1258
  1293
                    return true;
jaroslav@1258
  1294
            }
jaroslav@1258
  1295
            return false;
jaroslav@1258
  1296
        }
jaroslav@1258
  1297
jaroslav@1258
  1298
        final boolean inRange(Object key) {
jaroslav@1258
  1299
            return !tooLow(key) && !tooHigh(key);
jaroslav@1258
  1300
        }
jaroslav@1258
  1301
jaroslav@1258
  1302
        final boolean inClosedRange(Object key) {
jaroslav@1258
  1303
            return (fromStart || m.compare(key, lo) >= 0)
jaroslav@1258
  1304
                && (toEnd || m.compare(hi, key) >= 0);
jaroslav@1258
  1305
        }
jaroslav@1258
  1306
jaroslav@1258
  1307
        final boolean inRange(Object key, boolean inclusive) {
jaroslav@1258
  1308
            return inclusive ? inRange(key) : inClosedRange(key);
jaroslav@1258
  1309
        }
jaroslav@1258
  1310
jaroslav@1258
  1311
        /*
jaroslav@1258
  1312
         * Absolute versions of relation operations.
jaroslav@1258
  1313
         * Subclasses map to these using like-named "sub"
jaroslav@1258
  1314
         * versions that invert senses for descending maps
jaroslav@1258
  1315
         */
jaroslav@1258
  1316
jaroslav@1258
  1317
        final TreeMap.Entry<K,V> absLowest() {
jaroslav@1258
  1318
            TreeMap.Entry<K,V> e =
jaroslav@1258
  1319
                (fromStart ?  m.getFirstEntry() :
jaroslav@1258
  1320
                 (loInclusive ? m.getCeilingEntry(lo) :
jaroslav@1258
  1321
                                m.getHigherEntry(lo)));
jaroslav@1258
  1322
            return (e == null || tooHigh(e.key)) ? null : e;
jaroslav@1258
  1323
        }
jaroslav@1258
  1324
jaroslav@1258
  1325
        final TreeMap.Entry<K,V> absHighest() {
jaroslav@1258
  1326
            TreeMap.Entry<K,V> e =
jaroslav@1258
  1327
                (toEnd ?  m.getLastEntry() :
jaroslav@1258
  1328
                 (hiInclusive ?  m.getFloorEntry(hi) :
jaroslav@1258
  1329
                                 m.getLowerEntry(hi)));
jaroslav@1258
  1330
            return (e == null || tooLow(e.key)) ? null : e;
jaroslav@1258
  1331
        }
jaroslav@1258
  1332
jaroslav@1258
  1333
        final TreeMap.Entry<K,V> absCeiling(K key) {
jaroslav@1258
  1334
            if (tooLow(key))
jaroslav@1258
  1335
                return absLowest();
jaroslav@1258
  1336
            TreeMap.Entry<K,V> e = m.getCeilingEntry(key);
jaroslav@1258
  1337
            return (e == null || tooHigh(e.key)) ? null : e;
jaroslav@1258
  1338
        }
jaroslav@1258
  1339
jaroslav@1258
  1340
        final TreeMap.Entry<K,V> absHigher(K key) {
jaroslav@1258
  1341
            if (tooLow(key))
jaroslav@1258
  1342
                return absLowest();
jaroslav@1258
  1343
            TreeMap.Entry<K,V> e = m.getHigherEntry(key);
jaroslav@1258
  1344
            return (e == null || tooHigh(e.key)) ? null : e;
jaroslav@1258
  1345
        }
jaroslav@1258
  1346
jaroslav@1258
  1347
        final TreeMap.Entry<K,V> absFloor(K key) {
jaroslav@1258
  1348
            if (tooHigh(key))
jaroslav@1258
  1349
                return absHighest();
jaroslav@1258
  1350
            TreeMap.Entry<K,V> e = m.getFloorEntry(key);
jaroslav@1258
  1351
            return (e == null || tooLow(e.key)) ? null : e;
jaroslav@1258
  1352
        }
jaroslav@1258
  1353
jaroslav@1258
  1354
        final TreeMap.Entry<K,V> absLower(K key) {
jaroslav@1258
  1355
            if (tooHigh(key))
jaroslav@1258
  1356
                return absHighest();
jaroslav@1258
  1357
            TreeMap.Entry<K,V> e = m.getLowerEntry(key);
jaroslav@1258
  1358
            return (e == null || tooLow(e.key)) ? null : e;
jaroslav@1258
  1359
        }
jaroslav@1258
  1360
jaroslav@1258
  1361
        /** Returns the absolute high fence for ascending traversal */
jaroslav@1258
  1362
        final TreeMap.Entry<K,V> absHighFence() {
jaroslav@1258
  1363
            return (toEnd ? null : (hiInclusive ?
jaroslav@1258
  1364
                                    m.getHigherEntry(hi) :
jaroslav@1258
  1365
                                    m.getCeilingEntry(hi)));
jaroslav@1258
  1366
        }
jaroslav@1258
  1367
jaroslav@1258
  1368
        /** Return the absolute low fence for descending traversal  */
jaroslav@1258
  1369
        final TreeMap.Entry<K,V> absLowFence() {
jaroslav@1258
  1370
            return (fromStart ? null : (loInclusive ?
jaroslav@1258
  1371
                                        m.getLowerEntry(lo) :
jaroslav@1258
  1372
                                        m.getFloorEntry(lo)));
jaroslav@1258
  1373
        }
jaroslav@1258
  1374
jaroslav@1258
  1375
        // Abstract methods defined in ascending vs descending classes
jaroslav@1258
  1376
        // These relay to the appropriate absolute versions
jaroslav@1258
  1377
jaroslav@1258
  1378
        abstract TreeMap.Entry<K,V> subLowest();
jaroslav@1258
  1379
        abstract TreeMap.Entry<K,V> subHighest();
jaroslav@1258
  1380
        abstract TreeMap.Entry<K,V> subCeiling(K key);
jaroslav@1258
  1381
        abstract TreeMap.Entry<K,V> subHigher(K key);
jaroslav@1258
  1382
        abstract TreeMap.Entry<K,V> subFloor(K key);
jaroslav@1258
  1383
        abstract TreeMap.Entry<K,V> subLower(K key);
jaroslav@1258
  1384
jaroslav@1258
  1385
        /** Returns ascending iterator from the perspective of this submap */
jaroslav@1258
  1386
        abstract Iterator<K> keyIterator();
jaroslav@1258
  1387
jaroslav@1258
  1388
        /** Returns descending iterator from the perspective of this submap */
jaroslav@1258
  1389
        abstract Iterator<K> descendingKeyIterator();
jaroslav@1258
  1390
jaroslav@1258
  1391
        // public methods
jaroslav@1258
  1392
jaroslav@1258
  1393
        public boolean isEmpty() {
jaroslav@1258
  1394
            return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty();
jaroslav@1258
  1395
        }
jaroslav@1258
  1396
jaroslav@1258
  1397
        public int size() {
jaroslav@1258
  1398
            return (fromStart && toEnd) ? m.size() : entrySet().size();
jaroslav@1258
  1399
        }
jaroslav@1258
  1400
jaroslav@1258
  1401
        public final boolean containsKey(Object key) {
jaroslav@1258
  1402
            return inRange(key) && m.containsKey(key);
jaroslav@1258
  1403
        }
jaroslav@1258
  1404
jaroslav@1258
  1405
        public final V put(K key, V value) {
jaroslav@1258
  1406
            if (!inRange(key))
jaroslav@1258
  1407
                throw new IllegalArgumentException("key out of range");
jaroslav@1258
  1408
            return m.put(key, value);
jaroslav@1258
  1409
        }
jaroslav@1258
  1410
jaroslav@1258
  1411
        public final V get(Object key) {
jaroslav@1258
  1412
            return !inRange(key) ? null :  m.get(key);
jaroslav@1258
  1413
        }
jaroslav@1258
  1414
jaroslav@1258
  1415
        public final V remove(Object key) {
jaroslav@1258
  1416
            return !inRange(key) ? null : m.remove(key);
jaroslav@1258
  1417
        }
jaroslav@1258
  1418
jaroslav@1258
  1419
        public final Map.Entry<K,V> ceilingEntry(K key) {
jaroslav@1258
  1420
            return exportEntry(subCeiling(key));
jaroslav@1258
  1421
        }
jaroslav@1258
  1422
jaroslav@1258
  1423
        public final K ceilingKey(K key) {
jaroslav@1258
  1424
            return keyOrNull(subCeiling(key));
jaroslav@1258
  1425
        }
jaroslav@1258
  1426
jaroslav@1258
  1427
        public final Map.Entry<K,V> higherEntry(K key) {
jaroslav@1258
  1428
            return exportEntry(subHigher(key));
jaroslav@1258
  1429
        }
jaroslav@1258
  1430
jaroslav@1258
  1431
        public final K higherKey(K key) {
jaroslav@1258
  1432
            return keyOrNull(subHigher(key));
jaroslav@1258
  1433
        }
jaroslav@1258
  1434
jaroslav@1258
  1435
        public final Map.Entry<K,V> floorEntry(K key) {
jaroslav@1258
  1436
            return exportEntry(subFloor(key));
jaroslav@1258
  1437
        }
jaroslav@1258
  1438
jaroslav@1258
  1439
        public final K floorKey(K key) {
jaroslav@1258
  1440
            return keyOrNull(subFloor(key));
jaroslav@1258
  1441
        }
jaroslav@1258
  1442
jaroslav@1258
  1443
        public final Map.Entry<K,V> lowerEntry(K key) {
jaroslav@1258
  1444
            return exportEntry(subLower(key));
jaroslav@1258
  1445
        }
jaroslav@1258
  1446
jaroslav@1258
  1447
        public final K lowerKey(K key) {
jaroslav@1258
  1448
            return keyOrNull(subLower(key));
jaroslav@1258
  1449
        }
jaroslav@1258
  1450
jaroslav@1258
  1451
        public final K firstKey() {
jaroslav@1258
  1452
            return key(subLowest());
jaroslav@1258
  1453
        }
jaroslav@1258
  1454
jaroslav@1258
  1455
        public final K lastKey() {
jaroslav@1258
  1456
            return key(subHighest());
jaroslav@1258
  1457
        }
jaroslav@1258
  1458
jaroslav@1258
  1459
        public final Map.Entry<K,V> firstEntry() {
jaroslav@1258
  1460
            return exportEntry(subLowest());
jaroslav@1258
  1461
        }
jaroslav@1258
  1462
jaroslav@1258
  1463
        public final Map.Entry<K,V> lastEntry() {
jaroslav@1258
  1464
            return exportEntry(subHighest());
jaroslav@1258
  1465
        }
jaroslav@1258
  1466
jaroslav@1258
  1467
        public final Map.Entry<K,V> pollFirstEntry() {
jaroslav@1258
  1468
            TreeMap.Entry<K,V> e = subLowest();
jaroslav@1258
  1469
            Map.Entry<K,V> result = exportEntry(e);
jaroslav@1258
  1470
            if (e != null)
jaroslav@1258
  1471
                m.deleteEntry(e);
jaroslav@1258
  1472
            return result;
jaroslav@1258
  1473
        }
jaroslav@1258
  1474
jaroslav@1258
  1475
        public final Map.Entry<K,V> pollLastEntry() {
jaroslav@1258
  1476
            TreeMap.Entry<K,V> e = subHighest();
jaroslav@1258
  1477
            Map.Entry<K,V> result = exportEntry(e);
jaroslav@1258
  1478
            if (e != null)
jaroslav@1258
  1479
                m.deleteEntry(e);
jaroslav@1258
  1480
            return result;
jaroslav@1258
  1481
        }
jaroslav@1258
  1482
jaroslav@1258
  1483
        // Views
jaroslav@1258
  1484
        transient NavigableMap<K,V> descendingMapView = null;
jaroslav@1258
  1485
        transient EntrySetView entrySetView = null;
jaroslav@1258
  1486
        transient KeySet<K> navigableKeySetView = null;
jaroslav@1258
  1487
jaroslav@1258
  1488
        public final NavigableSet<K> navigableKeySet() {
jaroslav@1258
  1489
            KeySet<K> nksv = navigableKeySetView;
jaroslav@1258
  1490
            return (nksv != null) ? nksv :
jaroslav@1258
  1491
                (navigableKeySetView = new TreeMap.KeySet(this));
jaroslav@1258
  1492
        }
jaroslav@1258
  1493
jaroslav@1258
  1494
        public final Set<K> keySet() {
jaroslav@1258
  1495
            return navigableKeySet();
jaroslav@1258
  1496
        }
jaroslav@1258
  1497
jaroslav@1258
  1498
        public NavigableSet<K> descendingKeySet() {
jaroslav@1258
  1499
            return descendingMap().navigableKeySet();
jaroslav@1258
  1500
        }
jaroslav@1258
  1501
jaroslav@1258
  1502
        public final SortedMap<K,V> subMap(K fromKey, K toKey) {
jaroslav@1258
  1503
            return subMap(fromKey, true, toKey, false);
jaroslav@1258
  1504
        }
jaroslav@1258
  1505
jaroslav@1258
  1506
        public final SortedMap<K,V> headMap(K toKey) {
jaroslav@1258
  1507
            return headMap(toKey, false);
jaroslav@1258
  1508
        }
jaroslav@1258
  1509
jaroslav@1258
  1510
        public final SortedMap<K,V> tailMap(K fromKey) {
jaroslav@1258
  1511
            return tailMap(fromKey, true);
jaroslav@1258
  1512
        }
jaroslav@1258
  1513
jaroslav@1258
  1514
        // View classes
jaroslav@1258
  1515
jaroslav@1258
  1516
        abstract class EntrySetView extends AbstractSet<Map.Entry<K,V>> {
jaroslav@1258
  1517
            private transient int size = -1, sizeModCount;
jaroslav@1258
  1518
jaroslav@1258
  1519
            public int size() {
jaroslav@1258
  1520
                if (fromStart && toEnd)
jaroslav@1258
  1521
                    return m.size();
jaroslav@1258
  1522
                if (size == -1 || sizeModCount != m.modCount) {
jaroslav@1258
  1523
                    sizeModCount = m.modCount;
jaroslav@1258
  1524
                    size = 0;
jaroslav@1258
  1525
                    Iterator i = iterator();
jaroslav@1258
  1526
                    while (i.hasNext()) {
jaroslav@1258
  1527
                        size++;
jaroslav@1258
  1528
                        i.next();
jaroslav@1258
  1529
                    }
jaroslav@1258
  1530
                }
jaroslav@1258
  1531
                return size;
jaroslav@1258
  1532
            }
jaroslav@1258
  1533
jaroslav@1258
  1534
            public boolean isEmpty() {
jaroslav@1258
  1535
                TreeMap.Entry<K,V> n = absLowest();
jaroslav@1258
  1536
                return n == null || tooHigh(n.key);
jaroslav@1258
  1537
            }
jaroslav@1258
  1538
jaroslav@1258
  1539
            public boolean contains(Object o) {
jaroslav@1258
  1540
                if (!(o instanceof Map.Entry))
jaroslav@1258
  1541
                    return false;
jaroslav@1258
  1542
                Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
jaroslav@1258
  1543
                K key = entry.getKey();
jaroslav@1258
  1544
                if (!inRange(key))
jaroslav@1258
  1545
                    return false;
jaroslav@1258
  1546
                TreeMap.Entry node = m.getEntry(key);
jaroslav@1258
  1547
                return node != null &&
jaroslav@1258
  1548
                    valEquals(node.getValue(), entry.getValue());
jaroslav@1258
  1549
            }
jaroslav@1258
  1550
jaroslav@1258
  1551
            public boolean remove(Object o) {
jaroslav@1258
  1552
                if (!(o instanceof Map.Entry))
jaroslav@1258
  1553
                    return false;
jaroslav@1258
  1554
                Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
jaroslav@1258
  1555
                K key = entry.getKey();
jaroslav@1258
  1556
                if (!inRange(key))
jaroslav@1258
  1557
                    return false;
jaroslav@1258
  1558
                TreeMap.Entry<K,V> node = m.getEntry(key);
jaroslav@1258
  1559
                if (node!=null && valEquals(node.getValue(),
jaroslav@1258
  1560
                                            entry.getValue())) {
jaroslav@1258
  1561
                    m.deleteEntry(node);
jaroslav@1258
  1562
                    return true;
jaroslav@1258
  1563
                }
jaroslav@1258
  1564
                return false;
jaroslav@1258
  1565
            }
jaroslav@1258
  1566
        }
jaroslav@1258
  1567
jaroslav@1258
  1568
        /**
jaroslav@1258
  1569
         * Iterators for SubMaps
jaroslav@1258
  1570
         */
jaroslav@1258
  1571
        abstract class SubMapIterator<T> implements Iterator<T> {
jaroslav@1258
  1572
            TreeMap.Entry<K,V> lastReturned;
jaroslav@1258
  1573
            TreeMap.Entry<K,V> next;
jaroslav@1258
  1574
            final Object fenceKey;
jaroslav@1258
  1575
            int expectedModCount;
jaroslav@1258
  1576
jaroslav@1258
  1577
            SubMapIterator(TreeMap.Entry<K,V> first,
jaroslav@1258
  1578
                           TreeMap.Entry<K,V> fence) {
jaroslav@1258
  1579
                expectedModCount = m.modCount;
jaroslav@1258
  1580
                lastReturned = null;
jaroslav@1258
  1581
                next = first;
jaroslav@1258
  1582
                fenceKey = fence == null ? UNBOUNDED : fence.key;
jaroslav@1258
  1583
            }
jaroslav@1258
  1584
jaroslav@1258
  1585
            public final boolean hasNext() {
jaroslav@1258
  1586
                return next != null && next.key != fenceKey;
jaroslav@1258
  1587
            }
jaroslav@1258
  1588
jaroslav@1258
  1589
            final TreeMap.Entry<K,V> nextEntry() {
jaroslav@1258
  1590
                TreeMap.Entry<K,V> e = next;
jaroslav@1258
  1591
                if (e == null || e.key == fenceKey)
jaroslav@1258
  1592
                    throw new NoSuchElementException();
jaroslav@1258
  1593
                if (m.modCount != expectedModCount)
jaroslav@1258
  1594
                    throw new ConcurrentModificationException();
jaroslav@1258
  1595
                next = successor(e);
jaroslav@1258
  1596
                lastReturned = e;
jaroslav@1258
  1597
                return e;
jaroslav@1258
  1598
            }
jaroslav@1258
  1599
jaroslav@1258
  1600
            final TreeMap.Entry<K,V> prevEntry() {
jaroslav@1258
  1601
                TreeMap.Entry<K,V> e = next;
jaroslav@1258
  1602
                if (e == null || e.key == fenceKey)
jaroslav@1258
  1603
                    throw new NoSuchElementException();
jaroslav@1258
  1604
                if (m.modCount != expectedModCount)
jaroslav@1258
  1605
                    throw new ConcurrentModificationException();
jaroslav@1258
  1606
                next = predecessor(e);
jaroslav@1258
  1607
                lastReturned = e;
jaroslav@1258
  1608
                return e;
jaroslav@1258
  1609
            }
jaroslav@1258
  1610
jaroslav@1258
  1611
            final void removeAscending() {
jaroslav@1258
  1612
                if (lastReturned == null)
jaroslav@1258
  1613
                    throw new IllegalStateException();
jaroslav@1258
  1614
                if (m.modCount != expectedModCount)
jaroslav@1258
  1615
                    throw new ConcurrentModificationException();
jaroslav@1258
  1616
                // deleted entries are replaced by their successors
jaroslav@1258
  1617
                if (lastReturned.left != null && lastReturned.right != null)
jaroslav@1258
  1618
                    next = lastReturned;
jaroslav@1258
  1619
                m.deleteEntry(lastReturned);
jaroslav@1258
  1620
                lastReturned = null;
jaroslav@1258
  1621
                expectedModCount = m.modCount;
jaroslav@1258
  1622
            }
jaroslav@1258
  1623
jaroslav@1258
  1624
            final void removeDescending() {
jaroslav@1258
  1625
                if (lastReturned == null)
jaroslav@1258
  1626
                    throw new IllegalStateException();
jaroslav@1258
  1627
                if (m.modCount != expectedModCount)
jaroslav@1258
  1628
                    throw new ConcurrentModificationException();
jaroslav@1258
  1629
                m.deleteEntry(lastReturned);
jaroslav@1258
  1630
                lastReturned = null;
jaroslav@1258
  1631
                expectedModCount = m.modCount;
jaroslav@1258
  1632
            }
jaroslav@1258
  1633
jaroslav@1258
  1634
        }
jaroslav@1258
  1635
jaroslav@1258
  1636
        final class SubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> {
jaroslav@1258
  1637
            SubMapEntryIterator(TreeMap.Entry<K,V> first,
jaroslav@1258
  1638
                                TreeMap.Entry<K,V> fence) {
jaroslav@1258
  1639
                super(first, fence);
jaroslav@1258
  1640
            }
jaroslav@1258
  1641
            public Map.Entry<K,V> next() {
jaroslav@1258
  1642
                return nextEntry();
jaroslav@1258
  1643
            }
jaroslav@1258
  1644
            public void remove() {
jaroslav@1258
  1645
                removeAscending();
jaroslav@1258
  1646
            }
jaroslav@1258
  1647
        }
jaroslav@1258
  1648
jaroslav@1258
  1649
        final class SubMapKeyIterator extends SubMapIterator<K> {
jaroslav@1258
  1650
            SubMapKeyIterator(TreeMap.Entry<K,V> first,
jaroslav@1258
  1651
                              TreeMap.Entry<K,V> fence) {
jaroslav@1258
  1652
                super(first, fence);
jaroslav@1258
  1653
            }
jaroslav@1258
  1654
            public K next() {
jaroslav@1258
  1655
                return nextEntry().key;
jaroslav@1258
  1656
            }
jaroslav@1258
  1657
            public void remove() {
jaroslav@1258
  1658
                removeAscending();
jaroslav@1258
  1659
            }
jaroslav@1258
  1660
        }
jaroslav@1258
  1661
jaroslav@1258
  1662
        final class DescendingSubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> {
jaroslav@1258
  1663
            DescendingSubMapEntryIterator(TreeMap.Entry<K,V> last,
jaroslav@1258
  1664
                                          TreeMap.Entry<K,V> fence) {
jaroslav@1258
  1665
                super(last, fence);
jaroslav@1258
  1666
            }
jaroslav@1258
  1667
jaroslav@1258
  1668
            public Map.Entry<K,V> next() {
jaroslav@1258
  1669
                return prevEntry();
jaroslav@1258
  1670
            }
jaroslav@1258
  1671
            public void remove() {
jaroslav@1258
  1672
                removeDescending();
jaroslav@1258
  1673
            }
jaroslav@1258
  1674
        }
jaroslav@1258
  1675
jaroslav@1258
  1676
        final class DescendingSubMapKeyIterator extends SubMapIterator<K> {
jaroslav@1258
  1677
            DescendingSubMapKeyIterator(TreeMap.Entry<K,V> last,
jaroslav@1258
  1678
                                        TreeMap.Entry<K,V> fence) {
jaroslav@1258
  1679
                super(last, fence);
jaroslav@1258
  1680
            }
jaroslav@1258
  1681
            public K next() {
jaroslav@1258
  1682
                return prevEntry().key;
jaroslav@1258
  1683
            }
jaroslav@1258
  1684
            public void remove() {
jaroslav@1258
  1685
                removeDescending();
jaroslav@1258
  1686
            }
jaroslav@1258
  1687
        }
jaroslav@1258
  1688
    }
jaroslav@1258
  1689
jaroslav@1258
  1690
    /**
jaroslav@1258
  1691
     * @serial include
jaroslav@1258
  1692
     */
jaroslav@1258
  1693
    static final class AscendingSubMap<K,V> extends NavigableSubMap<K,V> {
jaroslav@1258
  1694
        private static final long serialVersionUID = 912986545866124060L;
jaroslav@1258
  1695
jaroslav@1258
  1696
        AscendingSubMap(TreeMap<K,V> m,
jaroslav@1258
  1697
                        boolean fromStart, K lo, boolean loInclusive,
jaroslav@1258
  1698
                        boolean toEnd,     K hi, boolean hiInclusive) {
jaroslav@1258
  1699
            super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
jaroslav@1258
  1700
        }
jaroslav@1258
  1701
jaroslav@1258
  1702
        public Comparator<? super K> comparator() {
jaroslav@1258
  1703
            return m.comparator();
jaroslav@1258
  1704
        }
jaroslav@1258
  1705
jaroslav@1258
  1706
        public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
jaroslav@1258
  1707
                                        K toKey,   boolean toInclusive) {
jaroslav@1258
  1708
            if (!inRange(fromKey, fromInclusive))
jaroslav@1258
  1709
                throw new IllegalArgumentException("fromKey out of range");
jaroslav@1258
  1710
            if (!inRange(toKey, toInclusive))
jaroslav@1258
  1711
                throw new IllegalArgumentException("toKey out of range");
jaroslav@1258
  1712
            return new AscendingSubMap(m,
jaroslav@1258
  1713
                                       false, fromKey, fromInclusive,
jaroslav@1258
  1714
                                       false, toKey,   toInclusive);
jaroslav@1258
  1715
        }
jaroslav@1258
  1716
jaroslav@1258
  1717
        public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
jaroslav@1258
  1718
            if (!inRange(toKey, inclusive))
jaroslav@1258
  1719
                throw new IllegalArgumentException("toKey out of range");
jaroslav@1258
  1720
            return new AscendingSubMap(m,
jaroslav@1258
  1721
                                       fromStart, lo,    loInclusive,
jaroslav@1258
  1722
                                       false,     toKey, inclusive);
jaroslav@1258
  1723
        }
jaroslav@1258
  1724
jaroslav@1258
  1725
        public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
jaroslav@1258
  1726
            if (!inRange(fromKey, inclusive))
jaroslav@1258
  1727
                throw new IllegalArgumentException("fromKey out of range");
jaroslav@1258
  1728
            return new AscendingSubMap(m,
jaroslav@1258
  1729
                                       false, fromKey, inclusive,
jaroslav@1258
  1730
                                       toEnd, hi,      hiInclusive);
jaroslav@1258
  1731
        }
jaroslav@1258
  1732
jaroslav@1258
  1733
        public NavigableMap<K,V> descendingMap() {
jaroslav@1258
  1734
            NavigableMap<K,V> mv = descendingMapView;
jaroslav@1258
  1735
            return (mv != null) ? mv :
jaroslav@1258
  1736
                (descendingMapView =
jaroslav@1258
  1737
                 new DescendingSubMap(m,
jaroslav@1258
  1738
                                      fromStart, lo, loInclusive,
jaroslav@1258
  1739
                                      toEnd,     hi, hiInclusive));
jaroslav@1258
  1740
        }
jaroslav@1258
  1741
jaroslav@1258
  1742
        Iterator<K> keyIterator() {
jaroslav@1258
  1743
            return new SubMapKeyIterator(absLowest(), absHighFence());
jaroslav@1258
  1744
        }
jaroslav@1258
  1745
jaroslav@1258
  1746
        Iterator<K> descendingKeyIterator() {
jaroslav@1258
  1747
            return new DescendingSubMapKeyIterator(absHighest(), absLowFence());
jaroslav@1258
  1748
        }
jaroslav@1258
  1749
jaroslav@1258
  1750
        final class AscendingEntrySetView extends EntrySetView {
jaroslav@1258
  1751
            public Iterator<Map.Entry<K,V>> iterator() {
jaroslav@1258
  1752
                return new SubMapEntryIterator(absLowest(), absHighFence());
jaroslav@1258
  1753
            }
jaroslav@1258
  1754
        }
jaroslav@1258
  1755
jaroslav@1258
  1756
        public Set<Map.Entry<K,V>> entrySet() {
jaroslav@1258
  1757
            EntrySetView es = entrySetView;
jaroslav@1258
  1758
            return (es != null) ? es : new AscendingEntrySetView();
jaroslav@1258
  1759
        }
jaroslav@1258
  1760
jaroslav@1258
  1761
        TreeMap.Entry<K,V> subLowest()       { return absLowest(); }
jaroslav@1258
  1762
        TreeMap.Entry<K,V> subHighest()      { return absHighest(); }
jaroslav@1258
  1763
        TreeMap.Entry<K,V> subCeiling(K key) { return absCeiling(key); }
jaroslav@1258
  1764
        TreeMap.Entry<K,V> subHigher(K key)  { return absHigher(key); }
jaroslav@1258
  1765
        TreeMap.Entry<K,V> subFloor(K key)   { return absFloor(key); }
jaroslav@1258
  1766
        TreeMap.Entry<K,V> subLower(K key)   { return absLower(key); }
jaroslav@1258
  1767
    }
jaroslav@1258
  1768
jaroslav@1258
  1769
    /**
jaroslav@1258
  1770
     * @serial include
jaroslav@1258
  1771
     */
jaroslav@1258
  1772
    static final class DescendingSubMap<K,V>  extends NavigableSubMap<K,V> {
jaroslav@1258
  1773
        private static final long serialVersionUID = 912986545866120460L;
jaroslav@1258
  1774
        DescendingSubMap(TreeMap<K,V> m,
jaroslav@1258
  1775
                        boolean fromStart, K lo, boolean loInclusive,
jaroslav@1258
  1776
                        boolean toEnd,     K hi, boolean hiInclusive) {
jaroslav@1258
  1777
            super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
jaroslav@1258
  1778
        }
jaroslav@1258
  1779
jaroslav@1258
  1780
        private final Comparator<? super K> reverseComparator =
jaroslav@1258
  1781
            Collections.reverseOrder(m.comparator);
jaroslav@1258
  1782
jaroslav@1258
  1783
        public Comparator<? super K> comparator() {
jaroslav@1258
  1784
            return reverseComparator;
jaroslav@1258
  1785
        }
jaroslav@1258
  1786
jaroslav@1258
  1787
        public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
jaroslav@1258
  1788
                                        K toKey,   boolean toInclusive) {
jaroslav@1258
  1789
            if (!inRange(fromKey, fromInclusive))
jaroslav@1258
  1790
                throw new IllegalArgumentException("fromKey out of range");
jaroslav@1258
  1791
            if (!inRange(toKey, toInclusive))
jaroslav@1258
  1792
                throw new IllegalArgumentException("toKey out of range");
jaroslav@1258
  1793
            return new DescendingSubMap(m,
jaroslav@1258
  1794
                                        false, toKey,   toInclusive,
jaroslav@1258
  1795
                                        false, fromKey, fromInclusive);
jaroslav@1258
  1796
        }
jaroslav@1258
  1797
jaroslav@1258
  1798
        public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
jaroslav@1258
  1799
            if (!inRange(toKey, inclusive))
jaroslav@1258
  1800
                throw new IllegalArgumentException("toKey out of range");
jaroslav@1258
  1801
            return new DescendingSubMap(m,
jaroslav@1258
  1802
                                        false, toKey, inclusive,
jaroslav@1258
  1803
                                        toEnd, hi,    hiInclusive);
jaroslav@1258
  1804
        }
jaroslav@1258
  1805
jaroslav@1258
  1806
        public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
jaroslav@1258
  1807
            if (!inRange(fromKey, inclusive))
jaroslav@1258
  1808
                throw new IllegalArgumentException("fromKey out of range");
jaroslav@1258
  1809
            return new DescendingSubMap(m,
jaroslav@1258
  1810
                                        fromStart, lo, loInclusive,
jaroslav@1258
  1811
                                        false, fromKey, inclusive);
jaroslav@1258
  1812
        }
jaroslav@1258
  1813
jaroslav@1258
  1814
        public NavigableMap<K,V> descendingMap() {
jaroslav@1258
  1815
            NavigableMap<K,V> mv = descendingMapView;
jaroslav@1258
  1816
            return (mv != null) ? mv :
jaroslav@1258
  1817
                (descendingMapView =
jaroslav@1258
  1818
                 new AscendingSubMap(m,
jaroslav@1258
  1819
                                     fromStart, lo, loInclusive,
jaroslav@1258
  1820
                                     toEnd,     hi, hiInclusive));
jaroslav@1258
  1821
        }
jaroslav@1258
  1822
jaroslav@1258
  1823
        Iterator<K> keyIterator() {
jaroslav@1258
  1824
            return new DescendingSubMapKeyIterator(absHighest(), absLowFence());
jaroslav@1258
  1825
        }
jaroslav@1258
  1826
jaroslav@1258
  1827
        Iterator<K> descendingKeyIterator() {
jaroslav@1258
  1828
            return new SubMapKeyIterator(absLowest(), absHighFence());
jaroslav@1258
  1829
        }
jaroslav@1258
  1830
jaroslav@1258
  1831
        final class DescendingEntrySetView extends EntrySetView {
jaroslav@1258
  1832
            public Iterator<Map.Entry<K,V>> iterator() {
jaroslav@1258
  1833
                return new DescendingSubMapEntryIterator(absHighest(), absLowFence());
jaroslav@1258
  1834
            }
jaroslav@1258
  1835
        }
jaroslav@1258
  1836
jaroslav@1258
  1837
        public Set<Map.Entry<K,V>> entrySet() {
jaroslav@1258
  1838
            EntrySetView es = entrySetView;
jaroslav@1258
  1839
            return (es != null) ? es : new DescendingEntrySetView();
jaroslav@1258
  1840
        }
jaroslav@1258
  1841
jaroslav@1258
  1842
        TreeMap.Entry<K,V> subLowest()       { return absHighest(); }
jaroslav@1258
  1843
        TreeMap.Entry<K,V> subHighest()      { return absLowest(); }
jaroslav@1258
  1844
        TreeMap.Entry<K,V> subCeiling(K key) { return absFloor(key); }
jaroslav@1258
  1845
        TreeMap.Entry<K,V> subHigher(K key)  { return absLower(key); }
jaroslav@1258
  1846
        TreeMap.Entry<K,V> subFloor(K key)   { return absCeiling(key); }
jaroslav@1258
  1847
        TreeMap.Entry<K,V> subLower(K key)   { return absHigher(key); }
jaroslav@1258
  1848
    }
jaroslav@1258
  1849
jaroslav@1258
  1850
    /**
jaroslav@1258
  1851
     * This class exists solely for the sake of serialization
jaroslav@1258
  1852
     * compatibility with previous releases of TreeMap that did not
jaroslav@1258
  1853
     * support NavigableMap.  It translates an old-version SubMap into
jaroslav@1258
  1854
     * a new-version AscendingSubMap. This class is never otherwise
jaroslav@1258
  1855
     * used.
jaroslav@1258
  1856
     *
jaroslav@1258
  1857
     * @serial include
jaroslav@1258
  1858
     */
jaroslav@1258
  1859
    private class SubMap extends AbstractMap<K,V>
jaroslav@1258
  1860
        implements SortedMap<K,V>, java.io.Serializable {
jaroslav@1258
  1861
        private static final long serialVersionUID = -6520786458950516097L;
jaroslav@1258
  1862
        private boolean fromStart = false, toEnd = false;
jaroslav@1258
  1863
        private K fromKey, toKey;
jaroslav@1258
  1864
        private Object readResolve() {
jaroslav@1258
  1865
            return new AscendingSubMap(TreeMap.this,
jaroslav@1258
  1866
                                       fromStart, fromKey, true,
jaroslav@1258
  1867
                                       toEnd, toKey, false);
jaroslav@1258
  1868
        }
jaroslav@1258
  1869
        public Set<Map.Entry<K,V>> entrySet() { throw new InternalError(); }
jaroslav@1258
  1870
        public K lastKey() { throw new InternalError(); }
jaroslav@1258
  1871
        public K firstKey() { throw new InternalError(); }
jaroslav@1258
  1872
        public SortedMap<K,V> subMap(K fromKey, K toKey) { throw new InternalError(); }
jaroslav@1258
  1873
        public SortedMap<K,V> headMap(K toKey) { throw new InternalError(); }
jaroslav@1258
  1874
        public SortedMap<K,V> tailMap(K fromKey) { throw new InternalError(); }
jaroslav@1258
  1875
        public Comparator<? super K> comparator() { throw new InternalError(); }
jaroslav@1258
  1876
    }
jaroslav@1258
  1877
jaroslav@1258
  1878
jaroslav@1258
  1879
    // Red-black mechanics
jaroslav@1258
  1880
jaroslav@1258
  1881
    private static final boolean RED   = false;
jaroslav@1258
  1882
    private static final boolean BLACK = true;
jaroslav@1258
  1883
jaroslav@1258
  1884
    /**
jaroslav@1258
  1885
     * Node in the Tree.  Doubles as a means to pass key-value pairs back to
jaroslav@1258
  1886
     * user (see Map.Entry).
jaroslav@1258
  1887
     */
jaroslav@1258
  1888
jaroslav@1258
  1889
    static final class Entry<K,V> implements Map.Entry<K,V> {
jaroslav@1258
  1890
        K key;
jaroslav@1258
  1891
        V value;
jaroslav@1258
  1892
        Entry<K,V> left = null;
jaroslav@1258
  1893
        Entry<K,V> right = null;
jaroslav@1258
  1894
        Entry<K,V> parent;
jaroslav@1258
  1895
        boolean color = BLACK;
jaroslav@1258
  1896
jaroslav@1258
  1897
        /**
jaroslav@1258
  1898
         * Make a new cell with given key, value, and parent, and with
jaroslav@1258
  1899
         * {@code null} child links, and BLACK color.
jaroslav@1258
  1900
         */
jaroslav@1258
  1901
        Entry(K key, V value, Entry<K,V> parent) {
jaroslav@1258
  1902
            this.key = key;
jaroslav@1258
  1903
            this.value = value;
jaroslav@1258
  1904
            this.parent = parent;
jaroslav@1258
  1905
        }
jaroslav@1258
  1906
jaroslav@1258
  1907
        /**
jaroslav@1258
  1908
         * Returns the key.
jaroslav@1258
  1909
         *
jaroslav@1258
  1910
         * @return the key
jaroslav@1258
  1911
         */
jaroslav@1258
  1912
        public K getKey() {
jaroslav@1258
  1913
            return key;
jaroslav@1258
  1914
        }
jaroslav@1258
  1915
jaroslav@1258
  1916
        /**
jaroslav@1258
  1917
         * Returns the value associated with the key.
jaroslav@1258
  1918
         *
jaroslav@1258
  1919
         * @return the value associated with the key
jaroslav@1258
  1920
         */
jaroslav@1258
  1921
        public V getValue() {
jaroslav@1258
  1922
            return value;
jaroslav@1258
  1923
        }
jaroslav@1258
  1924
jaroslav@1258
  1925
        /**
jaroslav@1258
  1926
         * Replaces the value currently associated with the key with the given
jaroslav@1258
  1927
         * value.
jaroslav@1258
  1928
         *
jaroslav@1258
  1929
         * @return the value associated with the key before this method was
jaroslav@1258
  1930
         *         called
jaroslav@1258
  1931
         */
jaroslav@1258
  1932
        public V setValue(V value) {
jaroslav@1258
  1933
            V oldValue = this.value;
jaroslav@1258
  1934
            this.value = value;
jaroslav@1258
  1935
            return oldValue;
jaroslav@1258
  1936
        }
jaroslav@1258
  1937
jaroslav@1258
  1938
        public boolean equals(Object o) {
jaroslav@1258
  1939
            if (!(o instanceof Map.Entry))
jaroslav@1258
  1940
                return false;
jaroslav@1258
  1941
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
jaroslav@1258
  1942
jaroslav@1258
  1943
            return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
jaroslav@1258
  1944
        }
jaroslav@1258
  1945
jaroslav@1258
  1946
        public int hashCode() {
jaroslav@1258
  1947
            int keyHash = (key==null ? 0 : key.hashCode());
jaroslav@1258
  1948
            int valueHash = (value==null ? 0 : value.hashCode());
jaroslav@1258
  1949
            return keyHash ^ valueHash;
jaroslav@1258
  1950
        }
jaroslav@1258
  1951
jaroslav@1258
  1952
        public String toString() {
jaroslav@1258
  1953
            return key + "=" + value;
jaroslav@1258
  1954
        }
jaroslav@1258
  1955
    }
jaroslav@1258
  1956
jaroslav@1258
  1957
    /**
jaroslav@1258
  1958
     * Returns the first Entry in the TreeMap (according to the TreeMap's
jaroslav@1258
  1959
     * key-sort function).  Returns null if the TreeMap is empty.
jaroslav@1258
  1960
     */
jaroslav@1258
  1961
    final Entry<K,V> getFirstEntry() {
jaroslav@1258
  1962
        Entry<K,V> p = root;
jaroslav@1258
  1963
        if (p != null)
jaroslav@1258
  1964
            while (p.left != null)
jaroslav@1258
  1965
                p = p.left;
jaroslav@1258
  1966
        return p;
jaroslav@1258
  1967
    }
jaroslav@1258
  1968
jaroslav@1258
  1969
    /**
jaroslav@1258
  1970
     * Returns the last Entry in the TreeMap (according to the TreeMap's
jaroslav@1258
  1971
     * key-sort function).  Returns null if the TreeMap is empty.
jaroslav@1258
  1972
     */
jaroslav@1258
  1973
    final Entry<K,V> getLastEntry() {
jaroslav@1258
  1974
        Entry<K,V> p = root;
jaroslav@1258
  1975
        if (p != null)
jaroslav@1258
  1976
            while (p.right != null)
jaroslav@1258
  1977
                p = p.right;
jaroslav@1258
  1978
        return p;
jaroslav@1258
  1979
    }
jaroslav@1258
  1980
jaroslav@1258
  1981
    /**
jaroslav@1258
  1982
     * Returns the successor of the specified Entry, or null if no such.
jaroslav@1258
  1983
     */
jaroslav@1258
  1984
    static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
jaroslav@1258
  1985
        if (t == null)
jaroslav@1258
  1986
            return null;
jaroslav@1258
  1987
        else if (t.right != null) {
jaroslav@1258
  1988
            Entry<K,V> p = t.right;
jaroslav@1258
  1989
            while (p.left != null)
jaroslav@1258
  1990
                p = p.left;
jaroslav@1258
  1991
            return p;
jaroslav@1258
  1992
        } else {
jaroslav@1258
  1993
            Entry<K,V> p = t.parent;
jaroslav@1258
  1994
            Entry<K,V> ch = t;
jaroslav@1258
  1995
            while (p != null && ch == p.right) {
jaroslav@1258
  1996
                ch = p;
jaroslav@1258
  1997
                p = p.parent;
jaroslav@1258
  1998
            }
jaroslav@1258
  1999
            return p;
jaroslav@1258
  2000
        }
jaroslav@1258
  2001
    }
jaroslav@1258
  2002
jaroslav@1258
  2003
    /**
jaroslav@1258
  2004
     * Returns the predecessor of the specified Entry, or null if no such.
jaroslav@1258
  2005
     */
jaroslav@1258
  2006
    static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
jaroslav@1258
  2007
        if (t == null)
jaroslav@1258
  2008
            return null;
jaroslav@1258
  2009
        else if (t.left != null) {
jaroslav@1258
  2010
            Entry<K,V> p = t.left;
jaroslav@1258
  2011
            while (p.right != null)
jaroslav@1258
  2012
                p = p.right;
jaroslav@1258
  2013
            return p;
jaroslav@1258
  2014
        } else {
jaroslav@1258
  2015
            Entry<K,V> p = t.parent;
jaroslav@1258
  2016
            Entry<K,V> ch = t;
jaroslav@1258
  2017
            while (p != null && ch == p.left) {
jaroslav@1258
  2018
                ch = p;
jaroslav@1258
  2019
                p = p.parent;
jaroslav@1258
  2020
            }
jaroslav@1258
  2021
            return p;
jaroslav@1258
  2022
        }
jaroslav@1258
  2023
    }
jaroslav@1258
  2024
jaroslav@1258
  2025
    /**
jaroslav@1258
  2026
     * Balancing operations.
jaroslav@1258
  2027
     *
jaroslav@1258
  2028
     * Implementations of rebalancings during insertion and deletion are
jaroslav@1258
  2029
     * slightly different than the CLR version.  Rather than using dummy
jaroslav@1258
  2030
     * nilnodes, we use a set of accessors that deal properly with null.  They
jaroslav@1258
  2031
     * are used to avoid messiness surrounding nullness checks in the main
jaroslav@1258
  2032
     * algorithms.
jaroslav@1258
  2033
     */
jaroslav@1258
  2034
jaroslav@1258
  2035
    private static <K,V> boolean colorOf(Entry<K,V> p) {
jaroslav@1258
  2036
        return (p == null ? BLACK : p.color);
jaroslav@1258
  2037
    }
jaroslav@1258
  2038
jaroslav@1258
  2039
    private static <K,V> Entry<K,V> parentOf(Entry<K,V> p) {
jaroslav@1258
  2040
        return (p == null ? null: p.parent);
jaroslav@1258
  2041
    }
jaroslav@1258
  2042
jaroslav@1258
  2043
    private static <K,V> void setColor(Entry<K,V> p, boolean c) {
jaroslav@1258
  2044
        if (p != null)
jaroslav@1258
  2045
            p.color = c;
jaroslav@1258
  2046
    }
jaroslav@1258
  2047
jaroslav@1258
  2048
    private static <K,V> Entry<K,V> leftOf(Entry<K,V> p) {
jaroslav@1258
  2049
        return (p == null) ? null: p.left;
jaroslav@1258
  2050
    }
jaroslav@1258
  2051
jaroslav@1258
  2052
    private static <K,V> Entry<K,V> rightOf(Entry<K,V> p) {
jaroslav@1258
  2053
        return (p == null) ? null: p.right;
jaroslav@1258
  2054
    }
jaroslav@1258
  2055
jaroslav@1258
  2056
    /** From CLR */
jaroslav@1258
  2057
    private void rotateLeft(Entry<K,V> p) {
jaroslav@1258
  2058
        if (p != null) {
jaroslav@1258
  2059
            Entry<K,V> r = p.right;
jaroslav@1258
  2060
            p.right = r.left;
jaroslav@1258
  2061
            if (r.left != null)
jaroslav@1258
  2062
                r.left.parent = p;
jaroslav@1258
  2063
            r.parent = p.parent;
jaroslav@1258
  2064
            if (p.parent == null)
jaroslav@1258
  2065
                root = r;
jaroslav@1258
  2066
            else if (p.parent.left == p)
jaroslav@1258
  2067
                p.parent.left = r;
jaroslav@1258
  2068
            else
jaroslav@1258
  2069
                p.parent.right = r;
jaroslav@1258
  2070
            r.left = p;
jaroslav@1258
  2071
            p.parent = r;
jaroslav@1258
  2072
        }
jaroslav@1258
  2073
    }
jaroslav@1258
  2074
jaroslav@1258
  2075
    /** From CLR */
jaroslav@1258
  2076
    private void rotateRight(Entry<K,V> p) {
jaroslav@1258
  2077
        if (p != null) {
jaroslav@1258
  2078
            Entry<K,V> l = p.left;
jaroslav@1258
  2079
            p.left = l.right;
jaroslav@1258
  2080
            if (l.right != null) l.right.parent = p;
jaroslav@1258
  2081
            l.parent = p.parent;
jaroslav@1258
  2082
            if (p.parent == null)
jaroslav@1258
  2083
                root = l;
jaroslav@1258
  2084
            else if (p.parent.right == p)
jaroslav@1258
  2085
                p.parent.right = l;
jaroslav@1258
  2086
            else p.parent.left = l;
jaroslav@1258
  2087
            l.right = p;
jaroslav@1258
  2088
            p.parent = l;
jaroslav@1258
  2089
        }
jaroslav@1258
  2090
    }
jaroslav@1258
  2091
jaroslav@1258
  2092
    /** From CLR */
jaroslav@1258
  2093
    private void fixAfterInsertion(Entry<K,V> x) {
jaroslav@1258
  2094
        x.color = RED;
jaroslav@1258
  2095
jaroslav@1258
  2096
        while (x != null && x != root && x.parent.color == RED) {
jaroslav@1258
  2097
            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
jaroslav@1258
  2098
                Entry<K,V> y = rightOf(parentOf(parentOf(x)));
jaroslav@1258
  2099
                if (colorOf(y) == RED) {
jaroslav@1258
  2100
                    setColor(parentOf(x), BLACK);
jaroslav@1258
  2101
                    setColor(y, BLACK);
jaroslav@1258
  2102
                    setColor(parentOf(parentOf(x)), RED);
jaroslav@1258
  2103
                    x = parentOf(parentOf(x));
jaroslav@1258
  2104
                } else {
jaroslav@1258
  2105
                    if (x == rightOf(parentOf(x))) {
jaroslav@1258
  2106
                        x = parentOf(x);
jaroslav@1258
  2107
                        rotateLeft(x);
jaroslav@1258
  2108
                    }
jaroslav@1258
  2109
                    setColor(parentOf(x), BLACK);
jaroslav@1258
  2110
                    setColor(parentOf(parentOf(x)), RED);
jaroslav@1258
  2111
                    rotateRight(parentOf(parentOf(x)));
jaroslav@1258
  2112
                }
jaroslav@1258
  2113
            } else {
jaroslav@1258
  2114
                Entry<K,V> y = leftOf(parentOf(parentOf(x)));
jaroslav@1258
  2115
                if (colorOf(y) == RED) {
jaroslav@1258
  2116
                    setColor(parentOf(x), BLACK);
jaroslav@1258
  2117
                    setColor(y, BLACK);
jaroslav@1258
  2118
                    setColor(parentOf(parentOf(x)), RED);
jaroslav@1258
  2119
                    x = parentOf(parentOf(x));
jaroslav@1258
  2120
                } else {
jaroslav@1258
  2121
                    if (x == leftOf(parentOf(x))) {
jaroslav@1258
  2122
                        x = parentOf(x);
jaroslav@1258
  2123
                        rotateRight(x);
jaroslav@1258
  2124
                    }
jaroslav@1258
  2125
                    setColor(parentOf(x), BLACK);
jaroslav@1258
  2126
                    setColor(parentOf(parentOf(x)), RED);
jaroslav@1258
  2127
                    rotateLeft(parentOf(parentOf(x)));
jaroslav@1258
  2128
                }
jaroslav@1258
  2129
            }
jaroslav@1258
  2130
        }
jaroslav@1258
  2131
        root.color = BLACK;
jaroslav@1258
  2132
    }
jaroslav@1258
  2133
jaroslav@1258
  2134
    /**
jaroslav@1258
  2135
     * Delete node p, and then rebalance the tree.
jaroslav@1258
  2136
     */
jaroslav@1258
  2137
    private void deleteEntry(Entry<K,V> p) {
jaroslav@1258
  2138
        modCount++;
jaroslav@1258
  2139
        size--;
jaroslav@1258
  2140
jaroslav@1258
  2141
        // If strictly internal, copy successor's element to p and then make p
jaroslav@1258
  2142
        // point to successor.
jaroslav@1258
  2143
        if (p.left != null && p.right != null) {
jaroslav@1258
  2144
            Entry<K,V> s = successor(p);
jaroslav@1258
  2145
            p.key = s.key;
jaroslav@1258
  2146
            p.value = s.value;
jaroslav@1258
  2147
            p = s;
jaroslav@1258
  2148
        } // p has 2 children
jaroslav@1258
  2149
jaroslav@1258
  2150
        // Start fixup at replacement node, if it exists.
jaroslav@1258
  2151
        Entry<K,V> replacement = (p.left != null ? p.left : p.right);
jaroslav@1258
  2152
jaroslav@1258
  2153
        if (replacement != null) {
jaroslav@1258
  2154
            // Link replacement to parent
jaroslav@1258
  2155
            replacement.parent = p.parent;
jaroslav@1258
  2156
            if (p.parent == null)
jaroslav@1258
  2157
                root = replacement;
jaroslav@1258
  2158
            else if (p == p.parent.left)
jaroslav@1258
  2159
                p.parent.left  = replacement;
jaroslav@1258
  2160
            else
jaroslav@1258
  2161
                p.parent.right = replacement;
jaroslav@1258
  2162
jaroslav@1258
  2163
            // Null out links so they are OK to use by fixAfterDeletion.
jaroslav@1258
  2164
            p.left = p.right = p.parent = null;
jaroslav@1258
  2165
jaroslav@1258
  2166
            // Fix replacement
jaroslav@1258
  2167
            if (p.color == BLACK)
jaroslav@1258
  2168
                fixAfterDeletion(replacement);
jaroslav@1258
  2169
        } else if (p.parent == null) { // return if we are the only node.
jaroslav@1258
  2170
            root = null;
jaroslav@1258
  2171
        } else { //  No children. Use self as phantom replacement and unlink.
jaroslav@1258
  2172
            if (p.color == BLACK)
jaroslav@1258
  2173
                fixAfterDeletion(p);
jaroslav@1258
  2174
jaroslav@1258
  2175
            if (p.parent != null) {
jaroslav@1258
  2176
                if (p == p.parent.left)
jaroslav@1258
  2177
                    p.parent.left = null;
jaroslav@1258
  2178
                else if (p == p.parent.right)
jaroslav@1258
  2179
                    p.parent.right = null;
jaroslav@1258
  2180
                p.parent = null;
jaroslav@1258
  2181
            }
jaroslav@1258
  2182
        }
jaroslav@1258
  2183
    }
jaroslav@1258
  2184
jaroslav@1258
  2185
    /** From CLR */
jaroslav@1258
  2186
    private void fixAfterDeletion(Entry<K,V> x) {
jaroslav@1258
  2187
        while (x != root && colorOf(x) == BLACK) {
jaroslav@1258
  2188
            if (x == leftOf(parentOf(x))) {
jaroslav@1258
  2189
                Entry<K,V> sib = rightOf(parentOf(x));
jaroslav@1258
  2190
jaroslav@1258
  2191
                if (colorOf(sib) == RED) {
jaroslav@1258
  2192
                    setColor(sib, BLACK);
jaroslav@1258
  2193
                    setColor(parentOf(x), RED);
jaroslav@1258
  2194
                    rotateLeft(parentOf(x));
jaroslav@1258
  2195
                    sib = rightOf(parentOf(x));
jaroslav@1258
  2196
                }
jaroslav@1258
  2197
jaroslav@1258
  2198
                if (colorOf(leftOf(sib))  == BLACK &&
jaroslav@1258
  2199
                    colorOf(rightOf(sib)) == BLACK) {
jaroslav@1258
  2200
                    setColor(sib, RED);
jaroslav@1258
  2201
                    x = parentOf(x);
jaroslav@1258
  2202
                } else {
jaroslav@1258
  2203
                    if (colorOf(rightOf(sib)) == BLACK) {
jaroslav@1258
  2204
                        setColor(leftOf(sib), BLACK);
jaroslav@1258
  2205
                        setColor(sib, RED);
jaroslav@1258
  2206
                        rotateRight(sib);
jaroslav@1258
  2207
                        sib = rightOf(parentOf(x));
jaroslav@1258
  2208
                    }
jaroslav@1258
  2209
                    setColor(sib, colorOf(parentOf(x)));
jaroslav@1258
  2210
                    setColor(parentOf(x), BLACK);
jaroslav@1258
  2211
                    setColor(rightOf(sib), BLACK);
jaroslav@1258
  2212
                    rotateLeft(parentOf(x));
jaroslav@1258
  2213
                    x = root;
jaroslav@1258
  2214
                }
jaroslav@1258
  2215
            } else { // symmetric
jaroslav@1258
  2216
                Entry<K,V> sib = leftOf(parentOf(x));
jaroslav@1258
  2217
jaroslav@1258
  2218
                if (colorOf(sib) == RED) {
jaroslav@1258
  2219
                    setColor(sib, BLACK);
jaroslav@1258
  2220
                    setColor(parentOf(x), RED);
jaroslav@1258
  2221
                    rotateRight(parentOf(x));
jaroslav@1258
  2222
                    sib = leftOf(parentOf(x));
jaroslav@1258
  2223
                }
jaroslav@1258
  2224
jaroslav@1258
  2225
                if (colorOf(rightOf(sib)) == BLACK &&
jaroslav@1258
  2226
                    colorOf(leftOf(sib)) == BLACK) {
jaroslav@1258
  2227
                    setColor(sib, RED);
jaroslav@1258
  2228
                    x = parentOf(x);
jaroslav@1258
  2229
                } else {
jaroslav@1258
  2230
                    if (colorOf(leftOf(sib)) == BLACK) {
jaroslav@1258
  2231
                        setColor(rightOf(sib), BLACK);
jaroslav@1258
  2232
                        setColor(sib, RED);
jaroslav@1258
  2233
                        rotateLeft(sib);
jaroslav@1258
  2234
                        sib = leftOf(parentOf(x));
jaroslav@1258
  2235
                    }
jaroslav@1258
  2236
                    setColor(sib, colorOf(parentOf(x)));
jaroslav@1258
  2237
                    setColor(parentOf(x), BLACK);
jaroslav@1258
  2238
                    setColor(leftOf(sib), BLACK);
jaroslav@1258
  2239
                    rotateRight(parentOf(x));
jaroslav@1258
  2240
                    x = root;
jaroslav@1258
  2241
                }
jaroslav@1258
  2242
            }
jaroslav@1258
  2243
        }
jaroslav@1258
  2244
jaroslav@1258
  2245
        setColor(x, BLACK);
jaroslav@1258
  2246
    }
jaroslav@1258
  2247
jaroslav@1258
  2248
    private static final long serialVersionUID = 919286545866124006L;
jaroslav@1258
  2249
jaroslav@1258
  2250
    /**
jaroslav@1258
  2251
     * Save the state of the {@code TreeMap} instance to a stream (i.e.,
jaroslav@1258
  2252
     * serialize it).
jaroslav@1258
  2253
     *
jaroslav@1258
  2254
     * @serialData The <em>size</em> of the TreeMap (the number of key-value
jaroslav@1258
  2255
     *             mappings) is emitted (int), followed by the key (Object)
jaroslav@1258
  2256
     *             and value (Object) for each key-value mapping represented
jaroslav@1258
  2257
     *             by the TreeMap. The key-value mappings are emitted in
jaroslav@1258
  2258
     *             key-order (as determined by the TreeMap's Comparator,
jaroslav@1258
  2259
     *             or by the keys' natural ordering if the TreeMap has no
jaroslav@1258
  2260
     *             Comparator).
jaroslav@1258
  2261
     */
jaroslav@1258
  2262
    private void writeObject(java.io.ObjectOutputStream s)
jaroslav@1258
  2263
        throws java.io.IOException {
jaroslav@1258
  2264
        // Write out the Comparator and any hidden stuff
jaroslav@1258
  2265
        s.defaultWriteObject();
jaroslav@1258
  2266
jaroslav@1258
  2267
        // Write out size (number of Mappings)
jaroslav@1258
  2268
        s.writeInt(size);
jaroslav@1258
  2269
jaroslav@1258
  2270
        // Write out keys and values (alternating)
jaroslav@1258
  2271
        for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) {
jaroslav@1258
  2272
            Map.Entry<K,V> e = i.next();
jaroslav@1258
  2273
            s.writeObject(e.getKey());
jaroslav@1258
  2274
            s.writeObject(e.getValue());
jaroslav@1258
  2275
        }
jaroslav@1258
  2276
    }
jaroslav@1258
  2277
jaroslav@1258
  2278
    /**
jaroslav@1258
  2279
     * Reconstitute the {@code TreeMap} instance from a stream (i.e.,
jaroslav@1258
  2280
     * deserialize it).
jaroslav@1258
  2281
     */
jaroslav@1258
  2282
    private void readObject(final java.io.ObjectInputStream s)
jaroslav@1258
  2283
        throws java.io.IOException, ClassNotFoundException {
jaroslav@1258
  2284
        // Read in the Comparator and any hidden stuff
jaroslav@1258
  2285
        s.defaultReadObject();
jaroslav@1258
  2286
jaroslav@1258
  2287
        // Read in size
jaroslav@1258
  2288
        int size = s.readInt();
jaroslav@1258
  2289
jaroslav@1258
  2290
        buildFromSorted(size, null, s, null);
jaroslav@1258
  2291
    }
jaroslav@1258
  2292
jaroslav@1258
  2293
    /** Intended to be called only from TreeSet.readObject */
jaroslav@1258
  2294
    void readTreeSet(int size, java.io.ObjectInputStream s, V defaultVal)
jaroslav@1258
  2295
        throws java.io.IOException, ClassNotFoundException {
jaroslav@1258
  2296
        buildFromSorted(size, null, s, defaultVal);
jaroslav@1258
  2297
    }
jaroslav@1258
  2298
jaroslav@1258
  2299
    /** Intended to be called only from TreeSet.addAll */
jaroslav@1258
  2300
    void addAllForTreeSet(SortedSet<? extends K> set, V defaultVal) {
jaroslav@1258
  2301
        try {
jaroslav@1258
  2302
            buildFromSorted(set.size(), set.iterator(), null, defaultVal);
jaroslav@1258
  2303
        } catch (java.io.IOException cannotHappen) {
jaroslav@1258
  2304
        } catch (ClassNotFoundException cannotHappen) {
jaroslav@1258
  2305
        }
jaroslav@1258
  2306
    }
jaroslav@1258
  2307
jaroslav@1258
  2308
jaroslav@1258
  2309
    /**
jaroslav@1258
  2310
     * Linear time tree building algorithm from sorted data.  Can accept keys
jaroslav@1258
  2311
     * and/or values from iterator or stream. This leads to too many
jaroslav@1258
  2312
     * parameters, but seems better than alternatives.  The four formats
jaroslav@1258
  2313
     * that this method accepts are:
jaroslav@1258
  2314
     *
jaroslav@1258
  2315
     *    1) An iterator of Map.Entries.  (it != null, defaultVal == null).
jaroslav@1258
  2316
     *    2) An iterator of keys.         (it != null, defaultVal != null).
jaroslav@1258
  2317
     *    3) A stream of alternating serialized keys and values.
jaroslav@1258
  2318
     *                                   (it == null, defaultVal == null).
jaroslav@1258
  2319
     *    4) A stream of serialized keys. (it == null, defaultVal != null).
jaroslav@1258
  2320
     *
jaroslav@1258
  2321
     * It is assumed that the comparator of the TreeMap is already set prior
jaroslav@1258
  2322
     * to calling this method.
jaroslav@1258
  2323
     *
jaroslav@1258
  2324
     * @param size the number of keys (or key-value pairs) to be read from
jaroslav@1258
  2325
     *        the iterator or stream
jaroslav@1258
  2326
     * @param it If non-null, new entries are created from entries
jaroslav@1258
  2327
     *        or keys read from this iterator.
jaroslav@1258
  2328
     * @param str If non-null, new entries are created from keys and
jaroslav@1258
  2329
     *        possibly values read from this stream in serialized form.
jaroslav@1258
  2330
     *        Exactly one of it and str should be non-null.
jaroslav@1258
  2331
     * @param defaultVal if non-null, this default value is used for
jaroslav@1258
  2332
     *        each value in the map.  If null, each value is read from
jaroslav@1258
  2333
     *        iterator or stream, as described above.
jaroslav@1258
  2334
     * @throws IOException propagated from stream reads. This cannot
jaroslav@1258
  2335
     *         occur if str is null.
jaroslav@1258
  2336
     * @throws ClassNotFoundException propagated from readObject.
jaroslav@1258
  2337
     *         This cannot occur if str is null.
jaroslav@1258
  2338
     */
jaroslav@1258
  2339
    private void buildFromSorted(int size, Iterator it,
jaroslav@1258
  2340
                                 java.io.ObjectInputStream str,
jaroslav@1258
  2341
                                 V defaultVal)
jaroslav@1258
  2342
        throws  java.io.IOException, ClassNotFoundException {
jaroslav@1258
  2343
        this.size = size;
jaroslav@1258
  2344
        root = buildFromSorted(0, 0, size-1, computeRedLevel(size),
jaroslav@1258
  2345
                               it, str, defaultVal);
jaroslav@1258
  2346
    }
jaroslav@1258
  2347
jaroslav@1258
  2348
    /**
jaroslav@1258
  2349
     * Recursive "helper method" that does the real work of the
jaroslav@1258
  2350
     * previous method.  Identically named parameters have
jaroslav@1258
  2351
     * identical definitions.  Additional parameters are documented below.
jaroslav@1258
  2352
     * It is assumed that the comparator and size fields of the TreeMap are
jaroslav@1258
  2353
     * already set prior to calling this method.  (It ignores both fields.)
jaroslav@1258
  2354
     *
jaroslav@1258
  2355
     * @param level the current level of tree. Initial call should be 0.
jaroslav@1258
  2356
     * @param lo the first element index of this subtree. Initial should be 0.
jaroslav@1258
  2357
     * @param hi the last element index of this subtree.  Initial should be
jaroslav@1258
  2358
     *        size-1.
jaroslav@1258
  2359
     * @param redLevel the level at which nodes should be red.
jaroslav@1258
  2360
     *        Must be equal to computeRedLevel for tree of this size.
jaroslav@1258
  2361
     */
jaroslav@1258
  2362
    private final Entry<K,V> buildFromSorted(int level, int lo, int hi,
jaroslav@1258
  2363
                                             int redLevel,
jaroslav@1258
  2364
                                             Iterator it,
jaroslav@1258
  2365
                                             java.io.ObjectInputStream str,
jaroslav@1258
  2366
                                             V defaultVal)
jaroslav@1258
  2367
        throws  java.io.IOException, ClassNotFoundException {
jaroslav@1258
  2368
        /*
jaroslav@1258
  2369
         * Strategy: The root is the middlemost element. To get to it, we
jaroslav@1258
  2370
         * have to first recursively construct the entire left subtree,
jaroslav@1258
  2371
         * so as to grab all of its elements. We can then proceed with right
jaroslav@1258
  2372
         * subtree.
jaroslav@1258
  2373
         *
jaroslav@1258
  2374
         * The lo and hi arguments are the minimum and maximum
jaroslav@1258
  2375
         * indices to pull out of the iterator or stream for current subtree.
jaroslav@1258
  2376
         * They are not actually indexed, we just proceed sequentially,
jaroslav@1258
  2377
         * ensuring that items are extracted in corresponding order.
jaroslav@1258
  2378
         */
jaroslav@1258
  2379
jaroslav@1258
  2380
        if (hi < lo) return null;
jaroslav@1258
  2381
jaroslav@1258
  2382
        int mid = (lo + hi) >>> 1;
jaroslav@1258
  2383
jaroslav@1258
  2384
        Entry<K,V> left  = null;
jaroslav@1258
  2385
        if (lo < mid)
jaroslav@1258
  2386
            left = buildFromSorted(level+1, lo, mid - 1, redLevel,
jaroslav@1258
  2387
                                   it, str, defaultVal);
jaroslav@1258
  2388
jaroslav@1258
  2389
        // extract key and/or value from iterator or stream
jaroslav@1258
  2390
        K key;
jaroslav@1258
  2391
        V value;
jaroslav@1258
  2392
        if (it != null) {
jaroslav@1258
  2393
            if (defaultVal==null) {
jaroslav@1258
  2394
                Map.Entry<K,V> entry = (Map.Entry<K,V>)it.next();
jaroslav@1258
  2395
                key = entry.getKey();
jaroslav@1258
  2396
                value = entry.getValue();
jaroslav@1258
  2397
            } else {
jaroslav@1258
  2398
                key = (K)it.next();
jaroslav@1258
  2399
                value = defaultVal;
jaroslav@1258
  2400
            }
jaroslav@1258
  2401
        } else { // use stream
jaroslav@1258
  2402
            key = (K) str.readObject();
jaroslav@1258
  2403
            value = (defaultVal != null ? defaultVal : (V) str.readObject());
jaroslav@1258
  2404
        }
jaroslav@1258
  2405
jaroslav@1258
  2406
        Entry<K,V> middle =  new Entry<>(key, value, null);
jaroslav@1258
  2407
jaroslav@1258
  2408
        // color nodes in non-full bottommost level red
jaroslav@1258
  2409
        if (level == redLevel)
jaroslav@1258
  2410
            middle.color = RED;
jaroslav@1258
  2411
jaroslav@1258
  2412
        if (left != null) {
jaroslav@1258
  2413
            middle.left = left;
jaroslav@1258
  2414
            left.parent = middle;
jaroslav@1258
  2415
        }
jaroslav@1258
  2416
jaroslav@1258
  2417
        if (mid < hi) {
jaroslav@1258
  2418
            Entry<K,V> right = buildFromSorted(level+1, mid+1, hi, redLevel,
jaroslav@1258
  2419
                                               it, str, defaultVal);
jaroslav@1258
  2420
            middle.right = right;
jaroslav@1258
  2421
            right.parent = middle;
jaroslav@1258
  2422
        }
jaroslav@1258
  2423
jaroslav@1258
  2424
        return middle;
jaroslav@1258
  2425
    }
jaroslav@1258
  2426
jaroslav@1258
  2427
    /**
jaroslav@1258
  2428
     * Find the level down to which to assign all nodes BLACK.  This is the
jaroslav@1258
  2429
     * last `full' level of the complete binary tree produced by
jaroslav@1258
  2430
     * buildTree. The remaining nodes are colored RED. (This makes a `nice'
jaroslav@1258
  2431
     * set of color assignments wrt future insertions.) This level number is
jaroslav@1258
  2432
     * computed by finding the number of splits needed to reach the zeroeth
jaroslav@1258
  2433
     * node.  (The answer is ~lg(N), but in any case must be computed by same
jaroslav@1258
  2434
     * quick O(lg(N)) loop.)
jaroslav@1258
  2435
     */
jaroslav@1258
  2436
    private static int computeRedLevel(int sz) {
jaroslav@1258
  2437
        int level = 0;
jaroslav@1258
  2438
        for (int m = sz - 1; m >= 0; m = m / 2 - 1)
jaroslav@1258
  2439
            level++;
jaroslav@1258
  2440
        return level;
jaroslav@1258
  2441
    }
jaroslav@1258
  2442
}