blob: 432b20cf9278b2a4481b4af1217c8f2dbae16a35 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.util;
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.A;
import org.jetbrains.annotations.Nullable;
/**
* Lean map implementation that keeps up to five entries in its fields.
* {@code Null}-keys are not supported.
*/
public class GridLeanMap<K, V> extends GridSerializableMap<K, V> implements Cloneable {
/** */
private static final long serialVersionUID = 0L;
/** Implementation used internally. */
private LeanMap<K, V> map;
/**
* Constructs lean map with initial size of {@code 3}.
*/
public GridLeanMap() {
this(3);
}
/**
* Constructs lean map with initial size.
* <p>
* If given size is greater than zero then map activates batch mode for <tt>put()</tt>
* operations. In this mode map allows to put up to <tt>size</tt> number of key-value
* pairs without internal size optimization, i.e. each next <tt>put()</tt> in batch
* doesn't switch backing implementation so that initial implementation is used as long
* as its capacity allows.
* <p>
* Note that any removal operation either through iterator or map
* itself turns batch mode off and map starts optimizing size after any modification.
*
* @param size Initial size.
*/
public GridLeanMap(int size) {
assert size >= 0;
if (size == 0)
map = null;
else if (size == 1)
map = new Map1<>();
else if (size == 2)
map = new Map2<>();
else if (size == 3)
map = new Map3<>();
else if (size == 4)
map = new Map4<>();
else if (size == 5)
map = new Map5<>();
else
map = new LeanHashMap<>(IgniteUtils.capacity(size), 0.75f);
}
/**
* Constructs lean map.
*
* @param m Map to copy entries from.
*/
public GridLeanMap(Map<K, V> m) {
buildFrom(m);
}
/**
* @param m Map to build from.
*/
private void buildFrom(Map<K, V> m) {
Iterator<Entry<K, V>> iter = m.entrySet().iterator();
if (m.isEmpty())
map = null;
else if (m.size() == 1) {
Entry<K, V> e = iter.next();
map = new Map1<>(e.getKey(), e.getValue());
}
else if (m.size() == 2) {
Entry<K, V> e1 = iter.next();
Entry<K, V> e2 = iter.next();
map = new Map2<>(e1.getKey(), e1.getValue(), e2.getKey(), e2.getValue());
}
else if (m.size() == 3) {
Entry<K, V> e1 = iter.next();
Entry<K, V> e2 = iter.next();
Entry<K, V> e3 = iter.next();
map = new Map3<>(e1.getKey(), e1.getValue(), e2.getKey(), e2.getValue(), e3.getKey(), e3.getValue());
}
else if (m.size() == 4) {
Entry<K, V> e1 = iter.next();
Entry<K, V> e2 = iter.next();
Entry<K, V> e3 = iter.next();
Entry<K, V> e4 = iter.next();
map = new Map4<>(e1.getKey(), e1.getValue(), e2.getKey(), e2.getValue(), e3.getKey(), e3.getValue(),
e4.getKey(), e4.getValue());
}
else if (m.size() == 5) {
Entry<K, V> e1 = iter.next();
Entry<K, V> e2 = iter.next();
Entry<K, V> e3 = iter.next();
Entry<K, V> e4 = iter.next();
Entry<K, V> e5 = iter.next();
map = new Map5<>(e1.getKey(), e1.getValue(), e2.getKey(), e2.getValue(), e3.getKey(), e3.getValue(),
e4.getKey(), e4.getValue(), e5.getKey(), e5.getValue());
}
else
map = new LeanHashMap<>(m);
}
/** {@inheritDoc} */
@Override public int size() {
return map != null ? map.size() : 0;
}
/** {@inheritDoc} */
@Override public boolean containsKey(Object key) {
A.notNull(key, "key");
return map != null && map.containsKey(key);
}
/** {@inheritDoc} */
@Override public boolean containsValue(Object val) {
return map != null && map.containsValue(val);
}
/** {@inheritDoc} */
@Nullable @Override public V get(Object key) {
A.notNull(key, "key");
return map != null ? map.get(key) : null;
}
/** {@inheritDoc} */
@Nullable @Override public V put(K key, V val) throws NullPointerException {
A.notNull(key, "key");
if (map == null) {
map = new Map1<>(key, val);
return null;
}
if (!map.isFull() || map.containsKey(key))
return map.put(key, val);
int size = map.size();
// Switch implementation.
if (size == 1) {
Map1<K, V> m = (Map1<K, V>)map;
map = new Map2<>(m.k1, m.v1, key, val);
}
else if (size == 2) {
Map2<K, V> m = (Map2<K, V>)map;
map = new Map3<>(m.k1, m.v1, m.k2, m.v2, key, val);
}
else if (size == 3) {
Map3<K, V> m = (Map3<K, V>)map;
map = new Map4<>(m.k1, m.v1, m.k2, m.v2, m.k3, m.v3, key, val);
}
else if (size == 4) {
Map4<K, V> m = (Map4<K, V>)map;
map = new Map5<>(m.k1, m.v1, m.k2, m.v2, m.k3, m.v3, m.k4, m.v4, key, val);
}
else if (size == 5) {
Map<K, V> m = map;
map = new LeanHashMap<>(6, 1.0f);
map.putAll(m);
map.put(key, val);
}
else
map.put(key, val);
return null;
}
/** {@inheritDoc} */
@Nullable @Override public V remove(Object key) {
A.notNull(key, "key");
V old;
if (map instanceof LeanHashMap) {
old = map.remove(key);
if (map.size() > 5)
return old;
else {
buildFrom(map);
return old;
}
}
else {
if (map == null)
return null;
int size = map.size();
old = map.remove(key);
if (map.size() < size)
buildFrom(map);
return old;
}
}
/** {@inheritDoc} */
@Override public void clear() {
map = null;
}
/** {@inheritDoc} */
@Override public Set<Entry<K, V>> entrySet() {
return new EntrySet();
}
/** {@inheritDoc} */
@SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException"})
@Override protected Object clone() {
try {
GridLeanMap<K, V> clone = (GridLeanMap<K, V>)super.clone();
clone.buildFrom(this);
return clone;
}
catch (CloneNotSupportedException ignore) {
throw new InternalError();
}
}
/**
* Entry set.
*/
private class EntrySet extends AbstractSet<Entry<K, V>> {
/** {@inheritDoc} */
@Override public Iterator<Entry<K, V>> iterator() {
return new Iterator<Entry<K, V>>() {
/** */
private int idx = -1;
/** */
private Iterator<Entry<K, V>> mapIter;
/** */
private Entry<K, V> curEnt;
/**
* @param forceNew If forced to create new instance.
* @return Iterator for internal map entry set.
*/
@SuppressWarnings("IfMayBeConditional")
private Iterator<Entry<K, V>> getMapIterator(boolean forceNew) {
if (mapIter == null || forceNew) {
if (map != null)
mapIter = map.entrySet().iterator();
else {
mapIter = new Iterator<Entry<K, V>>() {
@Override public boolean hasNext() {
return false;
}
@Override public Entry<K, V> next() {
throw new NoSuchElementException();
}
@Override public void remove() {
throw new IllegalStateException();
}
};
}
}
return mapIter;
}
@Override public boolean hasNext() {
return map != null && getMapIterator(false).hasNext();
}
@Override public Entry<K, V> next() {
if (!hasNext())
throw new NoSuchElementException();
idx++;
return curEnt = getMapIterator(false).next();
}
@Override public void remove() {
if (curEnt == null)
throw new IllegalStateException();
GridLeanMap.this.remove(curEnt.getKey());
curEnt = null;
mapIter = getMapIterator(true);
for (int i = 0; i < idx && mapIter.hasNext(); i++)
mapIter.next();
idx--;
}
};
}
/** {@inheritDoc} */
@Override public int size() {
return GridLeanMap.this.size();
}
}
/**
*
*/
private interface LeanMap<K, V> extends Map<K, V> {
/**
* @return {@code True} if map is full.
*/
public boolean isFull();
}
/**
* Map for single entry.
*/
private static class Map1<K, V> extends AbstractMap<K, V> implements LeanMap<K, V>, Serializable {
/** */
private static final long serialVersionUID = 0L;
/** */
protected K k1;
/** */
protected V v1;
/**
* Constructs map.
*/
Map1() {
// No-op.
}
/**
* Constructs map.
*
* @param k1 Key.
* @param v1 Value.
*/
Map1(K k1, V v1) {
this.k1 = k1;
this.v1 = v1;
}
/** {@inheritDoc} */
@Override public boolean isFull() {
return size() == 1;
}
/** {@inheritDoc} */
@Nullable @Override public V remove(Object key) {
V res = null;
if (F.eq(key, k1)) {
res = v1;
v1 = null;
k1 = null;
}
return res;
}
/** {@inheritDoc} */
@Override public int size() {
return k1 != null ? 1 : 0;
}
/** {@inheritDoc} */
@Override public boolean isEmpty() {
return size() == 0;
}
/** {@inheritDoc} */
@Override public boolean containsKey(Object key) {
return k1 != null && F.eq(key, k1);
}
/** {@inheritDoc} */
@Override public boolean containsValue(Object val) {
return k1 != null && F.eq(val, v1);
}
/** {@inheritDoc} */
@Nullable @Override public V get(Object key) {
return k1 != null && F.eq(key, k1) ? v1 : null;
}
/**
* Puts key-value pair into map only if given key is already contained in the map
* or there are free slots.
* Note that this implementation of {@link Map#put(Object, Object)} does not match
* general contract of {@link Map} interface and serves only for internal purposes.
*
* @param key Key.
* @param val Value.
* @return Previous value associated with given key.
*/
@Nullable @Override public V put(K key, V val) {
V oldVal = get(key);
if (k1 == null || F.eq(k1, key)) {
k1 = key;
v1 = val;
}
return oldVal;
}
/**
* @param key Key.
* @param val Value.
* @return New entry.
*/
protected Entry<K, V> e(K key, V val) {
return new SimpleImmutableEntry<>(key, val);
}
/** {@inheritDoc} */
@Override public Set<Entry<K, V>> entrySet() {
return new AbstractSet<Entry<K, V>>() {
@Override public Iterator<Entry<K, V>> iterator() {
return new Iterator<Entry<K, V>>() {
private int idx;
@Override public boolean hasNext() {
return idx == 0 && k1 != null;
}
@Override public Entry<K, V> next() {
if (!hasNext())
throw new NoSuchElementException();
idx = 1;
return e(k1, v1);
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override public int size() {
return Map1.this.size();
}
};
}
}
/**
* Map for two entries.
*/
private static class Map2<K, V> extends Map1<K, V> {
/** */
private static final long serialVersionUID = 0L;
/** */
protected K k2;
/** */
protected V v2;
/**
* Constructs map.
*/
Map2() {
// No-op.
}
/**
* Constructs map.
*
* @param k1 Key1.
* @param v1 Value1.
* @param k2 Key2.
* @param v2 Value2.
*/
Map2(K k1, V v1, K k2, V v2) {
super(k1, v1);
this.k2 = k2;
this.v2 = v2;
}
/** {@inheritDoc} */
@Override public boolean isFull() {
return size() == 2;
}
/** {@inheritDoc} */
@Nullable @Override public V remove(Object key) {
if (F.eq(key, k2)) {
V res = v2;
v2 = null;
k2 = null;
return res;
}
return super.remove(key);
}
/** {@inheritDoc} */
@Override public int size() {
return super.size() + (k2 != null ? 1 : 0);
}
/** {@inheritDoc} */
@Override public boolean containsKey(Object k) {
return super.containsKey(k) || (k2 != null && F.eq(k, k2));
}
/** {@inheritDoc} */
@Override public boolean containsValue(Object v) {
return super.containsValue(v) || (k2 != null && F.eq(v, v2));
}
/** {@inheritDoc} */
@Override public V get(Object k) {
V v = super.get(k);
return v != null ? v : (k2 != null && F.eq(k, k2)) ? v2 : null;
}
/**
* Puts key-value pair into map only if given key is already contained in the map
* or there are free slots.
* Note that this implementation of {@link Map#put(Object, Object)} does not match
* general contract of {@link Map} interface and serves only for internal purposes.
*
* @param key Key.
* @param val Value.
* @return Previous value associated with given key.
*/
@Nullable @Override public V put(K key, V val) throws NullPointerException {
V oldVal = get(key);
if (k1 == null || F.eq(k1, key)) {
k1 = key;
v1 = val;
}
else if (k2 == null || F.eq(k2, key)) {
k2 = key;
v2 = val;
}
return oldVal;
}
/** {@inheritDoc} */
@Override public Set<Entry<K, V>> entrySet() {
return new AbstractSet<Entry<K, V>>() {
@Override public Iterator<Entry<K, V>> iterator() {
return new Iterator<Entry<K, V>>() {
private int idx;
private Entry<K, V> next;
{
if (k1 != null) {
idx = 1;
next = e(k1, v1);
}
else if (k2 != null) {
idx = 2;
next = e(k2, v2);
}
}
@Override public boolean hasNext() {
return next != null;
}
@Override public Entry<K, V> next() {
if (!hasNext())
throw new NoSuchElementException();
Entry<K, V> old = next;
next = null;
if (idx == 1 && k2 != null) {
idx = 2;
next = e(k2, v2);
}
return old;
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override public int size() {
return Map2.this.size();
}
};
}
}
/**
* Map for three entries.
*/
private static class Map3<K, V> extends Map2<K, V> {
/** */
private static final long serialVersionUID = 0L;
/** */
protected K k3;
/** */
protected V v3;
/**
* Constructs map.
*/
Map3() {
// No-op.
}
/**
* Constructs map.
*
* @param k1 Key1.
* @param v1 Value1.
* @param k2 Key2.
* @param v2 Value2.
* @param k3 Key3.
* @param v3 Value3.
*/
Map3(K k1, V v1, K k2, V v2, K k3, V v3) {
super(k1, v1, k2, v2);
this.k3 = k3;
this.v3 = v3;
}
/** {@inheritDoc} */
@Override public boolean isFull() {
return size() == 3;
}
/** {@inheritDoc} */
@Nullable @Override public V remove(Object key) {
if (F.eq(key, k3)) {
V res = v3;
v3 = null;
k3 = null;
return res;
}
return super.remove(key);
}
/** {@inheritDoc} */
@Override public int size() {
return super.size() + (k3 != null ? 1 : 0);
}
/** {@inheritDoc} */
@Override public boolean containsKey(Object k) {
return super.containsKey(k) || (k3 != null && F.eq(k, k3));
}
/** {@inheritDoc} */
@Override public boolean containsValue(Object v) {
return super.containsValue(v) || (k3 != null && F.eq(v, v3));
}
/** {@inheritDoc} */
@Nullable @Override public V get(Object k) {
V v = super.get(k);
return v != null ? v : (k3 != null && F.eq(k, k3)) ? v3 : null;
}
/**
* Puts key-value pair into map only if given key is already contained in the map
* or there are free slots.
* Note that this implementation of {@link Map#put(Object, Object)} does not match
* general contract of {@link Map} interface and serves only for internal purposes.
*
* @param key Key.
* @param val Value.
* @return Previous value associated with given key.
*/
@Nullable @Override public V put(K key, V val) throws NullPointerException {
V oldVal = get(key);
if (k1 == null || F.eq(k1, key)) {
k1 = key;
v1 = val;
}
else if (k2 == null || F.eq(k2, key)) {
k2 = key;
v2 = val;
}
else if (k3 == null || F.eq(k3, key)) {
k3 = key;
v3 = val;
}
return oldVal;
}
/** {@inheritDoc} */
@Override public Set<Entry<K, V>> entrySet() {
return new AbstractSet<Entry<K, V>>() {
@Override public Iterator<Entry<K, V>> iterator() {
return new Iterator<Entry<K, V>>() {
private int idx;
private Entry<K, V> next;
{
if (k1 != null) {
idx = 1;
next = e(k1, v1);
}
else if (k2 != null) {
idx = 2;
next = e(k2, v2);
}
else if (k3 != null) {
idx = 3;
next = e(k3, v3);
}
}
@Override public boolean hasNext() {
return next != null;
}
@SuppressWarnings("fallthrough")
@Override public Entry<K, V> next() {
if (!hasNext())
throw new NoSuchElementException();
Entry<K, V> old = next;
next = null;
switch (idx) {
case 1:
if (k2 != null) {
idx = 2;
next = e(k2, v2);
break;
}
case 2:
if (k3 != null) {
idx = 3;
next = e(k3, v3);
break;
}
}
return old;
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override public int size() {
return Map3.this.size();
}
};
}
}
/**
* Map for four entries.
*/
private static class Map4<K, V> extends Map3<K, V> {
/** */
private static final long serialVersionUID = 0L;
/** */
protected K k4;
/** */
protected V v4;
/**
* Constructs map.
*/
Map4() {
// No-op.
}
/**
* Constructs map.
*
* @param k1 Key1.
* @param v1 Value1.
* @param k2 Key2.
* @param v2 Value2.
* @param k3 Key3.
* @param v3 Value3.
* @param k4 Key4.
* @param v4 Value4.
*/
Map4(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
super(k1, v1, k2, v2, k3, v3);
this.k4 = k4;
this.v4 = v4;
}
/** {@inheritDoc} */
@Override public boolean isFull() {
return size() == 4;
}
/** {@inheritDoc} */
@Nullable @Override public V remove(Object key) {
if (F.eq(key, k4)) {
V res = v4;
v4 = null;
k4 = null;
return res;
}
return super.remove(key);
}
/** {@inheritDoc} */
@Override public int size() {
return super.size() + (k4 != null ? 1 : 0);
}
/** {@inheritDoc} */
@Override public boolean containsKey(Object k) {
return super.containsKey(k) || (k4 != null && F.eq(k, k4));
}
/** {@inheritDoc} */
@Override public boolean containsValue(Object v) {
return super.containsValue(v) || (k4 != null && F.eq(v, v4));
}
/** {@inheritDoc} */
@Nullable @Override public V get(Object k) {
V v = super.get(k);
return v != null ? v : (k4 != null && F.eq(k, k4)) ? v4 : null;
}
/**
* Puts key-value pair into map only if given key is already contained in the map
* or there are free slots.
* Note that this implementation of {@link Map#put(Object, Object)} does not match
* general contract of {@link Map} interface and serves only for internal purposes.
*
* @param key Key.
* @param val Value.
* @return Previous value associated with given key.
*/
@Nullable @Override public V put(K key, V val) throws NullPointerException {
V oldVal = get(key);
if (k1 == null || F.eq(k1, key)) {
k1 = key;
v1 = val;
}
else if (k2 == null || F.eq(k2, key)) {
k2 = key;
v2 = val;
}
else if (k3 == null || F.eq(k3, key)) {
k3 = key;
v3 = val;
}
else if (k4 == null || F.eq(k4, key)) {
k4 = key;
v4 = val;
}
return oldVal;
}
/** {@inheritDoc} */
@Override public Set<Entry<K, V>> entrySet() {
return new AbstractSet<Entry<K, V>>() {
@Override public Iterator<Entry<K, V>> iterator() {
return new Iterator<Entry<K, V>>() {
private int idx;
private Entry<K, V> next;
{
if (k1 != null) {
idx = 1;
next = e(k1, v1);
}
else if (k2 != null) {
idx = 2;
next = e(k2, v2);
}
else if (k3 != null) {
idx = 3;
next = e(k3, v3);
}
else if (k4 != null) {
idx = 4;
next = e(k4, v4);
}
}
@Override public boolean hasNext() {
return next != null;
}
@SuppressWarnings("fallthrough")
@Override public Entry<K, V> next() {
if (!hasNext())
throw new NoSuchElementException();
Entry<K, V> old = next;
next = null;
switch (idx) {
case 1:
if (k2 != null) {
idx = 2;
next = e(k2, v2);
break;
}
case 2:
if (k3 != null) {
idx = 3;
next = e(k3, v3);
break;
}
case 3:
if (k4 != null) {
idx = 4;
next = e(k4, v4);
break;
}
}
return old;
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override public int size() {
return Map4.this.size();
}
};
}
}
/**
* Map for five entries.
*/
private static class Map5<K, V> extends Map4<K, V> {
/** */
private static final long serialVersionUID = 0L;
/** */
private K k5;
/** */
private V v5;
/**
* Constructs map.
*/
Map5() {
// No-op.
}
/**
* Constructs map.
*
* @param k1 Key1.
* @param v1 Value1.
* @param k2 Key2.
* @param v2 Value2.
* @param k3 Key3.
* @param v3 Value3.
* @param k4 Key4.
* @param v4 Value4.
* @param k5 Key5.
* @param v5 Value5.
*/
Map5(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
super(k1, v1, k2, v2, k3, v3, k4, v4);
this.k5 = k5;
this.v5 = v5;
}
/** {@inheritDoc} */
@Override public boolean isFull() {
return size() == 5;
}
/** {@inheritDoc} */
@Nullable @Override public V remove(Object key) {
if (F.eq(key, k5)) {
V res = v5;
v5 = null;
k5 = null;
return res;
}
return super.remove(key);
}
/** {@inheritDoc} */
@Override public int size() {
return super.size() + (k5 != null ? 1 : 0);
}
/** {@inheritDoc} */
@Override public boolean containsKey(Object k) {
return super.containsKey(k) || (k5 != null && F.eq(k, k5));
}
/** {@inheritDoc} */
@Override public boolean containsValue(Object v) {
return super.containsValue(v) || (k5 != null && F.eq(v, v5));
}
/** {@inheritDoc} */
@Nullable @Override public V get(Object k) {
V v = super.get(k);
return v != null ? v : (k5 != null && F.eq(k, k5)) ? v5 : null;
}
/**
* Puts key-value pair into map only if given key is already contained in the map
* or there are free slots.
* Note that this implementation of {@link Map#put(Object, Object)} does not match
* general contract of {@link Map} interface and serves only for internal purposes.
*
* @param key Key.
* @param val Value.
* @return Previous value associated with given key.
*/
@Nullable @Override public V put(K key, V val) throws NullPointerException {
V oldVal = get(key);
if (k1 == null || F.eq(k1, key)) {
k1 = key;
v1 = val;
}
else if (k2 == null || F.eq(k2, key)) {
k2 = key;
v2 = val;
}
else if (k3 == null || F.eq(k3, key)) {
k3 = key;
v3 = val;
}
else if (k4 == null || F.eq(k4, key)) {
k4 = key;
v4 = val;
}
else if (k5 == null || F.eq(k5, key)) {
k5 = key;
v5 = val;
}
return oldVal;
}
/** {@inheritDoc} */
@Override public Set<Entry<K, V>> entrySet() {
return new AbstractSet<Entry<K, V>>() {
@Override public Iterator<Entry<K, V>> iterator() {
return new Iterator<Entry<K, V>>() {
private int idx;
private Entry<K, V> next;
{
if (k1 != null) {
idx = 1;
next = e(k1, v1);
}
else if (k2 != null) {
idx = 2;
next = e(k2, v2);
}
else if (k3 != null) {
idx = 3;
next = e(k3, v3);
}
else if (k4 != null) {
idx = 4;
next = e(k4, v4);
}
else if (k5 != null) {
idx = 5;
next = e(k5, v5);
}
}
@Override public boolean hasNext() {
return next != null;
}
@SuppressWarnings("fallthrough")
@Override public Entry<K, V> next() {
if (!hasNext())
throw new NoSuchElementException();
Entry<K, V> old = next;
next = null;
switch (idx) {
case 1:
if (k2 != null) {
idx = 2;
next = e(k2, v2);
break;
}
case 2:
if (k3 != null) {
idx = 3;
next = e(k3, v3);
break;
}
case 3:
if (k4 != null) {
idx = 4;
next = e(k4, v4);
break;
}
case 4:
if (k5 != null) {
idx = 5;
next = e(k5, v5);
break;
}
}
return old;
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override public int size() {
return Map5.this.size();
}
};
}
}
/**
*
*/
private static class LeanHashMap<K, V> extends HashMap<K, V> implements LeanMap<K, V> {
/** */
private static final long serialVersionUID = 0L;
/**
* @param initCap Capacity.
* @param loadFactor Load factor.
*/
private LeanHashMap(int initCap, float loadFactor) {
super(initCap, loadFactor);
}
/**
* @param m Map.
*/
private LeanHashMap(Map<? extends K, ? extends V> m) {
super(m);
}
/** {@inheritDoc} */
@Override public boolean isFull() {
return false;
}
}
}