/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package com.espertech.esper.collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
/**
* reference-counting set based on a HashMap implementation that stores keys and a reference counter for
* each unique key value. Each time the same key is added, the reference counter increases.
* Each time a key is removed, the reference counter decreases.
*/
public class RefCountedSet<K>
{
private Map<K, Integer> refSet;
private int numValues;
/**
* Constructor.
*/
public RefCountedSet()
{
refSet = new HashMap<K, Integer>();
}
public RefCountedSet(Map<K, Integer> refSet, int numValues) {
this.refSet = refSet;
this.numValues = numValues;
}
/**
* Clear out the collection.
*/
public void clear()
{
refSet.clear();
numValues = 0;
}
/**
* Add a key to the set. Add with a reference count of one if the key didn't exist in the set.
* Increase the reference count by one if the key already exists.
* Return true if this is the first time the key was encountered, or false if key is already in set.
* @param key to add
* @return true if the key is not in the set already, false if the key is already in the set
*/
public boolean add(K key)
{
Integer value = refSet.get(key);
if (value == null)
{
refSet.put(key, 1);
numValues++;
return true;
}
value++;
numValues++;
refSet.put(key, value);
return false;
}
/**
* Add a key to the set with the given number of references.
* @param key to add
* @param numReferences initial number of references
*/
public void add(K key, int numReferences)
{
Integer value = refSet.get(key);
if (value == null)
{
refSet.put(key, numReferences);
numValues+=numReferences;
return;
}
throw new IllegalArgumentException("Key '" + key + "' already in collection");
}
/**
* Removed a key to the set. Removes the key if the reference count is one.
* Decreases the reference count by one if the reference count is more then one.
* Return true if the reference count was one and the key thus removed, or false if key is stays in set.
* @param key to add
* @return true if the key is removed, false if it stays in the set
* @throws IllegalStateException is a key is removed that wasn't added to the map
*/
public boolean remove(K key)
{
Integer value = refSet.get(key);
if (value == null)
{
return true; // ignore duplcate removals
}
if (value == 1)
{
refSet.remove(key);
numValues--;
return true;
}
value--;
refSet.put(key, value);
numValues--;
return false;
}
/**
* Remove a key from the set regardless of the number of references.
* @param key to add
* @return true if the key is removed, false if the key was not found
* @throws IllegalStateException if a key is removed that wasn't added to the map
*/
public boolean removeAll(K key)
{
Integer value = refSet.remove(key);
return (value != null);
}
/**
* Returns an iterator over the entry set.
* @return entry set iterator
*/
public Iterator<Map.Entry<K, Integer>> entryIterator()
{
return refSet.entrySet().iterator();
}
/**
* Returns a key iterator.
* @return key iterator
*/
public Iterator<K> keyIterator()
{
return refSet.keySet().iterator();
}
/**
* Returns the number of values in the collection.
* @return size
*/
public int size()
{
return numValues;
}
public Map<K, Integer> getRefSet() {
return refSet;
}
public int getNumValues() {
return numValues;
}
public void setNumValues(int numValues) {
this.numValues = numValues;
}
}