综合任务1
需求:学生的成绩存放于一个矩阵,其中行表示学生,列表示科目。如:第 0 行表示第 0 个学生的数学、语文、英语成绩。要求:
- 进行学生成绩的随机生成, 区间为 [50, 100].
- 找出成绩最好、最差的同学。但有挂科的同学不参加评比.
分析:
① 一个成绩矩阵——一个二维数组(行号代表学生编号,列好代表各个科目);
② 成绩随机生成,需要一个产生随机数的函数;
③ 需要计算所有没有挂科同学的成绩;
④ 从没有挂科的同学中选出成绩最好的、最差的同学。
Java知识补充
变量的作用:保存内存中的数据。
数据类型的分类:
- 基本数据类型:包括boolean,char,byte,short,int,long,folat,double.基本数据类型的变量保存的是数据的值,可以直接在栈中分配内存。
- 引用数据类型:包括类引用类型、接口引用类型和数组引用类型。不管何种引用类型的变量,它们引用的都是对象。引用类型的变量,在内存中存储的是对象的存储地址,变量放在栈中,对象实例放在堆中,变量保存的是堆地址。
内存简化结构
注意:将基本类型变量和引用类型变量的值赋给另一个变量的区别,引用类型变量赋值给另一个变量时,是将该变量指向堆中的地址给了新的变量,也就是说,这两个变量会指向同一个内存空间,当改变其中一个属性值时,也就是改变了另一个变量所值的属性值。
用new关键字创建对象
当一个引用类型的变量被声明后,如果没有初始化,那它就不指向任何对象。Java语言用new关键字创建对象,它有以下作用:
- 为对象分配内存空间,将对象的实例变量自动初始化为其变量类型的默认值。
- 如果实例变量在声明时被显示初始化,那就把初始化值赋给实例变量。
- 调用构造方法。
- 返回对象的引用。
用到的类
java.util.Random:获取随机数
import java.util.Arrays:提供操作数组的方法
代码中:
Random tempRandom = new Random();//创建一个Random类的实例对象,并赋给tempRandom(这是一个引用变量)
tempRandom.nextInt(51);//产生一个[0,51)的随机整数,得到的值再加上50,就能保证取得的随机数是[50,100]的整数。
Arrays.toString()将一维数组转换成字符串;
Arrays.deepToString()将多维数组转换成字符串
package day05;
import java.util.Arrays;
import java.util.Random;
public class Task1 {
/**
* The entrance of the program.
*
* @param args
*/
public static void main(String args[]) {
task1();
}// Of main
/**
* Method unit test.
*/
private static void task1() {
// Step 1. Generate the data with n students and m courses.
// Set these values by myself.
int n = 10;
int m = 3;
int lowerBound = 50;
int upperBound = 101;
int threshold = 65;
// Here we have to use an object to generate random numbers.
Random tempRandom = new Random();
int[][] data = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
data[i][j] = lowerBound + tempRandom.nextInt(upperBound - lowerBound);
} // Of j
} // Of i
System.out.println("The data is:\r\n" + Arrays.deepToString(data));
// Step 2. Compute the total score of each student.
int[] totalScore = new int[n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (data[i][j] < threshold) {
totalScore[i] = 0;
break;
} // Of if
totalScore[i] += data[i][j];
} // Of for j
} // Of for i
System.out.println("The total scores are:\r\n" + Arrays.toString(totalScore));
// Step 3. Find the best and worst student.
// Typical initialization for index: invalid value.
int tempBestIndex = -1;
int temWorstIndex = -1;
// Typical initialization for best and worst values.
// They must be replaced by valid values.
int tempBestScore = 0;
int tempWorstScore = m * upperBound + 1;
for (int i = 0; i < n; i++) {
// Do not consider failed students.
if (totalScore[i] == 0) {
continue;
} // Of if
if (tempBestScore < totalScore[i]) {
tempBestScore = totalScore[i];
tempBestIndex = i;
} // Of if
// Attention: This if statement cannot be combined with the last one
if (tempWorstScore > totalScore[i]) {
tempWorstScore = totalScore[i];
temWorstIndex = i;
} // Of if
} // Of for i
// Step 4. Output the student number and score.
if (tempBestIndex == -1) {
System.out.println("Cannot find the best student. All studens have failed.");
} else {
System.out.println("The best student is No." + tempBestIndex + " with scores: "
+ Arrays.toString(data[tempBestIndex]));
} // Of if
if (temWorstIndex == -1) {
System.out.println("Cannot find the worst student. All studens have succeeded.");
} else {
System.out.println("The worst student is No." + temWorstIndex + " with scores: "
+ Arrays.toString(data[temWorstIndex]));
} // Of if
}// Of task1
}// Of class Task1
运行结果:
总结:如果要是我在平时写代码的时候,我会将Step 2.和Step 3.的代码揉到一块儿写,在计算每个同学的总分的时候并找到最大值和最小值及其索引,这样会少一次遍历,当然这也会降低代码的可读性。。。
顺序表
面向对象编程
面向过程(POP) 与 面向对象(OOP)
- 二者都是一种思想,面向对象是相对于面向过程而言的。面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
- 面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等。
- 面向过程:根据业务逻辑从上到下写代码。
- 面向对象编程:将数据与函数捆绑到一起,进行封装,这样能够更快速的开发程序,减少了重复写代码的过程。
类与对象
- 类是一个模板,模板里面可以包含多个函数,函数里实现一些功能。
- 对象是根据模板创建的实例,通过实例对象可以执行类中的函数。
- 类的抽象:具有相同或相似属性和行为的一系列对象的集合都可以抽象出一个类。
类(Class)由3部分组成:
- 类的名称:类名
- 类的属性:一组数据
- 类的方法:允许对数据进行操作的方法(行为)
顺序表(一)
这里的代码中,提到了构造函数、方法覆盖、final修饰符。
构造函数:当new一个类的时候,所调用的函数,这也解释了为什么构造函数为什么要和类名一致。
final修饰符:
- 用final修饰的类不能被继承,没有子类;
- 用final修饰的方法不能被子类的方法覆盖;
- 用final修饰的变量表示常量,只能被赋一次值;
说白了,用final修饰的东西不能改~
为什么能直接打印tempFirstList呢?因为 toString 这个方法很特殊,本身是在 Object类中定义的,其返回值类型为String类型,返回类名和它的引用地址,当进行String类与其他类进行连接操作时,会自动调用toString()方法,而我们在SequentialList类中覆盖了该方法,所以会返回对象的字符串形式。
package day05;
public class SequentialList {
/**
* The maximal length of the list. It is a constant.
*
*/
public static final int MAX_LENGTH = 10;
/**
* The actual length not exceeding MAX_LENGTH. Attention: length is not only the
* member variable of Sequential list, but also the member variable of different
* classes.
*/
int length;
/**
* The data stored in an array.
*/
int[] data;
/**
* Construct an empty sequential list.
*/
public SequentialList() {
length = 0;
data = new int[MAX_LENGTH];
}// Of the first constructor
/**
* Construct a sequential list using an array.
*
* @param paraArray The given array. Its length should not exceed MAX_LENGTH.
* For simplicity now we do not check it.
*/
public SequentialList(int[] paraArray) {
data = new int[MAX_LENGTH];
length = paraArray.length;
// Copy data.
for (int i = 0; i < paraArray.length; i++) {
data[i] = paraArray[i];
} // Of for i
}// Of the second constructor
/**
* Overrides the method claimed in Object, the superclass of any class.
*/
public String toString() {
String resultString = "";
if (length == 0) {
return "empty";
} // Of if
for (int i = 0; i < length - 1; i++) {
resultString += data[i] + ", ";
} // Of for i
resultString += data[length - 1];
return resultString;
}// Of toString
/**
* Reset to empty.
*/
public void reset() {
length = 0;
}// Of reset
public static void main(String args[]) {
int[] tempArray = { 1, 4, 6, 9 };
SequentialList tempFirstList = new SequentialList(tempArray);
System.out.println("Initialized, the list is: " + tempFirstList.toString());
System.out.println("Again, the list is: " + tempFirstList);
tempFirstList.reset();
System.out.println("After reset,the list is: " + tempFirstList);
}// Of main
}// Of the SequentialList
运行效果:
顺序表(二)
主要完成了对顺序表的差值、插入、删除操作。
在对顺序表进行操作时,如果有明确的索引值,需要首先对索引值是否合法进行判断。插入操作首先要从后向前,依次将目标位置的元素后移一位,最后再对目标位置赋值;删除操作则是要从前向后,将元素向前移动一位,覆盖目标位置的值。
贴上与顺序表(一)不同代码的部分:
/**
* Find the index of the given value. If it appears in multiple positions,
* simply return the first one.
*
* @param paraValue The given value.
* @return The position. -1 for not found.
*/
public int indexOf(int paraValue) {
int temPosition = -1;
for (int i = 0; i < length; i++) {
if (data[i] == paraValue) {
temPosition = i;
break;
} // Of if
} // Of for i
return temPosition;
}// Of indexOf
/**
* Insert a value to position. If the list is already full,do nothing.
*
* @param paraPosition The given position.
* @param paraValue The given value.
* @return Success or not.
*/
public boolean insert(int paraPosition, int paraValue) {
if (length == MAX_LENGTH) {
System.out.println("List full.");
return false;
} // Of if
if ((paraPosition < 0) || (paraPosition > length)) {
System.out.println("The position " + paraPosition + " is out of bounds.");
return false;
} // Of if
// From tail to head. The last one is moved to a new position. Because length <
// MAX_LENGTH
for (int i = length; i > paraPosition; i--) {
data[i] = data[i - 1];
} // Of for i
data[paraPosition] = paraValue;
length++;
return true;
}// Of insert
/**
* Delete a value at a position.
*
* @param paraPosition The position
* @return Success or not.
*/
public boolean delete(int paraPosition) {
if ((paraPosition < 0) || (paraPosition >= length)) {
System.out.println("The position " + paraPosition + " is out of bounds.");
return false;
} // Of if
// From head to tail.
for (int i = paraPosition; i < length - 1; i++) {
data[i] = data[i + 1];
} // Of for i
length--;
return true;
}// Of delete
/**
* The entrance of the program.
*
* @param args Not used now.
*/
public static void main(String args[]) {
int[] tempArray = { 1, 4, 6, 9 };
SequentialList tempFirstList = new SequentialList(tempArray);
System.out.println("Initialized, the list is: " + tempFirstList.toString());
System.out.println("Again, the list is: " + tempFirstList);
int tempValue = 4;
int temPosition = tempFirstList.indexOf(tempValue);
System.out.println("The position of " + tempValue + " is " + temPosition);
tempValue = 5;
temPosition = tempFirstList.indexOf(tempValue);
System.out.println("The position of " + tempValue + " is " + temPosition);
tempValue = 2;
temPosition = 5;
if (tempFirstList.insert(temPosition, tempValue)) {
System.out.println("After inserting " + tempValue + " to position " + temPosition + ", the list is: "
+ tempFirstList);
} // Of if
temPosition = 3;
if (tempFirstList.delete(temPosition)) {
System.out.println("After deleting data at " + temPosition + ", the list is: " + tempFirstList);
} // Of if
for (int i = 0; i < 8; i++) {
if (tempFirstList.insert(i, i)) {
System.out.println("After inserting " + i + " to position " + i + ", the list is: " + tempFirstList);
} // Of if
} // Of for i
tempFirstList.reset();
System.out.println("After reset,the list is: " + tempFirstList);
}// Of main
运行效果:
总结:对顺序表的操作还算是简单,主要是要注意顺序表的索引和长度的关系以及删除和插入操作的小细节。自己下来还需要多补Java关于类与对象这块的知识~