第 31 天: 整数矩阵及其运算

目标:
矩阵对象的创建.
getRows 等: getter, setter 在 java 里面很常用. 主要是为了访问控制.
整数矩阵的加法、乘法.
Exception 的抛出与捕获机制.
用 this 调用其它的构造方法以减少冗余代码.
代码看起来多, 但矩阵运算我们以前写过.
把数据类型修改成 double, 获得 DoubleMatrix.java, 以后会很有用.
getIdentityMatrix: 单位矩阵.
resultMatrix.data[i][i]: 成员变量的访问权限: 在同一类里面是可以直接使用的.
代码如下

import java.util.Arrays;

public class IntMatrix {

	int[][] data;

	public IntMatrix(int paraRows, int paraColumns) {
		data = new int[paraRows][paraColumns];
	}//the first constructor

	public IntMatrix(int[][] paraMatrix) {
		data = new int[paraMatrix.length][paraMatrix[0].length];

		// 元素复制
		for (int i = 0; i < data.length; i++) {
			for (int j = 0; j < data[0].length; j++) {
				data[i][j] = paraMatrix[i][j];
			} //j
		} //i
	}//the second constructor

	public IntMatrix(IntMatrix paraMatrix) {
		this(paraMatrix.getData());
	}//third constructor

	public static IntMatrix getIdentityMatrix(int paraRows) {
		IntMatrix resultMatrix = new IntMatrix(paraRows, paraRows);
		for (int i = 0; i < paraRows; i++) {
			// According to access control, resultMatrix.data can be visited
			// directly.
			resultMatrix.data[i][i] = 1;
		} //i
		return resultMatrix;
	}//getIdentityMatrix

	public String toString() {
		return Arrays.deepToString(data);
	}//toString

	public int[][] getData() {
		return data;
	}//getData

	public int getRows() {
		return data.length;
	}//getRows

	public int getColumns() {
		return data[0].length;
	}//getColumns

	public void setValue(int paraRow, int paraColumn, int paraValue) {
		data[paraRow][paraColumn] = paraValue;
	}//setValue

	public int getValue(int paraRow, int paraColumn) {
		return data[paraRow][paraColumn];
	}//getValue

	public void add(IntMatrix paraMatrix) throws Exception {
		// Step 1. 获取指定矩阵的值
		int[][] tempData = paraMatrix.getData();

		// Step 2. 确定矩阵规格大小
		if (data.length != tempData.length) {
			throw new Exception("Cannot add matrices. Rows not match: " + data.length + " vs. "
					+ tempData.length + ".");
		} //if
		if (data[0].length != tempData[0].length) {
			throw new Exception("Cannot add matrices. Rows not match: " + data[0].length + " vs. "
					+ tempData[0].length + ".");
		} //if

		// Step 3. 求和
		for (int i = 0; i < data.length; i++) {
			for (int j = 0; j < data[0].length; j++) {
				data[i][j] += tempData[i][j];
			} //j
		} //i
	}//add

	public static IntMatrix add(IntMatrix paraMatrix1, IntMatrix paraMatrix2) throws Exception {
		// Step 1. 克隆第一个矩阵
		IntMatrix resultMatrix = new IntMatrix(paraMatrix1);

		// Step 2.两矩阵求和
		resultMatrix.add(paraMatrix2);

		return resultMatrix;
	}//add

	public static IntMatrix multiply(IntMatrix paraMatrix1, IntMatrix paraMatrix2)
			throws Exception {
		// Step 1. 大小检验
		int[][] tempData1 = paraMatrix1.getData();
		int[][] tempData2 = paraMatrix2.getData();
		if (tempData1[0].length != tempData2.length) {
			throw new Exception("Cannot multiply matrices: " + tempData1[0].length + " vs. "
					+ tempData2.length + ".");
		} //if

		// Step 2. 空间分配
		int[][] resultData = new int[tempData1.length][tempData2[0].length];

		// Step 3. 相乘
		for (int i = 0; i < tempData1.length; i++) {
			for (int j = 0; j < tempData2[0].length; j++) {
				for (int k = 0; k < tempData1[0].length; k++) {
					resultData[i][j] += tempData1[i][k] * tempData2[k][j];
				} //k
			} //j
		} //i

		// Step 4. 构造矩阵对象(这里不知道有什么意义)
		IntMatrix resultMatrix = new IntMatrix(resultData);

		return resultMatrix;
	}//multiply

	public static void main(String args[]) {
		IntMatrix tempMatrix1 = new IntMatrix(3, 3);
		tempMatrix1.setValue(0, 1, 1);
		tempMatrix1.setValue(1, 0, 1);
		tempMatrix1.setValue(1, 2, 1);
		tempMatrix1.setValue(2, 1, 1);
		System.out.println("The original matrix is: " + tempMatrix1);

		IntMatrix tempMatrix2 = null;
		try {
			tempMatrix2 = IntMatrix.multiply(tempMatrix1, tempMatrix1);
		} catch (Exception ee) {
			System.out.println(ee);
		} //try
		System.out.println("The square matrix is: " + tempMatrix2);

		IntMatrix tempMatrix3 = new IntMatrix(tempMatrix2);
		try {
			tempMatrix3.add(tempMatrix1);
		} catch (Exception ee) {
			System.out.println(ee);
		} //try
		System.out.println("The connectivity matrix is: " + tempMatrix3);
	}//main

}

运行结果:

The original matrix is: [[0, 1, 0], [1, 0, 1], [0, 1, 0]]
The square matrix is: [[1, 0, 1], [0, 2, 0], [1, 0, 1]]
The connectivity matrix is: [[1, 1, 1], [1, 2, 1], [1, 1, 1]]

笔记:
在 Java 中通常采用 try catch 语句来捕获异常并处理。语法格式如下:

try {
    逻辑代码块1;
} catch(ExceptionType e) {
    处理代码块1;
}

在以上语法中,把可能引发异常的语句封装在 try 语句块中,用以捕获可能发生的异常。

如果 try 语句块中发生异常,那么一个相应的异常对象就会被拋出,然后 catch 语句就会依据所拋出异常对象的类型进行捕获,并处理。处理之后,程序会跳过 try 语句块中剩余的语句,转到 catch 语句块后面的第一条语句开始执行。

如果 try 语句块中没有异常发生,那么 try 块正常结束,后面的 catch 语句块被跳过,程序将从 catch 语句块后的第一条语句开始执行。

在以上语法的处理代码块1中,可以使用以下 3 个方法输出相应的异常信息。
printStackTrace() 方法:指出异常的类型、性质、栈层次及出现在程序中的位置。
getMessage() 方法:输出错误的性质。
toString() 方法:给出异常的类型与性质。

注意:catch 语句的参数类似于方法的声明,包括一个异常类型和一个异常对象。异常类型必须为 Throwable 类的子类,它指明 catch 语句可以处理的异常类型,异常对象则由运行时系统在 try 语句块中生成并被捕获。