WALA/com.ibm.wala.core/src/com/ibm/wala/util/collections/BimodalMap.java

216 lines
5.5 KiB
Java

/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.collections;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.util.debug.Assertions;
/**
*
* This implementation of Map chooses between one of two implementations,
* depending on the size of the map.
*
* @author sfink
*/
public class BimodalMap<K, V> implements Map<K, V> {
// what's the cutoff between small and big maps?
// this may be a time-space tradeoff; the caller must determine if
// it's willing to put up with slower random access in exchange for
// smaller footprint.
private final int cutOff;
/**
* The implementation we delegate to
*/
private Map<K, V> backingStore;
/**
* @param cutoff
* the map size at which to switch from the small map implementation
* to the large map implementation
*/
public BimodalMap(int cutoff) {
this.cutOff = cutoff;
}
/*
* (non-Javadoc)
*
* @see java.util.Map#size()
*/
public int size() {
return (backingStore == null) ? 0 : backingStore.size();
}
/*
* (non-Javadoc)
*
* @see java.util.Map#isEmpty()
*/
public boolean isEmpty() {
return (backingStore == null) ? true : backingStore.isEmpty();
}
/*
* (non-Javadoc)
*
* @see java.util.Map#containsKey(java.lang.Object)
*/
public boolean containsKey(Object key) {
return (backingStore == null) ? false : backingStore.containsKey(key);
}
/*
* (non-Javadoc)
*
* @see java.util.Map#containsValue(java.lang.Object)
*/
public boolean containsValue(Object value) {
return (backingStore == null) ? false : backingStore.containsValue(value);
}
/*
* (non-Javadoc)
*
* @see java.util.Map#get(java.lang.Object)
*/
public V get(Object key) {
return (backingStore == null) ? null : backingStore.get(key);
}
/*
* (non-Javadoc)
*
* @see java.util.Map#put(java.lang.Object, java.lang.Object)
*/
public V put(K key, V value) {
if (backingStore == null) {
backingStore = new SmallMap<K, V>();
backingStore.put(key, value);
return null;
} else {
if (backingStore instanceof SmallMap) {
V result = backingStore.put(key, value);
if (backingStore.size() > cutOff) {
transferBackingStore();
}
return result;
} else {
return backingStore.put(key, value);
}
}
}
/**
* Switch backing implementation from a SmallMap to a HashMap
*/
private void transferBackingStore() {
if (Assertions.verifyAssertions) {
Assertions._assert(backingStore instanceof SmallMap);
}
SmallMap<K, V> S = (SmallMap<K,V>) backingStore;
backingStore = HashMapFactory.make(2 * S.size());
for (Iterator<K> it = S.keySet().iterator(); it.hasNext();) {
K key = it.next();
V value = S.get(key);
backingStore.put(key, value);
}
}
/*
* (non-Javadoc)
*
* @see java.util.Map#remove(java.lang.Object)
*/
public V remove(Object key) {
return (backingStore == null) ? null : backingStore.remove(key);
}
/*
* (non-Javadoc)
*
* @see java.util.Map#putAll(java.util.Map)
*/
@SuppressWarnings("unchecked")
public void putAll(Map<? extends K, ? extends V> t) {
if (backingStore == null) {
int size = t.size();
if (size > cutOff) {
backingStore = HashMapFactory.make();
} else {
backingStore = new SmallMap<K, V>();
}
backingStore.putAll(t);
return;
} else {
if (backingStore instanceof SmallMap) {
if (t.size() > cutOff) {
Map<K, V> old = backingStore;
backingStore = (Map<K, V>) HashMapFactory.make(t);
backingStore.putAll(old);
} else {
backingStore.putAll(t);
if (backingStore.size() > cutOff) {
transferBackingStore();
}
return;
}
} else {
backingStore.putAll(t);
}
}
}
/*
* (non-Javadoc)
*
* @see java.util.Map#clear()
*/
public void clear() {
backingStore = null;
}
/*
* (non-Javadoc)
*
* @see java.util.Map#keySet()
*/
@SuppressWarnings("unchecked")
public Set<K> keySet() {
return (Set<K>) ((backingStore == null) ? Collections.emptySet() : backingStore.keySet());
}
/*
* (non-Javadoc)
*
* @see java.util.Map#values()
*/
@SuppressWarnings("unchecked")
public Collection<V> values() {
return (Collection<V>) ((backingStore == null) ? Collections.emptySet() : backingStore.values());
}
/*
* (non-Javadoc)
*
* @see java.util.Map#entrySet()
*/
@SuppressWarnings("unchecked")
public Set<Map.Entry<K, V>> entrySet() {
return (Set<Entry<K, V>>) ((backingStore == null) ? Collections.emptySet() : backingStore.entrySet());
}
}