Home | FAQ | Contact me

Java Maps

This is a collection of cool things to do with maps as they are encountered and I get excited enough to write them down. (I'm getting long enough in the Java tooth that I don't always recognize when I should note something for general interest.)

How to initialize a static Map in Java

Here's a neat trick that works real well. It's just complicated enough that it might not occur to you. This is Java 5+ stuff, of course.

import java.util.Map;
import java.util.HashMap;
import java.util.Collections;

public class Ratings
{
	// ratings...
	public static final int	NR    = 0;	// not rated
	public static final int	G     = 1;	// general admission
	public static final int	PG    = 2;	// parental guidance suggested
	public static final int	PG_13 = 3;	// parent guidance strongly suggested/not under 13
	public static final int	R     = 5;	// restricted to mature audiences

	public static final Map< Integer, String >	RATINGS;

	static
	{
		Map< Integer, String > map = new HashMap<>();
		map.put( NR,    "NR" );
		map.put( G,     "G" );
		map.put( PG,    "PG" );
		map.put( PG_13, "PG_13" );
		map.put( R,     "R" );
		RATINGS = Collections.unmodifiableMap(  map );
	}
}

Afterward, it's easy to write code to convert from the integer (say, from a database column) to string and vice-versa. It's also possible to use the integer variables as "manifest constants."

...or...

import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

private static final Map< String, Integer > permissions = new HashMap< String, Integer >()
{
    {
        put( "password", new Integer( 0 ) );
        put( "read",     new Integer( 1 ) );
        put( "append",   new Integer( 2 ) );
        put( "write",    new Integer( 3 ) );
    }
};

private final boolean isSufficient( String horseShoeString, String stakeString )
{
    int stake     = permissions.get( stakeString );
    int horseshoe = permissions.get( horseShoeString );

    if( horseshoe == 0 && stake == 0 )       // password is only password, not read or write
        return true;

    // from here on, it's sort of telescopic...
    return( horseshoe >= stake );
}

Traversing the map

Traversing a map is a bit challenging. Here are two methods.

import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

private static final Map< String, String > permissionTuples = new HashMap< String, String >()
{
    {
        "Jack",  "write",
        "Jill",  "append",
        "Jack",  "password",
        "Jill",  "read",
        "Jimmy", "write",
    }
};

String name = "Jack";

/* method 1: since Java 5 */
for( Map.Entry< String, String > map : permissions.entrySet() )
{
    if( !map.getKey().equals( name ) )
        continue;

    if( isSufficient( permission, map.getValue() ) )
        ;
}

/* method 2: the older way */
Iterator< Map.Entry< String, String > > it = permissions.entrySet().iterator();

while( it.hasNext() )
{
    Map.Entry< String, String > tuple = ( Map.Entry< String, String > ) it.next();

    if( !tuple.getKey().equals( name ) )
        continue;

    if( isSufficient( permission, tuple.getValue() ) )
        ;
}

Best-of statement of possible ways to traverse the map

How to traverse a Map four different ways in Java. It's true that all these ways are more or less the same one or two ways, but it's a great illustration I picked up somewhere.

Create this map

...and imports used in these examples.

import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

HashMap< String, String > loans = new HashMap<>();
loans.put( "home loan", "citibank" );
loans.put( "personal loan", "Wells Fargo" );

Using keySet() and for loop

That is, the for-each style loop from Java 5...

for( String key : loans.keySet() )
   System.out.println( "key: " + key + " value: " + loans.get( key ) );

Output

key: home loan value: citibank
key: personal loan value: Wells Fargo

Using keySet(), Iterator and while

Set< String >      keySet         = loans.keySet();
Iterator< String > keySetIterator = keySet.iterator();

while( keySetIterator.hasNext() )
{
   String key = keySetIterator.next();
   System.out.println( "key: " + key + " value: " + loans.get( key ) );
}

Output

key: home loan value: citibank
key: personal loan value: Wells Fargo

Using Set, entrySet() and for loop

Set< Map.Entry< String, String > > entrySet = loans.entrySet();

for( Entry entry : entrySet )
   System.out.println( "key: " + entry.getKey() + " value: " + entry.getValue() );

Output

key: home loan value: citibank
key: personal loan value: Wells Fargo

Using Set, entrySet(), Iterator and while

Set< Map.Entry< String, String > >  entrySet1        = loans.entrySet();
Iterator< Entry< String, String > > entrySetIterator = entrySet1.iterator();

while( entrySetIterator.hasNext() )
{
   Entry entry = entrySetIterator.next();
   System.out.println( "key: " + entry.getKey() + " value: " + entry.getValue() );
}

Output

key: home loan value: citibank
key: personal loan value: Wells Fargo

Another example...

 /**
   * Given a symbol table, and the list of keys (sorted or not) in
   * the symbol table, print the keys, one per line, padded to be
   * right-aligned with a colon, and their values.
   *
   * Example
   *
   *                 content: 6
   *          targetSiteCode: 6
   *              consumable: 6
   * manufacturedLabeledDrug: 6
   *            originalText: 7
   *             translation: 7
   *     ExternalObservation: 8
   *                    list: 9
   *                    name: 11
   *       entryRelationship: 12
   *                      tr: 12
   *                      th: 14
   *                 section: 15
   *               reference: 15
   *                   title: 16
   *               component: 16
   *                      td: 18
   *                    text: 23
   *
   * @param table the symbol tables.
   * @param keys the set or a subset of keys in the symbol table.
   * @param padding width of the column in which to print the right-aligned keys.
   */
  public static void sortAndPrintPaddedByValue( SymbolTable table, List< String > keys, int padding )
  {
    Map< String, Integer > sortedMap = sortMapByValue( table.map() );

    for( Map.Entry< String, Integer > map : sortedMap.entrySet() )
    {
      Integer value  = map.getValue();
      String  key    = map.getKey();
      String  output = "";

      for( int pad = 0; pad < ( padding - key.length() ); pad++ )
        output = output + " ";

      System.out.println( output + key + ": " + value );
    }
  }

  private static < K, V extends Comparable< ? super V > > Map< K, V > sortMapByValue( Map< K, V > map )
  {
    List< Map.Entry< K, V > > list = new LinkedList<>( map.entrySet() );
    Collections.sort( list, new Comparator< Map.Entry< K, V > >()
      {
        @Override
        public int compare( Entry< K, V > o1, Entry< K, V > o2 )
        {
          return ( o1.getValue() ).compareTo( ( V ) o2.getValue() );
        }
      }
    );

    Map< K, V > result = new LinkedHashMap<>();

    for( Map.Entry< K, V > entry : list )
      result.put( entry.getKey(), entry.getValue() );

    return result;
  }