All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.continual.util.collections.MultiMap Maven / Gradle / Ivy

There is a newer version: 0.3.14
Show newest version
/*
 *	Copyright 2019, Continual.io
 *
 *	Licensed 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 io.continual.util.collections;

import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Maps a key to a list (not just a set) of values. The classes used for
 * K and V are not required to be immutable, but if they're not, clone()
 * could create a map that's not completely independent in terms of the
 * values stored.
 *
 * @param  a key type for the map
 * @param  a value type for the map
 */
public class MultiMap
{
	public MultiMap ()
	{
		fMultiMap = new Hashtable> ();
	}

	public MultiMap ( Map data )
	{
		this ();

		for ( Map.Entry e : data.entrySet () )
		{
			put ( e.getKey (), e.getValue () );
		}
	}

	@Override
	public MultiMap clone ()
	{
		final MultiMap newMap = new MultiMap<> ();
		for ( Entry> e : fMultiMap.entrySet () )
		{
			final K key = e.getKey ();

			// get(key) returns a new list
			newMap.put ( key, get ( key ) );
		}
		return newMap;
	}

	@Override
	public String toString ()
	{
		return fMultiMap.toString ();
	}

	public synchronized void put ( K k )
	{
		getOrCreateFor ( k );
	}

	public synchronized void put ( K k, V v )
	{
		LinkedList list = new LinkedList();
		list.add ( v );
		put ( k, list );
	}

	public synchronized void put ( K k, Collection v )
	{
		List itemList = getOrCreateFor ( k );
		itemList.removeAll ( v );	// only one of a given value allowed
		itemList.addAll ( v );
	}

	public synchronized void putAll ( Map> values )
	{
		for ( Map.Entry> e : values.entrySet () )
		{
			put ( e.getKey (), e.getValue () );
		}
	}
	
	public synchronized boolean containsKey ( K k )
	{
		return fMultiMap.containsKey ( k );
	}

	/**
	 * Get the values for a given key. A list is always returned, but it may be empty.
	 * @param k a key
	 * @return a list of values which may be empty
	 */
	public synchronized List get ( K k )
	{
		List itemList = new LinkedList ();
		if ( fMultiMap.containsKey ( k ) )
		{
			itemList = getOrCreateFor ( k );
		}
		return new LinkedList ( itemList );
	}

	/**
	 * Get the first value for the given key, or return null if none exists.
	 * @param k a key
	 * @return a value or null
	 */
	public V getFirst ( K k )
	{
		final List items = get ( k );
		if ( items.size () > 0 )
		{
			return items.get ( 0 );
		}
		return null;
	}

	public synchronized Collection getKeys ()
	{
		return fMultiMap.keySet ();
	}

	public synchronized Map> getValues ()
	{
		return fMultiMap;
	}

	public synchronized Map> getCopyAsSimpleMap ()
	{
		final HashMap> result = new HashMap> ();
		for ( Entry> e : fMultiMap.entrySet () )
		{
			final LinkedList list = new LinkedList ();
			list.addAll ( e.getValue () );
			result.put ( e.getKey(), list );
		}
		return result;
	}

	public synchronized List remove ( K k )
	{
		return fMultiMap.remove ( k );
	}

	public synchronized void remove ( K k, V v )
	{
		List itemList = getOrCreateFor ( k );
		itemList.remove ( v );
	}

	public synchronized void clear ()
	{
		fMultiMap.clear ();
	}

	public synchronized int size ()
	{
		return fMultiMap.size ();
	}

	public synchronized int size ( K k )
	{
		return getOrCreateFor ( k ).size ();
	}

	private final Hashtable> fMultiMap;

	private synchronized List getOrCreateFor ( K k )
	{
		List itemList = fMultiMap.get ( k );
		if ( itemList == null )
		{
			itemList = new LinkedList ();
			fMultiMap.put ( k, itemList );
		}
		return itemList;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy