一、计算机编程基础

1.人机交互方式

(1).图形化界面(GUI),简单直观,使用者易于接受且容易上手。
(2).命令行方式(CLI),需要有一个控制台,输入特定的指令,让计算机完成一些操作。

2.常用的一些命令行指令

(1).dir: 列出当前目录下的文件以及文件夹
(2).md: 创建目录(文件夹)
(3).rd: 删除目录(需要保证目录是空的)
(4).cd: 进入指定目录
(5).cd..:退回到上一级目录
(6).cd\: 退回到根目录
(7).del: 删除文件
(8).exit:退出dos命令行

del后面也可以跟文件夹名,作用是把该文件夹内所有文件都删除。

3.Java的两种核心机制

(1).Java虚拟机(JVM)

Ⅰ.JVM是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器。
Ⅱ.对于不同平台,有不同的虚拟机。
Ⅲ.只有某平台提供了对应的Java虚拟机,Java程序才能在此平台运行。
Ⅳ.Java虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,到处运行”。

(2).垃圾回收

Ⅰ.不再使用的内存空间应回收,在C/C++等语言中,由程序员负责回收无用内存。
Ⅱ.垃圾回收在Java程序运行过程中自动进行,程序员无法精确控制和干预。
Ⅲ.还是有可能出现内存泄露和内存溢出的问题。

4.JDK,JRE

(1).JDK(Java Decelopment Kit)Java开发工具包

JDK是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE,所以安装了JDK就不用单独安装JRE了。

(2).JRE(Java Runtime Environment)Java运行环境

包括Java虚拟机和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机只需要安装JRE即可

JDK与JRE的关系

二、了解Java

1.注释

(1).单行注释

1
2
3
4
5
6
Class Hello{
public static void main(String args[]){
//我是单行注释
System.out.println("Hello, World!");
}
}

(2).多行注释

1
2
3
4
5
6
7
8
9
Class Hello{
/*
我是多行注释,
main方法是程序的入口!
*/
public static void main(String args[]){
System.out.println("Hello, World!");
}
}

(3).文档注释(Java特有)

1
2
3
4
5
6
7
8
9
10
/**
文档注释,可以被javadoc所解析,生成一套以网页文件形式体现的该程序的说明文档
@author jagger
@version 1.0
*/
Class Hello{
public static void main(String args[]){
System.out.println("Hello, World!");
}
}

三、Java基本语法

1.关键字与保留字

(1).用于定义数据类型的关键字

class interface enum byte
short int long float
double char boolean void

(2).用于定义流程控制的关键字

if else switch case
default while do for
break continue return

(3).用于定义访问权限修饰符的关键字

private protected public

(4).用于定义类、函数、变量修饰符的关键字

abstract final static synchronized

(5).用于定义类与类之间的关系

extends implements

(6).用于定义建立实例及引用实例,判断实例的关键字

new this super instanceof

(7).用于异常处理的关键字

try catch finally throw throws

(8).用于包的关键字

package import

(9).其他修饰符关键字

native strictfp transient volatile assert

(10).用于定义数据类型值的字面值

true false null

保留字:现有Java版本尚未使用,但是以后的版本可能会作为关键字使用的,命名标识符时要避免使用这些保留字。

goto、const

2.Java中级名称命名规范

(1).包名:多单词组成时所有字母都小写:xxxyyyzzz

(2).类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz

(3).变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母发泄:xxxYyyZzz

(4).常量名:所有字母都大写。多单词组成时用下划线连接:XXX_YYY_ZZZ

3.Java的几种数据类型

数据类型

4.变量

(1).整型:byte(1字节=8bit),short(2字节),int(4字节),long(8字节)

1
2
3
4
5
6
7
8
9
10
Class Hello{
public static void main(String args[]){
/*
定义long类型的数据时要在后面加上“L”或者“l”,
不加的话会默认转换为int类型的,但是超过了int的表示范围之后就必须加L
*/
long a = 151234L;
System.out.println("Hello, World!");
}
}

(2).浮点型:float(4字节)、double(8字节)

1
2
3
4
5
6
7
8
9
10
Class Hello{
public static void main(String args[]){
/*
定义float类型的变量时要在后面加上“f”或者“F”
*/
double a = 15.1;
float f1 = 12.3f;
System.out.println("Hello, World!");
}
}

(3).字符型:char(2字节)

1
2
3
4
5
6
7
8
9
10
11
12
13
Class Hello{
public static void main(String args[]){
/*
1.声明一个字符
2.转义字符
3.直接使用Unicode的值来表示
*/
char c1 = 'a';
char c2 = '\n';
char c3 = '\u0043';
System.out.println("Hello, World!");
}
}

(4).布尔型:boolean(1字节)

5.自动类型提升和强制类型转换

(1).自动类型提升

当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的类型。
byte 、 short 、 char -> int -> long -> float -> double
特别的,当byte、char、short三种类型的变量做运算时(包括与自身相同的类型),结果为int型。
变量与整形、浮点型常量做运算时,整型常量默认为int型,浮点型常量默认为double型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class VariableTest{
public static void main(String args[]){
byte b1 = 2;
int i1 = 129;
// 因为运算结果是int,所以用更小的byte去接收是会报错的
// byte b2 = b1 + i1;
int i2 = b1 + i1;
long l1 = b1 + i1;
System.out.println(i2); //131

// 那么使用浮点型变量是否可以接收整形呢
float f =b1 + i1;
System.out.println(f); //131.0

short s1 = 123;
double d1 = s1;
System.out.println(d1); //123.0

char c1 = 'a';
int i3 = 10;
int i4 = c1 + i3;
System.out.println(i4); //97

short s2 = 10;
// short s3 = c1 + s2; 报错
// char c2 = c1 + s2; 报错

byte b2 = 10;
// char c3 = c1 + b2; 报错
}
}

(2).强制类型转换

即自动类型提升运算的逆运算
需要使用强转符:()
注意点:强制类型转换可能导致精度损失

1
2
3
4
5
6
7
8
class VariableTest{
public static void main(String args[]){
double d1 = 12.3;

int i1 = (int)d1;
System.out.println(i1); //12
}
}

6.String类型变量的使用

(1).String不是基本数据类型,属于引用数据类型

(2).声明String类型变量时,使用一对双引号:””

(3).String可以和8种基本数据类型做运算,且运算只能是连接运算:+,运算的结果仍是String类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class StringTest{
public static void main(String args[]){
String s1 = "Hello World";
System.out.println(s1);
int number = 1001;
String numberStr = "学号:";
String info = numberStr + number; //+:连接运算
boolean b1 =true;
String info2 = info + b1;
System.out.println(info2);
System.out.println(info);

//练习1
char c = 'a';
int num = 10;
String str = "Hello";
System.out.println(c + num + str); //107Hello
System.out.println(c + str + num); //aHello10
System.out.println(c + (num + str)); //a10Hello
System.out.println((c + num) + str); //107Hello
System.out.println(str + num + c); //Hello10a

//练习2
//* *
System.out.println("* *");
System.out.println('*'+"\t"+'*');
}
}

运行结果:

运行结果

7.四种进制

(1).二进制(binary):以0b或者0B开头
(2).十进制(decimal)
(3).八进制(octal):以数字0开头
(4).十六进制(hex):以0x或者0X开头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class System1 {

public static void main(String[] args) {
// TODO Auto-generated method stub
int num1 = 0b110;
int num2 = 110;
int num3 = 0127;
int num4 = 0x110A;

System.out.println("num1 = "+num1);
System.out.println("num2 = "+num2);
System.out.println("num3 = "+num3);
System.out.println("num4 = "+num4);

}

}

补充组原知识:原码、反码、补码

原码、反码、补码

8.运算符

(1).算术运算符

运算符

取模运算的结果正负性与被模数保持一致

(2).逻辑运算符

逻辑运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
* 逻辑运算符:
* & && | || ! ^
*
* 说明:
* 1.逻辑运算符操作的都是boolean型的变量
*
*
* */

package logic;

public class LogicTest {

public static void main(String[] args) {
// TODO Auto-generated method stub
// 区分逻辑& 与 &&
//相同点1:&与&&的运算结果相同
//相同点2:当符号昨天是true时,二者都会执行符号右边的运算
//不同点:当符号左边是false时,&会继续执行符号右边的运算。而&&不再执行
boolean b1 = true;
b1 = false;
int num1 = 10;
if(b1 & (num1++ > 0)) {
System.out.println("我现在在北京");
}
else {
System.out.println("我现在在南京");
}

System.out.println("num1 = " + num1);

boolean b2 = true;
b2 = false;
int num2 = 10;
if(b2 && (num2++ > 0)) { //短路与,因为b2已经是false了,不管&&后面是真是假,最后整体肯定为假,所以就不执行后面的语句了,所以num2++就没有执行,直接跳过了,即被短路了
System.out.println("我现在在北京");
}
else {
System.out.println("我现在在南京");
}

System.out.println("num2 = " + num2);


//区分|与||
//想同点1:|与||运算结果是下昂痛的
//相同点2:当符号左边是false时,二者都会执行符号右边的运算
//不同点:当符号左边是true时,|继续执行符号右边的运算,而||不再执行

boolean b3 =false;
b3 = true;
int num3 = 10;
if(b3 | (num3++ >0)) {
System.out.println("我现在在北京");
}
else {
System.out.println("我现在在南京");
}

System.out.println("num3 = "+ num3);


boolean b4 =false;
b4 = true;
int num4 = 10;
if(b4 || (num4++ >0)) {
System.out.println("我现在在北京");
}
else {
System.out.println("我现在在南京");
}

System.out.println("num4 = "+ num4);
}


}

(3).位运算符

位运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
* 1.位运算符操作的都是整形的数据
* 2.<<:在一定范围内,每向左移一位,相当于乘2,末尾补0
* >>:在一定范围内,每向右移一位,相当于除以2,开头是0就补0,开头是1就补1
* >>>:在一定范围内,每向右移一位,相当于除以2,开头补0
* */

package bit_operator;

public class Bit_operator {

public static void main(String[] args) {
// TODO Auto-generated method stub
int i =21;
//左移两位,就是乘2的2次方,在原本二进制后面加上了两个0
System.out.println("i << 2 :" + (i << 2));
//左移三位,就是乘2的3次方,在原本二进制后面加上了三个0
System.out.println("i << 3 :" + (i << 3));

//&是与运算,将每位上的数进行与操作:两者都为1,结果为1,其余都为0
//|是或运算,将每位上的数进行或操作:二者有一个为1,结果为1
//^是异或运算,将每位上的数进行异或操作:二者不一致的时候,结果为1,其余为0
int m = 12;
int n =5;
System.out.println("m & n :" + (m & n));
System.out.println("m | n :" + (m | n));
System.out.println("m ^ n :" + (m ^ n));
}

}

(4).运算符的优先级

运算符的优先级

9.Scanner类的使用

具体的实现步骤:

1.导包:import java.util.Scanner;
2.Scanner的实例化
3.调用Scanner类的相关方法,来获取指定类型的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package scanner;

import java.util.Scanner;
public class Scanner1 {

public static void main(String[] args) {
// Scanner的实例化
Scanner scan = new Scanner(System.in);
//调用nextInt()方法,来获取键盘输入的int型变量
int num = scan.nextInt();
//获取其他变量的输入方法:
//String类型:next()
//Double类型:nextDouble()
//Boolean类型:nextBoolean()
//对于char类型的获取没有提供相关的方法,故可以使用字符串的方法来获取
System.out.println(num);
}

}

10.分支结构(if-else, switch-case)

注意点:switch中的表达式,只能是如下的六种数据类型之一:
byte, short, char, int, 枚举类型, String

11.循环结构(for, do while, while)

(1).嵌套循环的应用:打印出100以内所有的质数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//100以内所有质数

package cycle1;
public class Cycle {

public static void main(String[] args) {
// TODO Auto-generated method stub
boolean isFlag = true; //用于记录i是否可以被除尽
for(int i=2;i<=100;i++) {
for(int j=2;j<i;j++) {
if(i%j==0) {
isFlag = false;
break;
}
}
if(isFlag==true) {
System.out.println(i);
}
isFlag = true; //重置isFlag的值,否则当isFlag为false时,上方的条件语句永远不会执行
}
}
}

对以上算法进行有优化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args){
long start = System.currentTimeMillis(); //获取程序刚开始运行时的时间戳
boolean isFlag = true; //用于记录i是否可以被除尽
label:for(int i=2;i<=10000;i++) {
for(int j=2;j<=Math.sqrt(i);j++) { //优化二:开方,调用Math.sqrt方法,需加上等号,最大的一个质数是97
// 开方后是9点多,所以9就是它的一个倍数,不需要再试更大的数
// 根据时间戳的结果,在优化一的基础上又变为了17ms,又更进一步缩短了程序的运行时间
if(i%j==0) {
isFlag = false;
break label; //break默认是结束最近的一层循环,但也可以指明跳出指定的循环,比如跳出外层循环
//在要跳出的指定循环前加上label:然后在break后面加上label就可以跳出label指定的循环
}
}
if(isFlag==true) {
System.out.println(i);
}
isFlag = true; //重置isFlag的值,否则当isFlag为false时,上方的条件语句永远不会执行
}
long end = System.currentTimeMillis(); //获取程序运行结束时的时间戳
System.out.println(end-start); //两个时间戳相减即可得到程序运行的时间
}

(2).小项目一-家庭收支管理系统

AccountController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package accountcon;
public class AccountController {
public static void main(String[] args) {
// TODO Auto-generated method stub
boolean isFlag = true;
//用于记录用户的收入和支出详情
String details = "";
//初始金额
int balance = 10000;
while(isFlag) {
System.out.println("----------家庭收支记账软件----------\n");
System.out.println(" 1.收支明细");
System.out.println(" 2.登记收入");
System.out.println(" 3.登记支出");
System.out.println(" 4.退 出\n");
System.out.println(" 请输入1-4来执行对应的功能");

//调用Utility文件中的方法,获取用户的选择
char selection = Utility.readMenuSelection();

switch(selection) {
//因为selection是char类型的,所以下面的1,2,3,4均需加上单引号
case '1' :
System.out.println("1.收支明细");
System.out.println("----------家庭收支记账软件----------\n");
System.out.println("收支\t账户金额\t收支金额\t说 明\n");
System.out.println(details);
System.out.println("-----------------------------------\n");
continue;
case '2' :
System.out.println("本次收入金额:");
int money = Utility.readNumber();
System.out.println("本次收入说明:");
String info = Utility.readString();

//处理余额balance
balance += money;

//处理details
details += "收入\t" + balance + "\t+" + money + "\t" + info + "\n";

System.out.println("--------------登记完成--------------\n");
continue;
case '3' :
System.out.println("本次支出金额:");
int moneyout = Utility.readNumber();
System.out.println("本次支出说明:");
String infoout = Utility.readString();

//处理balance
if(balance >= moneyout) {
balance -= moneyout;
}
else {
System.out.println("支付失败");
}

//处理deatils
details += "支出\t" + balance + "\t-" + moneyout + "\t" + infoout + "\n";

System.out.println("--------------登记完成--------------\\n");
continue;
case '4' :
System.out.println("确定要退出吗(Y/N)\n");
char isExit = Utility.readConfirmSelection();
if(isExit == 'Y') {
isFlag = false;
}
break;
}
}
}

}

Utility.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package accountcon; 
import java.util.Scanner;
/**
Utility工具类:
将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。
*/
public class Utility {
private static Scanner scanner = new Scanner(System.in);
/**
用于界面菜单的选择。该方法读取键盘,如果用户键入’1’-’4’中的任意字符,则方法返回。返回值为用户键入字符。
*/
public static char readMenuSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1);
c = str.charAt(0);
if (c != '1' && c != '2' && c != '3' && c != '4') {
System.out.print("选择错误,请重新输入:");
} else break;
}
return c;
}
/**
用于收入和支出金额的输入。该方法从键盘读取一个不超过4位长度的整数,并将其作为方法的返回值。
*/
public static int readNumber() {
int n;
for (; ; ) {
String str = readKeyBoard(4);
try {
n = Integer.parseInt(str);
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
用于收入和支出说明的输入。该方法从键盘读取一个不超过8位长度的字符串,并将其作为方法的返回值。
*/
public static String readString() {
String str = readKeyBoard(8);
return str;
}

/**
用于确认选择的输入。该方法从键盘读取‘Y’或’N’,并将其作为方法的返回值。
*/
public static char readConfirmSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1).toUpperCase();
c = str.charAt(0);
if (c == 'Y' || c == 'N') {
break;
} else {
System.out.print("选择错误,请重新输入:");
}
}
return c;
}


private static String readKeyBoard(int limit) {
String line = "";

while (scanner.hasNext()) {
line = scanner.nextLine();
if (line.length() < 1 || line.length() > limit) {
System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
continue;
}
break;
}

return line;
}
}

12.数组

数组属于引用数据类型,所以需要用new进行实例化,数组的元素可以是基本数据类型,也可以是引用数据类型。
创建数组对象会在内存中开辟一块连续的内存空间,而数组名引用的是这块连续空间的首地址。
数组一旦初始化完成,其长度就确定了,不可以更改。

1
2
3
4
5
6
7
8
9
//1.动态初始化
int[] arr1 = new int[3];
//2.静态初始化
int[] arr2 = new int[]{1,2,3};
// int[] arr2 = {1,2.3}; 简写或者说省略

String arr3 = new String[3];
//3.在初始化时未赋值,每个类型都会有一个默认值,例如
//整形默认为0,char型默认为0,String默认为null,boolean默认为false,浮点型默认为0.0

数组元素的默认初始化值
整型数组元素的默认初始化值:0
浮点型数组元素的默认初始化值:0.0
字符型数组元素的默认初始化值:0(或理解为’\u0000’)
boolean型数组元素的默认初始化值:false
引用数据类型数组元素的默认初始化值:null

一维数组的内存解析
Java中的内存结构是如何划分的?
主要关心JVM的运行时内存环境,将内存区域划分为5个部分:程序计数器、虚拟机栈、本地方法栈、堆、方法区
目前数组相关的内存结构: 比如 int[] arr = new int[]{1,2,3};
虚拟机栈:用于存放方法中声明的变量。比如:arr
堆:用于存放数组的实体(即数组中的所有元素)。比如:1,2.3

(1)二维数组

对于二维数组,可以简单理解为arr1作为另一个数组arr2的数组元素而存在。(套娃)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//1.动态初始化
int[][] arr = new int arr[11][3];
int[] arr1[] = new int arr1[11][3];
int arr2[][] = new int arr2[11][3];
//2.静态初始化
int [][] arr3 = new int arr3[][]{{1,2,3},{2,3,6},{7,8,9}};
//3.遍历二位数组
for(int i=0;i<arr.lenght;i++){
for(int j=0;j<arr[i].length;j++){
System.out.println(arr[i][j]+" ");
}
}
//4.二维数组的初始化默认值
System.out.println(arr);//是一个地址值
//如果是动态初始化,且内部元素未定义长度,则会返回null
System.out.println(arr[1]);//null

(2)数组操作

杨辉三角
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
public void test4(){
//1.声明并初始化二维数组
int[][] arr = new int[10][];
for(int i=1;i<=arr.length;i++) {
arr[i-1]=new int[i];
}

//2.二维数组赋值
for(int i=0;i<arr.length;i++) {
arr[i][0]=1;
arr[i][i]=1;
for(int j=0;j<=i;j++) {
if(i>1&&j>0&&j<i) {
arr[i][j]=arr[i-1][j-1]+arr[i-1][j];
}
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}

运行结果

数组反转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 @Test
public void test5(){
int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
//方法1
for (int i = 0;i < arr.length/2;i++){
//交换arr[i]与arr[arr.length - 1 -i]的位置
int temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 -i] = temp;
}
//方法2 (不推荐)
// int[] newArr = new int[arr.length];
// for (int i = arr.length - 1;i >= 0; i--){
// newArr[arr.length - 1 - i] = arr[i];
// }
// arr = newArr;
//遍历
for (int i = 0;i < arr.length;i++){
System.out.println(arr[i] + "\t");//987654321
}
}

}

(3)数组查找

顺序查找

顺序查找的时间复杂度为 O(N)

二分查找(数组有序)

二分查找的时间复杂度为 O(log N)
二分查找逻辑图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Test
public void test6(){
int[] arr = new int[]{0,9,4,5};
int target = 9;
boolean flag = false;
int head = 0;//默认的首索引
int end = arr.length - 1;//默认的尾索引
while(head <= end){
int middle = (head + end) / 2;
if (target == arr[middle]){
flag = true;
System.out.println("找到了," + target +"对应的位置是" + middle);
break;
} else if (target > arr[middle]) {
head = arr[middle] +1;
}else {
end = arr[middle] - 1;
}
}
if (!flag){
System.out.println("没找到" + target + "这个数");
}
}

(4)数组元素排序

十大排序算法

算法概述

衡量排序算法的优劣
1.时间复杂度:分析关键字的比较次数和记录的移动次数。
常见的算法时间复杂度由小到大依次是:O(1) < O(log 2N) < O(N) < O(Nlog 2N) < O(N²) < O(N³) <…< O(2ⁿ) < O(N!) <O(Nⁿ)
2.空间复杂度:分析排序算法中需要多少辅助内存。
3.稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。

冒泡排序(最经典)

思想:
每一次比较“相邻(位置相邻)”元素,如果它们不符合目标顺序,就交换它们,经过多轮比较,最终实现排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Test
public void test7(){
int[] arr = new int[]{11,31,9,66,99};

for (int i = 0;i < arr.length;i++){
System.out.print(arr[i] + "\t");
}
//冒泡
for (int i = 0;i < arr.length - 1;i++){
for (int j = 0;j < arr.length - 1 - i;j++){
if (arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}

}
System.out.println();
for (int i = 0;i < arr.length;i++){
System.out.print(arr[i] + "\t");
}

}
快速排序

思想:
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class QuickSort {
public static void quickSort(int[] arr,int low,int high){
int i,j,temp,t;
if(low>high){
return;
}
i=low;
j=high;
//temp就是基准位
temp = arr[low];

while (i<j) {
//先看右边,依次往左递减
while (temp<=arr[j]&&i<j) {
j--;
}
//再看左边,依次往右递增
while (temp>=arr[i]&&i<j) {
i++;
}
//如果满足条件则交换
if (i<j) {
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}

}
//最后将基准为与i和j相等位置的数字交换
arr[low] = arr[i];
arr[i] = temp;
//递归调用左半数组
quickSort(arr, low, j-1);
//递归调用右半数组
quickSort(arr, j+1, high);
}


public static void main(String[] args){
int[] arr = {10,7,2,4,7,62,3,4,2,1,8,9,19};
quickSort(arr, 0, arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}

(5)Arrays工具类

1.boolean equals(int[] a,int[] b): 比较两个数组的元素是否依次相等。

1
2
3
4
int[] arr1 = new int[]{1,2,3,4,5};
int[] arr2 = new int[]{1,2,3,4,5};
boolean isEquals = Arrays.equals(arr1,arr2);
System.out.println(isEquals);//true

2.String toString(int[] a): 输出数组元素信息

1
2
3
int[] arr1 = new int[]{1,2,3,4,5};
System.out.println(arr1);//[I@2aafb23c
System.out.println(Arrays.toString(arr1));//[1, 2, 3, 4, 5]

3.void fill(int[] a,int val): 将指定值填充到数组之中。

1
2
3
int[] arr1 = new int[]{1,2,3,4,5};
Arrays.fill(arr1,10);
System.out.println(Arrays.toString(arr1));//[10, 10, 10, 10, 10]

4.void sort(int[] a): 使用快速排序算法实现的排序

1
2
3
4
int[] arr2 = new int[]{2,1,4,5,3};
Arrays.sort(arr2);//快速排序
System.out.println(Arrays.toString(arr2));//[1, 2, 3, 4, 5]

5.int binarySearch(int[] a,int key): 二分查找(适用前提:数组必须有序)

1
2
3
4
int[] arr1 = new int[]{1,2,3,4,5};
int[] arr2 = new int[]{2,1,4,5,3};
int index = Arrays.binarySearch(arr1,4);
System.out.println(index);//3 ,若为负数则未找到

四、面向对象编程(基础)

1.什么是面向对象和面向过程?

面向对象(Object-Oriented) 是一种编程范式,它将程序设计看作是一组对象的集合,每个对象都可以接收消息、处理数据,并与其他对象进行交互。在面向对象编程中,程序由多个对象组成,每个对象都有自己的状态和行为。
面向过程(Procedural) 是一种以过程为中心的编程范式,它将程序视为一系列按照特定顺序执行的操作或函数调用。在面向过程编程中,程序由一系列函数或过程组成,这些函数按照特定的顺序依次执行。
2.面向对象和面向过程的区别?

1.1思维方式不同:面向对象强调对问题领域的抽象和建模,通过定义类和对象来描述问题的实体及其关系;而面向过程则更注重解决问题的步骤和流程。

2.2封装性不同:面向对象通过将数据和方法封装在对象内部,隐藏了内部实现细节,只暴露必要的接口给外部使用;而面向过程没有封装的概念,所有数据和方法都是公开的。

3.3复用性不同:面向对象通过继承和多态等机制提供了更好的代码复用性,可以通过继承现有类创建新的类,并重写或扩展其方法;而面向过程需要手动复制和粘贴代码来实现复用。

4.4可维护性不同:面向对象的代码结构清晰、模块化,易于理解和修改;而面向过程的代码往往是线性的,难以分割和组织。

5.5灵活性不同:面向对象的设计更加灵活,可以根据需求进行扩展和修改,而不会影响其他部分;而面向过程的设计较为僵硬,一旦需求变化,可能需要大量修改代码。

3.学习面向对象内容的三条主线:

Java类及类的成员
面向对象的特征:封装、继承、多态
其他关键字的使用:this、super、package、import、static、final、interface、abstract等

1.Java语言的基本元素:类和对象

1.1 类和对象概述

类(Class)和对象(Object)是面向对象的核心概念。
1.什么是类?
类:具有相同特征的事物的抽象描述,是抽象的、概念上的定义。
2.什么是对象?
对象:实际存在的该类实物的‘每个个体’,是具体的,因而也称为 实例。

1.2 类的成员概述

面向对象程序设计的重点是类的设计
类的设计,其实就是类的成员的设计

类,是一组相关属性行为的集合,这也是类最基本的两个成员。
属性:该类实物的状态信息。对应类中的成员变量
成员变量<=>属性<=>Field
行为:该类实物要做什么操作,或者给予事物的状态能做什么,对应类中的成员方法
(成员)方法<=>函数<=>Method

类的实例化:

等价描述:类的实例化<=>创建类的对象<=>创建类的实例
格式:类类型 对象名 = 通过new创建的对象实体
举例:Phone p1 = new Phone()

面向对象完成具体功能的操作三步骤

步骤1:创建类,并设计类的内部成员(属性、方法).
步骤2:创建类的对象,比如:Phone p1 = new Phone();.
步骤3:通过对象,调用其内部声明的属性或方法,完成相关功能.

五、面向对象编程(进阶)

六、面向对象编程(高级)