JMU JMU - Department of Computer Science
Help Tools
Lab: Experimenting with Type-Safe Collections


Instructions: Answer the following questions one at a time. After answering each question, check your answer (by clicking on the check-mark icon if it is available) before proceeding to the next question.

Getting Ready: Before going any further, you should:

  1. Depending on your development environment, create either a directory or a project for this lab.
  2. Setup your development environment.
  3. Download the following files:
    to an appropriate directory/folder. (In most browsers/OSs, the easiest way to do this is by right-clicking/control-clicking on each of the links above and then selecting Save as... or Save link as....)
  4. and add them to your project/directory. Remember to put the data files in the appropriate place (e.g., in the project directory in Eclipse). Also, remember that in some IDEs it is easier to add a .jar file to a project rather than a .class file. robotsimulator.jar contains both Direction.class and Robot.class.

1. A Review: This part of the lab will help you recall/remember some important concepts about arrays (especially arrays of objects).
  1. Open ArrayColorFinder.java.
  2. What "kind of thing" is colors?


    Conceptually, it is an array of Color objects. In fact, it is really an array of references to Color objects.
    Expand
  3. What "kind of thing" is colors[0]?


    Conceptually, it is a Color object. In fact, it is a reference to a Color object.
    Expand
  4. What "kind of thing" is names?


    Conceptually, it is an array of String objects. In fact, it is really an array of references to String objects.
    Expand
  5. What statement allocates memory for colors?


           colors = new Color[147];
        
    Expand
  6. After this statement has been executed, how many actual Color objects have been instantiated?


    None. Space has been allocated for 147 references.
    Expand
  7. What statement instantiates the Color objects?


           value = new Color(red, green, blue);
        
    Expand
  8. What statement assigns Color objects to elements of the array colors?


           colors[i] = value;
        
    Expand
  9. What word is commonly used to describe two arrays like names and colors?


    They are often said to be conformal (that is, they have common indexes).
    Expand
  10. Open, compile and execute the Driver. What output is generated when you enter "snow"?


    snow: java.awt.Color[r=255,g=250,b=250]
        
    Expand
  11. What output is generated when you enter "apricotice"? Why?


    No output is generated since there is no such color. (Actually, I used to have a car that was "Apricot Ice" but that's a story for another day.)
    Expand
2. Using List Objects: This part of the lab will help you become acquainted with the List interface and the ArrayList class.
  1. Create a class named ListColorFinder and copy the code from ArrayColorFinder into it (changing the name of the constructor appropriately).
  2. Change the declarations of the parameters named colors and names so that they are both List objects. (Do not parameterize them!) What changes did you make?


        private List         colors;
        private List         names;       
        
    Expand
  3. Recall that you must import something in order to use the List class. What line do you have to add to the top of your class as a result?


        import java.util.List;
        
    Expand
  4. Change the instantiation of the colors and names objects so that they are now ArrayList objects. What changes did you make?


           colors = new ArrayList();
           names  = new ArrayList();
        
    Expand
  5. What did you need to import?


        import java.util.ArrayList;
        
    Expand
  6. Why can you declare variables to be List objects but instantiate them as ArrayList objects>?


    Because the ArrayList class implements the List interface. In other words, an ArrayList object "is a" List.
    Expand
  7. What is the major advantage of declaring these variables to be List objects rather than ArrayList objects>?


    The particular implementation can easily be changed, if needed.
    Expand
  8. What is the major advantage of using List objects rather than arrays? (Hint: It should be immediately apparent from the change you just made.)


    They do not have a pre-defined size.
    Expand
  9. Change the statements in the for loop that store the names and colors. (Hint: Look at the documentation for the ArrayList java.util.ArrayList class.) What changes did you make?


    I replaced names[i] with names.set(i, key), and colors[i] with colors.set(i, value).
    Expand
  10. Change the statements in the for in getColor(). (Hint: Look at the documentation for the ArrayList java.util.ArrayList class.) What changes did you make?


    I replaced names.length with names.size(), names[i] with names.get(i), and colors[i] with colors.get(i).
    Expand
  11. Compile the ListColorFinder class. What error messages were generated?


    ColorFinder.java:106: incompatible types
    found   : java.lang.Object
    required: java.lang.String
              key = names.get(i);
                             ^
    ColorFinder.java:109: incompatible types
    found   : java.lang.Object
    required: java.awt.Color
                 result = colors.get(i);
                                    ^
    
    Expand
  12. Fix these errors by typecasting the objects that are returned by the get() method calls. What changes did you make?


              key = (String)names.get(i);          
        

    and

                 result = (Color)colors.get(i);
        
    Expand
  13. Compile the ListColorFinder class. The compiler still generates at least one "Note/Warning" when you compile the class. What "Note/Warning" is generated?


    A warning about using raw types.
        
    Expand
  14. Why is this "Note" generated?


    Because we did not ensure type safety.
    Expand
3. Making a List Type Safe: This part of the lab will help you understand how to use type-safe collections.
  1. Change the declaration of colors so that it is a List of Color objects. What change did you make?
        private List<Color>         colors;       
        
    Expand
  2. Change the declaration of names so that it is a List of String objects. What change did you make?
        private List<String>        names;       
        
    Expand
  3. Change the instantiation of the colors and names objects. What changes did you make?
           colors = new ArrayList<Color>();
           names  = new ArrayList<String>();
        
    Expand
  4. "Fix" the getColor() method so that it no longer casts the objects returned by the calls to get(). What changes did you make?
              key = names.get(i);          
        

    and

                 result = colors.get(i);
        
    Expand
  5. Was it necessary to remove the type cast?
    No. But, there is no reason to cast a String as a String or a Color as a Color.
    Expand
4. Using a Map: This part of the lab will help you understand how to use objects that implement the Map interface and some of the benefits of maps. Since you understand type-safety now, there's no reason to start with a version that isn't type-safe.
  1. Create a class named MapColorFinder and copy the code from ArrayColorFinder into it (changing the name of the constructor appropriately).
  2. Delete the declaration and instantiation of the names object.
  3. Change the declaration of the colors object so that it is now a Map with a key of type String and a value of type Color. (This is often described as a Map from String to Color.) What code did you change?


           Map<String,Color>   colors;
        
    Expand
  4. What class do you need to import?


           java.util.Map
        
    Expand
  5. Instantiate the colors object as a HashMap from String to Color. What code did you add?


           colors = new HashMap<String,Color>();
        
    Expand
  6. What class do you need to import?


           java.util.HashMap
        
    Expand
  7. Replace the assignment statements involving the local variables key and value with a call to the appropriate method in the HashMap class. What change did you make?


           colors.put(key, value);
        
    Expand
  8. Complete the getColor() method in the ColorFinder class so that it now uses the HashMap named colors. (Hint: Look at the documentation for the HashMap java.util.HashMap class.) What code did you add?


        public Color getColor(String description)
        {
            return colors.get(description);
        }
        
    Expand
  9. What is the major advantage of Map objects as compared to List objects. (Hint: It should be immediately apparent from the change you just made.)


    They can use anything as the key/index.
    Expand
5. Passing a Simple Type-Safe Collection: This part of the lab will help you understand how to pass type safe collections as parameters.
  1. Open the Bender and Driver1 classes.
  2. The Robot class includes the following methods:
            protected boolean canMove(Direction d)
    
            protected void move(Direction d)
    
            protected boolean haveBeen(Direction d)
        

    Complete the execute() method in the Bender class using the above methods from the Robot class in such a way that it is consistent with the comments describing it. (Note: You need not use the haveBeen() method.) Do not use an Iterator or a for-each loop.

    What code did you add?

        public void execute(List<Direction> method)
        {
           Direction        d;
           
    
           for (int i=0; i<method.size(); i++)
           {
              d = method.get(i);
    	  move(d);          
           }
        }
        
    Expand
  3. Compile and execute Driver1.
  4. Modify the execute() method so that it uses a for-each loop. What is your execute() method now?
        public void execute(List<Direction> method)
        {
           for (Direction d: method)
           {
               move(d);
           }
        }
        
    Expand
  5. Compile and execute Driver1.
  6. Modify the execute() method so that it uses an Iterator. What is your execute() method now?
        public void execute(List<Direction> method)
        {
           Direction              d;
           Iterator<Direction>    i;
    
           i = method.iterator();
           while (i.hasNext())
           {
               d = i.next();
               move(d);
           }
        }
        
    Expand
  7. Compile and execute Driver1.
6. Creating a Simple Type-Safe Collection: This part of the lab will help you understand how to read a text file and use it to create a simple type-safe collection.
  1. Read and understand the Driver2 class and the data file box.txt.
  2. Add the following method to the Bender class and complete it. (For this question you should assume that there are four directions: Direction.FORWARD, Direction.RIGHT, Direction.BACKWARD, and Direction.LEFT.)
         * Read instructions from a file
         *
         * @param name   The name of the file
         * @return       An ArrayList of Direction objects
         */
        public List<Direction> read(String name)
        {
    
    
        }
        
    What code did you add?
        public List<Direction> read(String name)
        {
           BufferedReader           in;
           File                     file;       
           String                   line;       
           List<Direction>    method;
           
    
           try
           {
              file    = new File(name);
              in      = new BufferedReader(new FileReader(file));
              method  = new ArrayList<Direction>();
              
              while ((line=in.readLine()) != null)
              {
    	     Direction      d;
    
    	     d = Direction.valueOf(line);
    	     if (d != null) method.add(d);
    
                 // This could also be accomplished as follows:
                 //if      (line.equals("FORWARD"))  method.add(Direction.FORWARD);
                 //else if (line.equals("RIGHT"))    method.add(Direction.RIGHT);
                 //else if (line.equals("BACKWARD")) method.add(Direction.BACKWARD);
                 //else if (line.equals("LEFT"))     method.add(Direction.LEFT);
              }
           }
           catch (IOException ioe)
           {
              method = null;
           }
           
           return method;       
        }
        
    Expand
  3. Compile and execute Driver2.
  4. The Direction class actually includes Direction.CONTINUE. Add a line to the read() method that accounts for this Direction. What code did you add?
    For the implementation that uses if statements, I added the following:
                 else if (line.equals("CONTINUE")) method.add(Direction.CONTINUE);
        

    For the implementation that uses valueOf() it isn't necessary to make any changes.

    Expand
  5. Modify the execute() method (the version that uses the Iterator pattern) so that it handles Direction.CONTINUE. Specifically, when a Direction.CONTINUE is encountered the execute() method must get the next element in the method collection and then repeatedly move the Robot in that direction until it can no longer do so. What code did you add?
        public void execute(List<Direction> method)
        {
           Direction        d;
           Iterator<Direction>    i;
    
           i = method.iterator();
           while (i.hasNext())
           {
              d = i.next();
    
              if (d.equals(Direction.CONTINUE))
              {
                 d = i.next();
                 while (canMove(d)) move(d);             
              }
              else
              {
                 move(d);          
              }
           }
        }
        
    Expand
7. Using Complicated Type-Safe Collections: This part of the lab will help you understand more complicated type-safe collections.
  1. Read and understand Driver3.
  2. Add the following attribute to the Bender class:
        private Map<String, List<Direction>>    library;
        

    Make sure you understand this declaration.

  3. Instantiate the library attribute in the constructor of the Bender class. What code did you add?
           library = new HashMap<String, List<Direction>>();
        
    Expand
  4. Add the following method to the Bender class and complete it:
        /**
         * Add a method to the existing library
         *
         * @param method   The method to add
         */
        public void add(String name, List<Direction> method)
        {
    
        }
        
    What code did you add?
    
        /**
         * Add a method to the existing library
         *
         * @param method   The method to add
         */
        public void add(String name, List<Direction> method)
        {
           library.put(name, method);       
        }
        
    Expand
  5. Add the following method to the Bender class and complete it:
        /**
         * Execute a named set of instructions from the library.
         * Specifically, retrieve a named set of instructions from
         * the library and then call the other version of
         * execute().
         *
         * @param name   The name of the method
         */
        public void execute(String name)
        {
        }
        

    What code did you add?

        /**
         * Execute a named set of instructions from the library.
         * Specifically, retrieve a named set of instructions from
         * the library and then call the other version of
         * execute().
         *
         * @param name   The name of the method
         */
        public void execute(String name)
        {
           List<Direction>        method;
           
           method = library.get(name);
           if (method != null) execute(method);
        }
        
    Expand
  6. Compile and execute Driver3.

Copyright 2021