1/* 2 * Copyright (C) 2012 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.google.common.collect; 17 18import static com.google.common.base.Preconditions.checkNotNull; 19 20import com.google.common.annotations.GwtCompatible; 21 22import javax.annotation.Nullable; 23 24/** 25 * An implementation of an immutable sorted map with one or more entries. 26 * 27 * @author Louis Wasserman 28 */ 29@GwtCompatible(emulated = true) 30@SuppressWarnings("serial") // uses writeReplace, not default serialization 31final class RegularImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> { 32 private final transient RegularImmutableSortedSet<K> keySet; 33 private final transient ImmutableList<V> valueList; 34 35 RegularImmutableSortedMap(RegularImmutableSortedSet<K> keySet, ImmutableList<V> valueList) { 36 this.keySet = keySet; 37 this.valueList = valueList; 38 } 39 40 RegularImmutableSortedMap( 41 RegularImmutableSortedSet<K> keySet, 42 ImmutableList<V> valueList, 43 ImmutableSortedMap<K, V> descendingMap) { 44 super(descendingMap); 45 this.keySet = keySet; 46 this.valueList = valueList; 47 } 48 49 @Override 50 ImmutableSet<Entry<K, V>> createEntrySet() { 51 return new EntrySet(); 52 } 53 54 private class EntrySet extends ImmutableMapEntrySet<K, V> { 55 @Override 56 public UnmodifiableIterator<Entry<K, V>> iterator() { 57 return asList().iterator(); 58 } 59 60 @Override 61 ImmutableList<Entry<K, V>> createAsList() { 62 return new ImmutableAsList<Entry<K, V>>() { 63 // avoid additional indirection 64 private final ImmutableList<K> keyList = keySet().asList(); 65 66 @Override 67 public Entry<K, V> get(int index) { 68 return Maps.immutableEntry(keyList.get(index), valueList.get(index)); 69 } 70 71 @Override 72 ImmutableCollection<Entry<K, V>> delegateCollection() { 73 return EntrySet.this; 74 } 75 }; 76 } 77 78 @Override 79 ImmutableMap<K, V> map() { 80 return RegularImmutableSortedMap.this; 81 } 82 } 83 84 @Override 85 public ImmutableSortedSet<K> keySet() { 86 return keySet; 87 } 88 89 @Override 90 public ImmutableCollection<V> values() { 91 return valueList; 92 } 93 94 @Override 95 public V get(@Nullable Object key) { 96 int index = keySet.indexOf(key); 97 return (index == -1) ? null : valueList.get(index); 98 } 99 100 private ImmutableSortedMap<K, V> getSubMap(int fromIndex, int toIndex) { 101 if (fromIndex == 0 && toIndex == size()) { 102 return this; 103 } else if (fromIndex == toIndex) { 104 return emptyMap(comparator()); 105 } else { 106 return from( 107 keySet.getSubSet(fromIndex, toIndex), 108 valueList.subList(fromIndex, toIndex)); 109 } 110 } 111 112 @Override 113 public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) { 114 return getSubMap(0, keySet.headIndex(checkNotNull(toKey), inclusive)); 115 } 116 117 @Override 118 public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) { 119 return getSubMap(keySet.tailIndex(checkNotNull(fromKey), inclusive), size()); 120 } 121 122 @Override 123 ImmutableSortedMap<K, V> createDescendingMap() { 124 return new RegularImmutableSortedMap<K, V>( 125 (RegularImmutableSortedSet<K>) keySet.descendingSet(), 126 valueList.reverse(), 127 this); 128 } 129 130} 131