SDSU CS 596 Client-Server Programming
Assignment 1 Solutions

[To Lecture Notes Index]
San Diego State University -- This page last updated February 29, 1996
----------

Contents of Assignment 1 Solutions Lecture

    1. Matrix
    2. Complete Listing

Matrix

import java.util.*;

class Matrix 
    {
    protected  Object[][]  matrixElements;

    protected  static  String  rowSeperator         = "\n";
    protected  static  String  columnSeperator      = "\t";
    protected  static  String  matrixStringHeader   = "Matrix(";
    protected  static  String  matrixStringTrailer  = ")";


    public Matrix( int  numberOfRows, int numberOfColumns )
        {
        matrixElements = new Object[numberOfRows][numberOfColumns];
        }

    public  Object  elementAt( int row,  int column )
        {
        return  matrixElements[ row ][ column ];
        }

    public  void  setElementAt( Object data, int row,  int column )
        {
        matrixElements[ row ][ column ] = data;
        }

     // rowSize = number of columns
    public  int  rowSize()
        {
        return matrixElements[ 0 ].length;
        }

     // columnSize = number of rows
    public  int  columnSize()
        {
        return matrixElements.length;
        }

Issues
Array verses Vector

What difference does it make?
Protection level
class Matrix 
    {
    protected  Object[][]  matrixElements;

verses
class Matrix 
    {
    Object[][]  matrixElements;

Storing or computing row and column length
    protected  int  rowSize;
    protected  int  columnSize;

    public Matrix( int  numberOfRows, int numberOfColumns )
        {
        rowSize  =  numberOfColumns;
        columnSize  =  numberOfRows;
        matrixElements = new Object[numberOfRows][numberOfColumns];
        }

verses code on previous page
Issues
Names

elementAt is Java standard

Names

rowSize verses numberOfColumns verses rowLength

Exceptions - Double check
    public  Object  elementAt( int row,  int column )
        {
         if ( ( row >= 0 ) && ( row < columnSize() ) &&
             ( column >= 0 ) && ( column < rowSize() ) )
             return  matrixElements[ row ][ column ];
         else
             throw new ArrayIndexOutOfBoundsException();
        }

verses
    public  Object  elementAt( int row,  int column )
        {
        return  matrixElements[ row ][ column ];
        }
Exceptions - Who catches?
    public  Object  elementAt( int row,  int column )
        {
        try 
            {
             return  matrixElements[ row ][ column ];
            }
         catch (ArrayIndexOutOfBoundsException e)
            {
             System.err.println( "Now what do I do? " );
            }
        }

verses
    public  Object  elementAt( int row,  int column )
        {
        return  matrixElements[ row ][ column ];
        }
     public  static  void main( String[] args )
        {
        try
            {
             Matrix  test  =  new  Matrix( 3, 5 );
             // code missing

             test.elementAt( 10, 20 );
             //  more stuff
            }
         catch (ArrayIndexOutOfBoundsException e)
            {
             //Now handle;
            }

More Matrix
    public  Vector  rowAt( int row )
        {
        Vector  rowCopy  =  new Vector();

        for  ( int column = 0;  column < rowSize();  column++ ) 
            rowCopy.addElement( elementAt( row, column) );
        return  rowCopy;
        }
    
    
    public  Vector  columnAt( int column )
        {
        Vector  columnCopy  =  new Vector();

        for  ( int row = 0;  row < columnSize();  row++ ) 
            columnCopy.addElement( elementAt( row, column ) );
        return  columnCopy;
        }

Issues
Names - Role or What
        Vector  rowCopy  =  new Vector();

verses
        Vector  vector  =  new Vector();

verses
        Vector  tempVector  =  new Vector();

Information Hiding
Vector or Array
            rowCopy.addElement( elementAt( row, column) );

verses
            rowCopy.addElement( matrixElements[ row ][ column] );

More Matrix
    protected  static  String  rowSeperator         = "\n";
    protected  static  String  columnSeperator      = "\t";
    protected  static  String  matrixStringHeader   = "Matrix(";
    protected  static  String  matrixStringTrailer  = ")";
    public  String  toString()
        {
        String  matrixAsString  =  matrixStringHeader + rowSeperator;
        for  ( int row  =  0; row < columnSize();  row++ ) 
            {
            matrixAsString  += rowToString( row ) + rowSeperator  ;
            }
        return matrixAsString.trim() + matrixStringTrailer;
        }


    protected  String  rowToString( int row )
        {
        String  rowAsString  =  new String();
        for  ( int column = 0;  column < rowSize(); column++ ) 
            {
            rowAsString  +=  elementAt( row, column ) + columnSeperator;
            }
    
        return rowAsString.trim();
        }

Issues
Constants
    protected  static  String  rowSeperator  = "\n";

Why rowToString?

So can be used by LabeledMatrix toString()
More Matrix
    public  static  Matrix  fromString(  String  matrixString ) 
         throws Exception
        {
         // stuff removed to save space
        }

Issues

Why part of Matrix class

Why static

What happens if string is not a mattrixString?

Labeled Matrix
class  LabeledMatrix  extends  Matrix 
    {
    Hashtable  rowLabelToIndex       =  new Hashtable();
    Hashtable  columnLabelToIndex  =  new Hashtable();

    public  LabeledMatrix( String[]  rowLabels,  String[] columnLabels)
        {
        super( rowLabels.length, columnLabels.length );
        
        for ( int row = 0; row < rowLabels.length; row++ )
            {
            rowLabelToIndex.put( rowLabels[ row ], new Integer( row ) );
            }

        for ( int column = 0;  column < columnLabels.length; column++ )
            {
            columnLabelToIndex.put( columnLabels[ column ], 
                                                    new Integer( column ) );
            }
        }

Issues
Label independence

Use two hashtables not one

Information hiding

Use parent's constructor
Object Safety/Consistancy

Constructor gets labels
Labels not added later
More LabeledMatrix
    public  Object  elementAt( String rowLabel, String columnLabel ) 
        throws NoSuchLabelException
        {
        int row      = labelToIndex( rowLabel, rowLabelToIndex );
        int column = labelToIndex( columnLabel , columnLabelToIndex );

        return  elementAt( row, column );
        }

    public  setElementAt( Object data, String rowLabel, 
                                     String columnLabel) 
         throws NoSuchLabelException
        {
        int row      = labelToIndex( rowLabel, rowLabelToIndex );
        int column = labelToIndex( columnLabel , columnLabelToIndex );

        super.setElementAt( data, row, column );
        }

    private  int  labelToIndex( String label, 
                                           Hashtable labelToIndexTable ) 
        throws NoSuchLabelException
        {

        if  ( labelToIndexTable.containsKey( label )  )
            {
            Integer index = (Integer) labelToIndexTable.get( label );
            return index.intValue();
            }
        else
            {
            throw new NoSuchLabelException( "No label " + label);
            }
        }

Issues
Information Hiding

use parent's setElementAt(), elementAt() to access data in matrix

Reduce name space clutterConsistancy

Overload setElementAt(), elementAt()

Abstraction/Information Hiding/Code Reuse

Isolate hashtable access in labelToIndex

Information Hiding

Should user of LabeledMatrix be able to access Matrix's setElementAt(), elementAt() operations?
Even more HidingOr how paranoid does one get?
    public  Object  elementAt( int row, int column ) 
        throws NoSuchMethodException
        {
        throw new NoSuchMethodException();
        }
    public  Object  elementAt( String rowLabel, String columnLabel ) 
        throws NoSuchLabelException
        {
        int row      = rowIndex( rowLabel );
        int column = columnIndex( columnLabel );

        return  elementAt( row, column );
        }


    private  int  rowIndex( String rowLabel ) 
        throws NoSuchLabelException
        {
         return labelToIndex( rowLabel, rowLabelToIndex );
        }

    private  int  columnIndex( String columnLabel ) 
        throws NoSuchLabelException
        {
         return labelToIndex( columnLabel, columnLabelToIndex );
        }

    private  int  labelToIndex( String label, 
                                           Hashtable labelToIndexTable ) 
        throws NoSuchLabelException
        {
         // As before
        }

Complete Listing

import java.util.*;

class Matrix 
    {
    protected  Object[][]  matrixElements;

    protected  static  String  rowSeperator         = "\n";
    protected  static  String  columnSeperator      = "\t";
    protected  static  String  matrixStringHeader   = "Matrix(";
    protected  static  String  matrixStringTrailer  = ")";


    public Matrix( int  numberOfRows, int numberOfColumns )
        {
        matrixElements = new Object[numberOfRows][numberOfColumns];
        }

    public  Object  elementAt( int row,  int column )
        {
        return  matrixElements[ row ][ column ];
        }

    public  void  setElementAt( Object data, int row,  int column )
        {
        matrixElements[ row ][ column ] = data;
        }

     // rowSize = number of columns
    public  int  rowSize()
        {
        return matrixElements[ 0 ].length;
        }

     // columnSize = number of rows
    public  int  columnSize()
        {
        return matrixElements.length;
        }

    public  Vector  rowAt( int row )
        {
        Vector  rowCopy  =  new Vector();

        for  ( int column = 0;  column < rowSize();  column++ ) 
            rowCopy.addElement( elementAt( row, column) );
        return  rowCopy;
        }
    
    
    public  Vector  columnAt( int column )
        {
        Vector  columnCopy  =  new Vector();

        for  ( int row = 0;  row < columnSize();  row++ ) 
            columnCopy.addElement( elementAt( row, column ) );
        return  columnCopy;
        }

    public  String  toString()
        {
        String  matrixAsString  =  matrixStringHeader + rowSeperator;
        for  ( int row  =  0; row < columnSize();  row++ ) 
            {
            matrixAsString  += rowToString( row ) + rowSeperator;
            }
        return matrixAsString.trim() + matrixStringTrailer;
        }

    protected  String  rowToString( int row )
        {
        String  rowAsString  =  new String();
        for  ( int column = 0;  column < rowSize(); column++ ) 
            {
            rowAsString  +=  elementAt( row, column ) + columnSeperator;
            }
    
        return rowAsString.trim();
        }

    public  static  Matrix  fromString(  String  matrixString ) 
         throws Exception
        {

        Vector  rowsString  =  extractRowsAsStrings( matrixString );

        StringTokenizer  rowParser;
        rowParser = new StringTokenizer( (String) rowsString.elementAt(1), 
                           columnSeperator );

        int  numberOfRows = rowsString.size();
        int numberOfColumns = rowParser.countTokens();

        Matrix  matrixFromString = new Matrix( numberOfRows , 
                                                                     numberOfColumns );
        
        for ( int row = 0;  row < numberOfRows; row++ )
            {
            String  rowAsString  =  (String) rowsString.elementAt( row );
            rowParser  =  new StringTokenizer( rowAsString , columnSeperator);

            for ( int column = 0;  column < numberOfColumns ; column++ )
                {
                 String dataAsString = rowParser.nextToken();
                 Integer  data  =  new Integer( dataAsString.trim() );
                 matrixFromString.setElementAt( data, row, column );
                }
             if ( rowParser.hasMoreTokens() )
                 throw new Exception( "Bad String as Matrix");
            }

        return matrixFromString;
        }

    private  static Vector extractRowsAsStrings(  String  matrixAsString )
        {
        StringTokenizer matrixParser = new StringTokenizer
                                                     ( matrixAsString, rowSeperator + 
                                                       matrixStringTrailer );

        // remove  header "Matrix(\n"
        matrixParser.nextToken();

        Vector  rowsAsStrings  =  new  Vector();

        while (  matrixParser.hasMoreTokens() )
            {
            rowsAsStrings.addElement( matrixParser.nextToken() );
            }

        return rowsAsStrings;
        }

    public static  void main( String args[] ) throws Exception
        {
        Matrix  test  =  new Matrix(3, 5);
        for (int row = 0; row < 3; row++)
            for (int col = 0; col < 5; col++ )
                test.setElementAt( new Integer( row + col), row , col);

        System.out.println( test );
        System.out.println( test.rowAt( 1) );
        System.out.println( test.columnAt( 1) );
        System.out.println( Matrix.fromString( test.toString() ));
        }
    }

class  LabeledMatrix  extends  Matrix 
    {
    Hashtable  rowLabelToIndex       =  new Hashtable();
    Hashtable  columnLabelToIndex  =  new Hashtable();

    public  LabeledMatrix( String[]  rowLabels,  String[] columnLabels)
        {
        super( rowLabels.length, columnLabels.length );
        
        for ( int row = 0; row < rowLabels.length; row++ )
            {
            rowLabelToIndex.put( rowLabels[ row ], new Integer( row ) );
            }

        for ( int column = 0;  column < columnLabels.length; column++ )
            {
            columnLabelToIndex.put( columnLabels[ column ], new Integer( column ) );
            }
        }

    public  Object  elementAt( String rowLabel, String columnLabel ) 
        throws NoSuchLabelException
        {
        int row      = labelToIndex( rowLabel, rowLabelToIndex );
        int column = labelToIndex( columnLabel , 
                                    columnLabelToIndex );

        return  elementAt( row, column );
        }

    public  setElementAt( Object data, String rowLabel, String columnLabel) 
        throws NoSuchLabelException
        {
        int row      = labelToIndex( rowLabel, rowLabelToIndex );
        int column = labelToIndex( columnLabel , 
                                    columnLabelToIndex );

        super.setElementAt( data, row, column );
        }

    private  int  labelToIndex( String label, 
        Hashtable labelToIndexTable ) throws NoSuchLabelException
        {

        if  ( labelToIndexTable.containsKey( label )  )
            {
            Integer index = (Integer) labelToIndexTable.get( label );
            return index.intValue();
            }
        else
            {
            throw new NoSuchLabelException( "No label " + label);
            }
        }

    public static  void main( String args[] )
        {
        String[] rowLabels  =  { "sam", "pete", "roger" };
        String[] columnLabels  =  { "exam", "final", "roger" };
        LabeledMatrix  test  =  new LabeledMatrix( rowLabels, columnLabels);
        test.setElementAt( new Integer(5), "sam" , "final");

        System.out.println( test );
        System.out.println( test.rowAt( 1) );
        System.out.println( test.columnAt( 1) );
        System.out.println( Matrix.fromString( test.toString() ));
        }

    }


class  NoSuchLabelException  extends  Exception
    {
    public  NoSuchLabelException()
        {
        super();
        }

    public  NoSuchLabelException( String  message )
        {
        super( message );
        }
    }
----------