讲解Java Coursework、代表写Matrix java homework 、辅导java assignment

- 首页 >> Java编程


COMP103P Applied Software Development

Last Summer Assessment Coursework

(for the project component)

Wednesday 15th August. Submit a zip file containing the source code organised into folders for

each question answered.

Aim: You are asked to write a body of Java code to demonstrate a good understanding of classes

and object-oriented design. The design and implementation of the code will require appropriate

thought and planning.

Marking: The work will be graded A-F.

On this scheme a grade C is considered to be basically satisfactory, which means the program

runs, does more or less the right things and has a reasonable design using functions. Grades B

and A represent better and excellent programs, while D and E are progressively less good

programs that show serious problems in execution and/or design. Grade F means a failure to

submit anything of merit.

Getting a good grade: Marking will take into account the quality of the program you write. In

particular pay attention to the following:

• Proper declaration and use of classes and class relationships.

• The layout and presentation of the program code.

• Appropriate selection of class, variable and method names.

• Appropriate use of comments. Don't add comments that should be obvious by reading the

code. Your code should be fully readable without comments.

• Selection of a suitable design to provide an effective solution to the problems in question.

Development Advice:

• Keep things straightforward!

• Keep things straightforward! (Very important so I've repeated it.)

• Straightforward does not mean trivial.

• First brainstorm/doodle/sketch to get a feel for the program you need to write and what it

should do.

• Don't rush into writing Java code if you don't fully understand what classes, variables or

methods are needed. Don't let the detail of writing code confuse your design thinking.

• What is the structure of the code in terms of classes, interfaces and class relationships.

• How is the behaviour of the program implemented in terms of methods calling each other?

• Role play or talk through the sequence of method calls to make sure everything makes

sense.

• Are your classes cohesive and your methods short and cohesive?

• Can't get started? Do a subset of the problem or invent a simpler version, and work on that

to see how it goes. Then return to the more complex problem.

COMP103P C LSA Coursework

-2-

The Coursework

This coursework is about implementing Matrix classes, making use of interfaces, an abstract class,

inheritance, overridden methods, a factory and exceptions. A matrix class represents the familiar

rectangular array of numbers, with the size specified by the number of rows and columns. The

contents of a matrix are represented by double values. The Java language features needed to

implement these classes were covered in the COMP103P lectures and background reading, and it

would be a good idea to refresh your knowledge of Java and classes first.

The goal is to set up a framework that will support several classes providing different concrete

Matrix implementations. The framework structure is shown below:

This framework is based on the principles used by the data structure classes in the standard Java

libraries. Interface Matrix defines the common methods for all matrix classes. A variable of type

Matrix can reference any Matrix object of a class that implements Matrix (or inherits the

implements relationship). This enables ‘Programming to an Interface’, allowing code to be written

using the Matrix type without needing to be concerned about the exact type of Matrix of objects it is

working with at runtime.

The Matrix interface, documented using documentation comments, is defined as follows:

/*

* Specification of the public methods that all matrix

* implementations should provide.

* Copyright (c) 2018

* Dept. of Computer Science, UCL

* @author Graham Roberts

* @version 1.7 Sept 2018

*/

public interface Matrix

{

/**

* Return the number of rows in the matrix.

* @return the number of rows in the matrix.

COMP103P C LSA Coursework

-3-

*/

public int getNumberOfRows();

/**

* Return the number of columns in the matrix.

* @return the number of columns in the matrix.

*/

public int getNumberOfColumns();

/**

* Return the element at position (row,column).

*

* @param row row of element to return.

* @param column column of element to return.

* @return element value of element.

* @throws MatrixException if the element position is not within the

* matrix.

*/

public double getElement(final int row, final int column)

throws MatrixException;

/**

* Set element at position (row,column). If the element is not within

* the matrix, the matrix is left unchanged.

*

* @param row row of element to set.

* @param column column of element to set.

* @param value value to store at (row,column).

* @throws MatrixException if the element position is not within the

* matrix.

*/

public void setElement(final int row, final int column, final double value)

throws MatrixException;

/**

* Add the argument matrix to <i>this</i> and return a new matrix containing

* the result.

* The matrices must match in size for the addition to succeed.

* This is a generic method that can add matrices of any concrete

* implementation class.

* @param m matrix to add to <i>this</i>.

* @return new matrix containing the result or null.

* @throws MatrixException if parameter matrix is not the same size

* as the matrix the method is called for.

*/

public Matrix add(final Matrix m) throws MatrixException;

/**

* Subtract the argument matrix from <i>this</i> and return a new matrix

* containing the result.

* The matrices must match in size for the subtraction to succeed.

* This is a generic method that can subtract matrices of any concrete

* implementation class.

* @param m matrix to subtract from <i>this</i>.

* @return new matrix containing the result or null.

* @throws MatrixException if parameter matrix is not the same size

* as the matrix the method is called for.

*/

public Matrix subtract(final Matrix m) throws MatrixException;

/**

* Multiply the argument matrix with <i>this</i> and return a new matrix

* containing the result.

* The matrices must have valid sizes for the multiplication to succeed.

* This is a generic method that can multiply matrices of any concrete

COMP103P C LSA Coursework

-4-

* implementation class.

* @param m matrix to multiply with <i>this</i>.

* @return new matrix containing the result or null.

* @throws MatrixException if matrices are not of compatible size

* to perform multiplication.

*/

public Matrix multiply(final Matrix m) throws MatrixException;

}

Note that a number of methods are declared as throwing exceptions of type MatrixException, if an

attempt is made to access an invalid matrix element (i.e., the row,column specified is not in the

matrix) or if an invalid operation applied to a matrix. A single exception class is used to represent

all errors but the constructors have parameters allowing the message stored in the exception to

provide more information. The MatrixException class is:

/**

* Exception subclass to represent exceptions thrown when working

* with matrix objects.

* Copyright (c) 2018

* Dept. of Computer Science, UCL

* @author Graham Roberts

* @version 1.1

*/

public class MatrixException extends Exception

{

/**

* Provide a custom message.

* @param message The message to store in the exception object.

*/

public MatrixException(String message)

{

super(message);

}

/**

* Attempt made to access an invalid matrix element.

* @param row Index of row

* @param column Index of column

*/

public MatrixException(int row, int column)

{

super("Attempt to access invalid element ("+row+","+column+")");

}

}

The AbstractMatrix class is an abstract class that provides common methods for concrete

subclasses. This avoids duplicating the methods in the subclasses as they can just be inherited.

Remember that an abstract class cannot have instance objects, so attempting to create a new

AbstractMatrix object will result in a compilation error.

The listing below includes an example add method, which adds two matrices together returning a

new matrix as the result. The new matrix object returned is created using a Factory. A factory is a

class that specialises in creating objects. The use of a factory avoids code having to name a

specific concrete set class and decouples object creation from class naming. Factory is an

example of a Design Pattern.

The AbstractMatrix class follows:

/*

* An abstract matrix class providing the shared implementation

* for concrete subclasses.

* The add, subtract and multiply methods are declared final, so cannot

* be overridden by subclasses.

COMP103P C LSA Coursework

-5-

* Copyright (c) 2018

* Dept. of Computer Science, UCL

* @author Graham Roberts

* @version 1.7 Sept 2018

*/

public abstract class AbstractMatrix implements Matrix

{

private static MatrixFactory factory = new DefaultMatrixFactory();

private Matrix getNewMatrixInstance(Matrix kind,

int numberOfRows, int numberOfColumns)

throws MatrixException

{

return factory.getInstance(kind.getClass(), numberOfRows, numberOfColumns);

}

/**

* Set the factory to be used for matrix creation. Note this is a static

* method so <em>all</em> matrix objects created from now on

* will be created by the new factory.

* @param aFactory The factory to use.

*/

public static void setFactory(MatrixFactory aFactory)

{

factory = aFactory;

}

public final boolean isSameSize(final Matrix m)

{

return (getNumberOfRows() == m.getNumberOfRows())

&& (getNumberOfColumns() == m.getNumberOfColumns());

}

public final Matrix add(final Matrix m) throws MatrixException

{

if (!isSameSize(m))

{

throw new MatrixException("Trying to add matrices of different sizes");

}

final Matrix result =

getNewMatrixInstance(this, getNumberOfRows(), getNumberOfColumns());

for (int row = 0; row < getNumberOfRows(); row++)

{

for (int column = 0; column < getNumberOfColumns(); column++)

{

final double value =

getElement(row, column) + m.getElement(row, column);

result.setElement(row, column, value);

}

}

return result;

}

public final Matrix subtract(final Matrix m) throws MatrixException

{

// The method body is not provided - you should write your own implementation

}

public final Matrix multiply(final Matrix m) throws MatrixException

{

// The method body is not provided - you should write your own implementation

}

}

COMP103P C LSA Coursework

-6-

Class AbstractMatrix class uses class DefaultMatrixFactory to create new matrix objects but this

can be changed at runtime by providing a different factory. As the factory is referenced via a static

variable the same factory is used for creating all matrix objects. Allowing this variability is a

common strategy to facilitate testing, as test code can provide a special factory for testing

purposes.

Interface MatrixFactory defines the public methods needed by a factory. This again allows the

Programming to an Interface concept to separate specification from implementation.

/**

* This interface defines the public methods that a Matrix factory must

* implement.

* Copyright (c) 2018

* Dept. of Computer Science, UCL

* @author Graham Roberts

* @version 1.1

*/

public interface MatrixFactory

{

/**

* Create a matrix that is an instance of the same class as the

* parameter object, with the given matrix size.

* @param matrixClass A class object used to determine the class

* of the matrix to instantiate

* @param numberOfRows The number of rows in the new matrix.

* @param numberOfColumns The number of columns in the new matrix.

* @return The new matrix.

* @throws MatrixException If the class is not recognised as one from

* which a matrix object can be created or if an attempt is made to

* create a matrix with an invalid size.

*/

public Matrix getInstance(Class matrixClass,

int numberOfRows, int numberOfColumns)

throws MatrixException;

/**

* Create a matrix that is an instance of the same class as the

* parameter object, with the given content. The matrix size is

* determined from the content provided.

* @param matrixClass A class object used to determine the

* class of the matrix to instantiate.

* @param contents The contents of the new matrix.

* @return The new matrix.

* @throws MatrixException If the class is not recognised as one from

* which a matrix object can be created or if an attempt is made to

* create a matrix with an invalid size.

*/

public Matrix getInstance(Class matrixClass, double[][] contents)

throws MatrixException;

}

Note that the getInstance factory methods take a value of type Class, which is used to determine

the class of the matrix object to be created. Java represents classes at runtime with objects of type

Class and an object can be asked for its class.

The DefaultMatrixFactory class looks like this:

/**

* Factory to create Matrix objects.

* Copyright (c) 2018

* Dept. of Computer Science, UCL

* @author Graham Roberts

* @version 1.1

*/

COMP103P C LSA Coursework

-7-

public class DefaultMatrixFactory implements MatrixFactory

{

public Matrix getInstance(Class matrixClass,

int numberOfRows, int numberOfColumns)

throws MatrixException

{

if (matrixClass.equals(ArrayMatrix.class))

{

return new ArrayMatrix(numberOfRows,numberOfColumns);

}

if (matrixClass.equals(SparseMatrix.class))

{

return new SparseMatrix(numberOfRows,numberOfColumns);

}

throw new MatrixException

("getNewInstance: Class is not a recognised matrix class");

}

public Matrix getInstance(Class matrixClass, double[][] contents)

throws MatrixException

{

if (matrixClass.equals(ArrayMatrix.class))

{

return new ArrayMatrix(contents);

}

if (matrixClass.equals(SparseMatrix.class))

{

return new SparseMatrix(contents);

}

throw new MatrixException

("getNewInstance: Class is not a recognised matrix class");

}

}

To illustrate how to implement a concrete matrix class as a subclass of AbstractMatrix, here is an

outline template of class ArrayMatrix that uses a 2D array of doubles to store the values held in the

matrix.

public class ArrayMatrix extends AbstractMatrix

{

private double[][] elements;

public ArrayMatrix(final int rows, final int columns)

throws MatrixException

{

// Initialise a new matrix with all the elements set to 0.0

}

public ArrayMatrix(double[][] content) throws MatrixException

{

// Initialise a new matrix storing the data provided by the

// double[][] parameter. Note the data should be copied.

}

public int getNumberOfRows()

{

// Number of rows in matrix

}

public int getNumberOfColumns()

{

// Number of columns in matrix

}

COMP103P C LSA Coursework

-8-

public double getElement(final int row, final int column)

throws MatrixException

{

// Return the element at the specified position or throw an exception

}

public void setElement(final int row, final int column, final double value)

throws MatrixException

{

// Set the element at the specified position or throw an exception

}

}

Note that class ArrayMatrix throws exceptions but does not catch any of its own exceptions. A

matrix throws exceptions, while code using a matrix catches any exceptions using try/catch blocks.

Make sure you understand the point being made here.

Finally, here is some example code that uses the classes and interfaces above:

/**

* Example code illustrating the use of Matrix objects.

*/

public class MatrixExample

{

private MatrixFactory factory = new DefaultMatrixFactory();


// Output matrix neatly to screen.

public void display(Matrix m) throws MatrixException

{

for (int row = 0 ; row < m.getNumberOfRows() ; row++)

{

for (int column = 0 ; column < m.getNumberOfColumns() ; column++)

{

System.out.print(m.getElement(row,column) + " ");

}

System.out.println();

}

}

public void runExamples()

throws MatrixException

{

Matrix m1

= factory.getInstance(SparseMatrix.class,

new double[][]{{1.2,2.5,4.5},

{3.9,4.2,0.9}});

Matrix m2

= factory.getInstance(SparseMatrix.class,

new double[][]{{1.3,7.5,5.2},

{4.8,8.3,9.1}});

Matrix m3 = m1.add(m2);

display(m3);

Matrix m4

= factory.getInstance(ArrayMatrix.class,

new double[][]{{1.2,2.5,4.5},

{3.9,4.2,0.9}});

Matrix m5

= factory.getInstance(ArrayMatrix.class,

new double[][]{{1.3,7.5,5.2},

{4.8,8.3,9.1}});

Matrix m6 = m4.add(m5);

display(m6);

COMP103P C LSA Coursework

-9-

Matrix m7 = m1.add(m5);

display(m7);

}

public static void main(final String[] args)

throws MatrixException

{

new MatrixExample().runExamples();

}

}

Code to Write

Q1.

a) Fill in the template for the ArrayMatrix class shown above to create a complete working class.

b) Write the subtract and multiply method bodies for class AbstractMatrix. These methods will be

inherited by all matrix subclasses and should work with any matrix implementation, so should only

make use of the methods declared in the Matrix interface. The add method body is already

provided as an example. You should not define any add, subtract or multiply methods in the

ArrayMatrix class.

c) Write a test program to test your matrix implementation. The test program should test all

methods of the matrix class, including the error handling (e.g., testing that an exception is thrown

when matrices of incompatible sizes are added, subtracted or multiplied).

Q2. Implement a sparse matrix subclass called SparseMatrix, following the same basic template

as the ArrayMatrix class but with a different data structure.

A sparse matrix behaves exactly like a normal matrix but only values that are not equal to 0.0 are

actually stored, the rest are assumed to be 0.0. Hence, the matrix object only stores the value of a

matrix element in its data structure if that element is explicitly set to a value other than 0.0 by a call

to setElement. If getElement is called to access an element whose value has not been explicitly set

then the default value of 0.0 is returned, and no space in the data structure is needed.

A sparse matrix allows a large matrix to be represented in a relatively small amount of memory,

providing the majority of elements have the value 0.0. This is useful for certain types of calculation.

To implement a sparse matrix consider using a HashMap as the data structure (but investigate

sets as well). This is a kind of hash table and is documented in the online Javadoc documentation.

An element in a hash table is accessed using a key value. For the sparse matrix the key value can

be the (x,y) coordinates of an element in matrix.

To represent a key value, look at class Index below, which should be nested in the scope of the

sparse matrix class. The hash table can then be declared as a HashMap<Index,Double>, i.e., a

map from an index to a double value, which has to be stored as a Double object as maps cannot

store values of primitive types directly (but find out how autoboxing/unboxing helps).

private static class Index

{

private int x = 0;

private int y = 0;

private int hashvalue = 0;

public Index(final int x, final int y)

{

this.x = x;

this.y = y;

hashvalue =

((x +"") + (y + "")).hashCode();

COMP103P C LSA Coursework

-10-

}

// Override equals and hashcode to ensure Index objects

// behave correctly when used as keys in a hash table.

@Override

public boolean equals(final Object obj)

{

if (obj instanceof Index)

{

Index index = (Index) obj;

return ((x == index.x) && (y == index.y));

}

else

{

return false;

}

}

@Override

public int hashCode()

{

return hashvalue;

}

}

Study this class carefully and use the Javadoc documentation, books and other sources to work

out what the equals and hashcode methods are doing. Make sure that the setElement method of

the matrix class does not end up adding two values with the same index.

Write a test program to test your sparse matrix class and the exception handling.

Q3. It should be possible to use both ArrayMatrix and SparseMatrix objects interchangeably in the

same program, for example to add an ArrayMatrix to a SparseMatrix. Write some example code to

confirm this does actually work.

Q4. Implement another sparse matrix subclass using a tree data structure. Extend and re-run the

test program from Q3 to work with this new subclass.

Q5. Write a program that uses your Matrix classes to do the following:

• Add a class that can read and write the contents of a Matrix to and from files. Note, that the

code to access the files should all go in this class, not in the Matrix classes.

• Provide a command line to type in commands to use matrices interactively. For example,

you might support the following interaction:

a = readMatrixFrom(‘datafile.txt’)

b = a * 10 // Multiple all elements by 10

c = a + b // Also subtract and multiple matrices

• Display a Matrix neatly.

• Work with very large matrices.

COMP103P C LSA Coursework

-11-

Q6. (Challenge Question – do this if you can) Using Java generics, modify all your classes (and

interfaces) to create generic classes. This would allow the type of number stored to be determined

using declarations like:

Matrix<Double> myMatrix = new ArrayMatrix<Double>(10,10);

Matrix<Integer> intMatrix = new SparseMatrix<Integer>(5,6);

Matrix<BigDecimal> big = new SparseMatrix<BigDecimal>(100,100);


站长地图