/*
 * [TestHashMapAutoBoxing.java]
 *
 * Summary: example use of java.util.HashMap autoboxing. Sample code to TEST HashMap with automatic boxing.
 *
 * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.8+
 *
 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
 *
 * Version History:
 *  1.0 2009-01-01 initial version
 */
package com.mindprod.example;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import static java.lang.System.*;

/**
 * example use of java.util.HashMap autoboxing. Sample code to TEST HashMap with automatic boxing.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0 2009-01-01 initial version
 * @since 2009-01-01
 */
@SuppressWarnings( { "UnusedAssignment" } )
public final class TestHashMapAutoBoxing
    {
    /**
     * Sample code to TEST HashMap with automatic boxing. requires JDK 1.5+
     *
     * @param args not used
     */
    @SuppressWarnings( "unchecked" )
    public static void main( String[] args )
        {
        // create a new HashMap
        final Map<String, Integer> h = new HashMap<>( 149 /* capacity */, 0.75f /* loadfactor */ );
        {
        // add some key/value pairs about English measure to the HashMap
        h.put( "inch", 1 );
        h.put( "foot", 12 );
        h.put( "yard", 36 );
        h.put( "mile", 3760 * 36 );
        }
        // look up a key in the HashMap
        int inches = h.get( "foot" );
        // prints "12"
        out.println( inches );
        out.println( "enumerate all the keys in the HashMap" );
        // officially a Set<K> but actually a java.util.HashMap$KeySet, Does contains with the HashMap hash.
        out.println( h.keySet().getClass() );
        for ( String key : h.keySet() )
            {
            int value = h.get( key );
            // prints lines of the form foot 12
            // in effectively random order
            out.println( key + " " + value );
            }
        out.println( "enumerate all the values in the HashMap" );
        // officially a Collection<V> but actually a java.util.HashMap$Values, Does contains by linear search.
        out.println( h.values().getClass() );
        for ( int value : h.values() )
            {
            // prints lines of the form "12"
            // in effectively random order.
            out.println( value );
            }
        out.println( "enumerate all the key/value Entries in the HashMap" );
        for ( Map.Entry<String, Integer> entry : h.entrySet() )
            {
            // prints lines of the form foot=12
            // in effectively random order.
            out.println( "as Entry: " + entry );
            // this does not require an expensive get lookup to find the value.
            String key = entry.getKey();
            int value = entry.getValue();
            out.println( "separately: " + key + " " + value );
            }
        //
        // extract just the keys into an array
        Set<String> justKeys = h.keySet();
        // Use toArray that takes an empty array,
        // otherwise we went up with a useless Object[] instead of a String[].
        String[] keys = justKeys.toArray( new String[ justKeys.size() ] );
        //
        // extract just the values into an array, may contain duplicates unlike a Set.
        Collection<Integer> justValues = h.values();
        Integer[] values = justValues.toArray( new Integer[ justValues.size() ] );
        //
        // extract key/value pair entries into an array
        Set<Map.Entry<String, Integer>> justEntries = h.entrySet();
        // Infuriatingly, this generates an unchecked conversion warning message.
        Map.Entry<String, Integer>[] keyValuePairs = justEntries.toArray( new Map.Entry[ justEntries.size() ] );
        // Type erasure won't let us say:
        // Map.Entry<String, Integer>[] keyValuePairs =
        // justEntries.toArray ( new
        //  Map.Entry<String,Integer>[justEntries.size()] );
        //
        // L A M B D A   S T Y L E
        out.println( "enumerate all the key/value Entries in the HashMap using Java 1.8 lambda dual foreach" );
        h.forEach( ( unit, measure ) ->
        {
        out.println( unit + " -> " + measure );
        // this effectively creates an anonymous class with an anonymous method that prints two values.
        // h.forEach traverses the hasMap and calls that method for each key/value pair.
        // Javac automatically infers the types from the declaration for h.
        } );
        // quite a bit terser, eh?
        } // end main
    }