/home/wpollock1/public_html/AJava/CollectionsDemo.java

// Demo of ArrayList and Map, showing how to create them, add objects,
// search for objects, remove objects, and iterate over them.
//
// Collections hold objects; you must "wrap" primitive types to add
// them.  This is easier since Java 5, which automatically converts
// primitives to their wrapper class and back, as needed ("autoboxing").
// Another Java 5 feature is "generics", which allows you to create a
// collection of elements of a specific type.  If you do this, you can
// avoid using "cast" operators.
//
// Collections have a "capacity", which is the amount of memory
// reserved for it.  Adding new elements to a collection is very
// efficient if the current size is less than the current capacity.
// Otherwise the collection must be grown.
//
// Collections can be converted to arrays and vice-versa.  Using the
// utility methods in java.util.Collections an ArrayList can be
// easily searched, sorted, reversed, etc.  (Note shown here.)
//
// Written 3/2005 by Wayne Pollock, Tampa Florida USA.
// Updated 2015, 2017

import java.util.*;

class CollectionsDemo
{
    public static void main ( String [] args )
    {
        List<String> names = new ArrayList<>();

        names.add( new String( "Jane" ) );
        names.add( new String( "Anna" ) );
        names.add( new String( "Hiro" ) );
        names.add( new String( "Kim" ) );
        names.add( new String( "Sam" ) );
        names.add( new String( "Wayne" ) );

        // Quick and dirty way to print a collection:
        System.out.println( "Initial contents: " + names );
        // For collections of collections print them this way:
        //   Arrays.deepToString( names.toArray() ) );

        if ( names.contains("Sam") )  // Note, "contains" uses "equal".
        {
            int i = names.indexOf( "Sam" );  // returns -1 if not found
            String s = names.get( i );
            System.out.println( "\nIndex of \"" + s + "\" is "
                    + i + "." );

            System.out.println( "Removing \"Sam\"." );
            names.remove( i );  // names.remove( "Sam" ) works too.
            System.out.println( "Num of remaining names: "
                    + names.size() );
        }

        System.out.println( "Sorting names.\n" );
        Collections.sort( names );

        System.out.println( "The remaining names are:\n" );
        for ( String name : names )
            System.out.println( name );

        // Using an Iterator: needed when altering collection:
        Iterator<String> it = names.iterator();
        while ( it.hasNext() )
        {
            String name = it.next();
            if ( name.endsWith( "e" ) )
            {  System.out.println( "Removing \"" + name + "\"" );
               it.remove();
            }
        }

        System.out.println( "\nThe remaining names are:\n" );
        for ( String name : names )
            System.out.println( name );

        names.clear();  // removes all elements

        // Demo of creating and using a Map:
        Map<String, Integer> m = new HashMap<>();
        m.put( "January", 31 );       m.put( "February", 28 );
        m.put( "March", 31 );         m.put( "April", 30 );
        m.put( "May", 31 );           m.put( "June", 30 );
        m.put( "July", 31 );          m.put( "August", 31 );
        m.put( "September", 30 );     m.put( "October", 31 );
        m.put( "November", 30 );      m.put( "December", 31 );

        int days = m.get( "July" );

        System.out.println( "\nDays in July: " + days );

        // Since Java 8, there must be a dozen ways to iterate over a
        // collection.  I show four of them here.  Generally speaking,
        // the forEach way is most efficient.  Note these methods work
        // for any type of collection; Maps are actually the most difficult.

        // Since Maps don't preserve key order, sort the keys first:
        System.out.println( "\nMap (sorted keys):" );
        List<String> keys = new ArrayList<>( m.keySet() );
        Collections.sort( keys );
        // Dumping the sorted Map using a for-each loop:
        for ( String key : keys ) {
            System.out.println( key + " has " + m.get(key) + " days." );
        }

        // Dumping the unsorted Map again, this time using an iterator):
        System.out.println( "\nMap (unsorted keys) via iterator:" );
        Iterator<String> iter = m.keySet().iterator();
        while ( iter.hasNext() ) {
            String key = iter.next();
            System.out.println( key + " has " + m.get(key) + " days." );
        }

        // Dumping the unsorted Map again, this time using forEach):
        System.out.println( "\nMap (unsorted keys) via forEach:" );
        m.forEach ( (k,v) -> System.out.println( k + " has " + v + " days." ) );

        // Dumping the unsorted Map again, this time using a stream):
        System.out.println( "\nMap (unsorted keys) via a stream:" );
        m.entrySet().stream().forEach(e ->
            System.out.println( e.getKey() + " has " + e.getValue() + " days." )
        );

        // This runs:
        Integer numDays = m.get( "Pollockuary" );
        System.out.println( "\nDays in Pollockuary: " + numDays );

        // This would fail with a NullPointerException:
        // int days = m.get( "Pollockuary" );
    }
}