<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.kram.nz/index.php?action=history&amp;feed=atom&amp;title=SE251%3Ajhor053sMultiMap</id>
	<title>SE251:jhor053sMultiMap - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.kram.nz/index.php?action=history&amp;feed=atom&amp;title=SE251%3Ajhor053sMultiMap"/>
	<link rel="alternate" type="text/html" href="https://wiki.kram.nz/index.php?title=SE251:jhor053sMultiMap&amp;action=history"/>
	<updated>2026-04-24T19:50:30Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://wiki.kram.nz/index.php?title=SE251:jhor053sMultiMap&amp;diff=9773&amp;oldid=prev</id>
		<title>Mark: 3 revision(s)</title>
		<link rel="alternate" type="text/html" href="https://wiki.kram.nz/index.php?title=SE251:jhor053sMultiMap&amp;diff=9773&amp;oldid=prev"/>
		<updated>2008-11-03T05:21:04Z</updated>

		<summary type="html">&lt;p&gt;3 revision(s)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Here is my multi map as per showcased in the [[SE251:Session5 | 251 Group Session 5]]&lt;br /&gt;
&lt;br /&gt;
Any q&amp;#039;s or comments let me know on my talk page or here [[User:Jhor053|Jhor053]] 22:13, 11 May 2008 (NZST)&lt;br /&gt;
&lt;br /&gt;
If you use this for something Include Hong Yul Yang and I please and feel free to modify it and post it up on another wiki page and post your link also on here!&lt;br /&gt;
&amp;lt;pre&amp;gt;//package movies.core;&lt;br /&gt;
&lt;br /&gt;
import java.util.Iterator;&lt;br /&gt;
import java.util.Map;&lt;br /&gt;
import java.util.Set;&lt;br /&gt;
import java.util.TreeMap;&lt;br /&gt;
import java.util.TreeSet;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * A multi-map stores mapping from a key (type K) to a set of elements (type V)&lt;br /&gt;
 * A many to many&lt;br /&gt;
 * &lt;br /&gt;
 * @origAuthor Hong Yul Yang (based of his Skeleton code from 251 wiki)&lt;br /&gt;
 * @author jhor053&lt;br /&gt;
 * */&lt;br /&gt;
public class MultiMap&amp;lt;K,V&amp;gt; {&lt;br /&gt;
    //private Map&amp;lt;K,Set&amp;lt;V&amp;gt;&amp;gt; backingMap;&lt;br /&gt;
    private Map&amp;lt;K, Set&amp;lt;V&amp;gt;&amp;gt; backingMap;&lt;br /&gt;
    private Map&amp;lt;V, Set&amp;lt;K&amp;gt;&amp;gt; reverseMap;&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Constructs an empty MultiMap&lt;br /&gt;
     */&lt;br /&gt;
    public MultiMap() {&lt;br /&gt;
    	backingMap = new TreeMap&amp;lt;K, Set&amp;lt;V&amp;gt;&amp;gt; ();&lt;br /&gt;
    	reverseMap = new TreeMap&amp;lt;V, Set&amp;lt;K&amp;gt;&amp;gt; ();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Returns the set of all keys that have at least one associated value&lt;br /&gt;
     * in this multimap.&lt;br /&gt;
     * @return a set containing all keys&lt;br /&gt;
     */&lt;br /&gt;
    public Set&amp;lt;K&amp;gt; keySet() {&lt;br /&gt;
    	return backingMap.keySet();        &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Returns the set of all values that have at least one associated key&lt;br /&gt;
     * in this multimap&lt;br /&gt;
     * @return a set containing all values&lt;br /&gt;
     */&lt;br /&gt;
    public Set&amp;lt;V&amp;gt; valueSet() {&lt;br /&gt;
    	&lt;br /&gt;
    	//Uses the reverse map to get a quick set of the values&lt;br /&gt;
		return reverseMap.keySet();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Adds the specified value to the set associated with the specified key.&lt;br /&gt;
     * Note, if the key doesn&amp;#039;t have an associated set, you would have to create&lt;br /&gt;
     * and associate it first before adding the value to it.&lt;br /&gt;
     * @param key &lt;br /&gt;
     * @param value &lt;br /&gt;
     * @return true if the set associated with the key didn&amp;#039;t contain value previously;&lt;br /&gt;
     * false if it did (i.e. nothing was added)&lt;br /&gt;
     */&lt;br /&gt;
    public boolean add(K key, V value) {&lt;br /&gt;
    	&lt;br /&gt;
    	//Safety to get rid of false alignments&lt;br /&gt;
    	if(key == null || value == null)&lt;br /&gt;
    		return false;&lt;br /&gt;
    	&lt;br /&gt;
    	//Checks too see if it is already assigned&lt;br /&gt;
    	if(containsValueAssignedToKey(key, value))&lt;br /&gt;
    		return false;&lt;br /&gt;
    	&lt;br /&gt;
    	//Initialising variable names for the sets&lt;br /&gt;
    	Set &amp;lt;V&amp;gt; vSet;&lt;br /&gt;
    	Set &amp;lt;K&amp;gt; kSet;&lt;br /&gt;
    	&lt;br /&gt;
    	//Seeing if the reference is non existant&lt;br /&gt;
    	//I.e. either the key is present&lt;br /&gt;
    	if (backingMap.get(key) != null){&lt;br /&gt;
    		vSet = backingMap.get(key);&lt;br /&gt;
    	}else{ //I.e. key has nothing assigned or non existant key&lt;br /&gt;
    		vSet = new TreeSet&amp;lt;V&amp;gt; ();&lt;br /&gt;
    	}&lt;br /&gt;
    	&lt;br /&gt;
    	//Add the value to the set to be assigned&lt;br /&gt;
    	vSet.add(value);    	&lt;br /&gt;
    	&lt;br /&gt;
    	//Seeing if the reference is non existant&lt;br /&gt;
    	//I.e. either the value is present&lt;br /&gt;
    	if(reverseMap.get(value) != null){&lt;br /&gt;
    		kSet = reverseMap.get(value);&lt;br /&gt;
    	}else{ //I.e. value has nothing assigned or non existant value&lt;br /&gt;
    		kSet = new TreeSet&amp;lt;K&amp;gt; ();&lt;br /&gt;
    	}&lt;br /&gt;
    	&lt;br /&gt;
    	//Add the key to the set to be assigned&lt;br /&gt;
    	kSet.add(key);&lt;br /&gt;
    	&lt;br /&gt;
    	//Saving references&lt;br /&gt;
    	backingMap.put(key, vSet);&lt;br /&gt;
    	reverseMap.put(value, kSet);&lt;br /&gt;
    	&lt;br /&gt;
    	return true;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Removes the specified value from the set associated with the specified key.&lt;br /&gt;
     * If the set becomes empty as a result, then also removes its association to the key&lt;br /&gt;
     * altogether. Thus, the set returned from subsequent calls to keySet() would not&lt;br /&gt;
     * contain this key anymore.&lt;br /&gt;
     * Note, if the set associated with the key doesn&amp;#039;t contain the value, nothing&lt;br /&gt;
     * is done. &lt;br /&gt;
     * @param key&lt;br /&gt;
     * @param value&lt;br /&gt;
     * @return true if the value successfully was removed; false if the set associated&lt;br /&gt;
     * with the key didn&amp;#039;t contain value&lt;br /&gt;
     */&lt;br /&gt;
    public boolean remove(K key, V value) {&lt;br /&gt;
    	&lt;br /&gt;
    	if(containsValueAssignedToKey(key, value)){&lt;br /&gt;
    		&lt;br /&gt;
    		//initialise Sets&lt;br /&gt;
    		Set &amp;lt;V&amp;gt; vSet = backingMap.get(key);&lt;br /&gt;
    		Set &amp;lt;K&amp;gt; kSet;&lt;br /&gt;
    		//boolean removeKey = false;&lt;br /&gt;
    		&lt;br /&gt;
    		//Remove the value from the normal map&lt;br /&gt;
    		if(vSet.remove(value)){&lt;br /&gt;
    			&lt;br /&gt;
    			//IE no more occurrences of the key &lt;br /&gt;
    			if(vSet.isEmpty()){&lt;br /&gt;
    				//removing key as nothing assigned to it&lt;br /&gt;
    				backingMap.remove(key);&lt;br /&gt;
    				//removeKey = true;&lt;br /&gt;
    			}else{//Still have references for the key&lt;br /&gt;
    				backingMap.put(key, vSet);&lt;br /&gt;
    			}   			&lt;br /&gt;
    			&lt;br /&gt;
    			//Get all references&lt;br /&gt;
    			kSet = reverseMap.get(value);&lt;br /&gt;
    			&lt;br /&gt;
    			//Ie occurrences of the value&lt;br /&gt;
    			if(kSet != null){&lt;br /&gt;
    				kSet.remove(key);&lt;br /&gt;
    				&lt;br /&gt;
    				//update refferences on the reverse map&lt;br /&gt;
					if(kSet.isEmpty()){&lt;br /&gt;
						reverseMap.remove(value);&lt;br /&gt;
					}else{&lt;br /&gt;
						reverseMap.put(value, kSet);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
    			&lt;br /&gt;
    			return true;&lt;br /&gt;
    		}&lt;br /&gt;
    	}&lt;br /&gt;
    	&lt;br /&gt;
    	&lt;br /&gt;
    	return false;   		&lt;br /&gt;
        &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Removes the specified key from the set associated with the specified value.&lt;br /&gt;
     * If the set becomes empty as a result, then also removes its association to the key&lt;br /&gt;
     * altogether. Thus, the set returned from subsequent calls to keySet() would not&lt;br /&gt;
     * contain this key anymore.&lt;br /&gt;
     * Note, if the set associated with the key doesn&amp;#039;t contain the value, nothing&lt;br /&gt;
     * is done. &lt;br /&gt;
&lt;br /&gt;
     * @param value&lt;br /&gt;
     * @return true if the value successfully was removed; false if the set associated&lt;br /&gt;
     * with the key didn&amp;#039;t contain value&lt;br /&gt;
     */&lt;br /&gt;
    public boolean removeKey(K key) {&lt;br /&gt;
    	if(backingMap.containsKey(key)){&lt;br /&gt;
    		Set&amp;lt;V&amp;gt; tempSet = backingMap.remove(key);&lt;br /&gt;
    		&lt;br /&gt;
    		   		&lt;br /&gt;
    		for (Iterator&amp;lt;V&amp;gt; iterator = tempSet.iterator(); iterator.hasNext();) {&lt;br /&gt;
				V v = iterator.next();&lt;br /&gt;
				&lt;br /&gt;
				Set&amp;lt;K&amp;gt; tempSet2 = reverseMap.get(v);&lt;br /&gt;
				&lt;br /&gt;
				if(tempSet2 != null){&lt;br /&gt;
					tempSet2.remove(key);&lt;br /&gt;
					&lt;br /&gt;
					if(tempSet2.isEmpty()){&lt;br /&gt;
						reverseMap.remove(v);&lt;br /&gt;
					}else{&lt;br /&gt;
						reverseMap.put(v, tempSet2);&lt;br /&gt;
					}&lt;br /&gt;
					&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
			}&lt;br /&gt;
    		return true;&lt;br /&gt;
    	}&lt;br /&gt;
    	&lt;br /&gt;
    	return false;   		&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Removes the specified value from the set associated with the specified key.&lt;br /&gt;
     * If the set becomes empty as a result, then also removes its association to the key&lt;br /&gt;
     * altogether. Thus, the set returned from subsequent calls to keySet() would not&lt;br /&gt;
     * contain this key anymore.&lt;br /&gt;
     * Note, if the set associated with the key doesn&amp;#039;t contain the value, nothing&lt;br /&gt;
     * is done. &lt;br /&gt;
&lt;br /&gt;
     * @param value&lt;br /&gt;
     * @return true if the value successfully was removed; false if the set associated&lt;br /&gt;
     * with the key didn&amp;#039;t contain value&lt;br /&gt;
     */&lt;br /&gt;
    public boolean removeValue(V value) {&lt;br /&gt;
    	if(reverseMap.containsKey(value)){&lt;br /&gt;
    		Set&amp;lt;K&amp;gt; tempSet = reverseMap.remove(value);&lt;br /&gt;
    		&lt;br /&gt;
    		   		&lt;br /&gt;
    		for (Iterator&amp;lt;K&amp;gt; iterator = tempSet.iterator(); iterator.hasNext();) {&lt;br /&gt;
				K k = iterator.next();&lt;br /&gt;
				&lt;br /&gt;
				Set&amp;lt;V&amp;gt; tempSet2 = backingMap.get(k);&lt;br /&gt;
				&lt;br /&gt;
				if(tempSet2 != null){&lt;br /&gt;
					tempSet2.remove(value);&lt;br /&gt;
					&lt;br /&gt;
					if(tempSet2.isEmpty()){&lt;br /&gt;
						backingMap.remove(k);&lt;br /&gt;
					}else{&lt;br /&gt;
						backingMap.put(k, tempSet2);&lt;br /&gt;
					}&lt;br /&gt;
					&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
			}&lt;br /&gt;
    		return true;&lt;br /&gt;
    	}&lt;br /&gt;
    	&lt;br /&gt;
    	return false;   		&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Returns the set associated with the given key. Returns an empty&lt;br /&gt;
     * set if the key has no associations.&lt;br /&gt;
     * &lt;br /&gt;
     * @param key&lt;br /&gt;
     * @return the set associated with the given key&lt;br /&gt;
     */&lt;br /&gt;
    public Set&amp;lt;V&amp;gt; get(K key) {&lt;br /&gt;
        Set &amp;lt;V&amp;gt; returnSet = new TreeSet&amp;lt;V&amp;gt;();&lt;br /&gt;
        if(backingMap.get(key) == null)&lt;br /&gt;
        	return returnSet;&lt;br /&gt;
        returnSet = backingMap.get(key);&lt;br /&gt;
        return returnSet;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Returns the set associated with the given value. Returns an empty&lt;br /&gt;
     * set if the value has no associations.&lt;br /&gt;
     * &lt;br /&gt;
     * @param key&lt;br /&gt;
     * @return the set associated with the given key&lt;br /&gt;
     */&lt;br /&gt;
    public Set&amp;lt;K&amp;gt; getKeySetFromValue(V value) {&lt;br /&gt;
        Set &amp;lt;K&amp;gt; returnSet = new TreeSet&amp;lt;K&amp;gt;();&lt;br /&gt;
        if(reverseMap.get(value) == null)&lt;br /&gt;
        	return returnSet;&lt;br /&gt;
        returnSet = reverseMap.get(value);&lt;br /&gt;
        return returnSet;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Returns a string representation of this multimap in the form of e.g.&lt;br /&gt;
     * [key1=[val1, val2], key2=[val1, val3, val4], key3=[val3]].&lt;br /&gt;
     * &lt;br /&gt;
     * @return the string representation of this multimap&lt;br /&gt;
     */&lt;br /&gt;
    public String toString() {&lt;br /&gt;
        return backingMap.toString();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Checks to see if a specified value is assigned to a key&lt;br /&gt;
     * &lt;br /&gt;
     * @param key&lt;br /&gt;
     * @param value&lt;br /&gt;
     * @return true if the value is assigned to that key&lt;br /&gt;
     */&lt;br /&gt;
    public boolean containsValueAssignedToKey (K key, V value){&lt;br /&gt;
    	&lt;br /&gt;
    	if( backingMap.containsKey(key) ){&lt;br /&gt;
    		&lt;br /&gt;
    		//Get the Set&amp;lt;V&amp;gt; as per specified by the key&lt;br /&gt;
    		Set&amp;lt;V&amp;gt; testSet = backingMap.get(key);&lt;br /&gt;
    		&lt;br /&gt;
    		//See if testSet Contains the specified value&lt;br /&gt;
    		if(testSet.contains(value))&lt;br /&gt;
    			return true;&lt;br /&gt;
    	}&lt;br /&gt;
    	&lt;br /&gt;
    	return false;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Checks to see if a specified key is assigned to a Value&lt;br /&gt;
     * &lt;br /&gt;
     * @param value&lt;br /&gt;
     * @param key&lt;br /&gt;
     * @return true if the key is assigned to that value&lt;br /&gt;
     */&lt;br /&gt;
    public boolean containsKeyAssignedToValue (V value, K key){&lt;br /&gt;
    	&lt;br /&gt;
    	if( reverseMap.containsKey(value) ){&lt;br /&gt;
    		&lt;br /&gt;
    		//Get the Set&amp;lt;V&amp;gt; as per specified by the key&lt;br /&gt;
    		Set&amp;lt;K&amp;gt; testSet = reverseMap.get(value);&lt;br /&gt;
    		&lt;br /&gt;
    		//See if testSet Contains the specified value&lt;br /&gt;
    		if(testSet.contains(key))&lt;br /&gt;
    			return true;&lt;br /&gt;
    	}&lt;br /&gt;
    	&lt;br /&gt;
    	return false;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Implements containKey() from Map&lt;br /&gt;
     * &lt;br /&gt;
     * @param key&lt;br /&gt;
     * @return True if it contains specified key &lt;br /&gt;
     */&lt;br /&gt;
    public boolean containsKey(K key){&lt;br /&gt;
    	return backingMap.containsKey(key);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     * Implements containValue() from Map&lt;br /&gt;
     * &lt;br /&gt;
     * @param key&lt;br /&gt;
     * @return True if it contains specified Value &lt;br /&gt;
     */&lt;br /&gt;
    public boolean containsValue(V value){&lt;br /&gt;
    	return reverseMap.containsKey(value);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mark</name></author>
	</entry>
</feed>