什么是计算机
- Computer:全称电子计算机,俗称电脑。
- 能够按照 程序 运行,自动、高速处理海量数据的现代化智能电子设备。
- 由 硬件 和 软件 所组成
- 常见的形式有台式计算机。笔记本计算机、大型计算机等。
- 广泛应用在:科学计算,数据处理,自动控制,计算机辅助设计,人工智能,网络等领域
计算机硬件
- 一些物理装置按系统结构的要求构成一个有机整体为计算机软件运行提供物质基础。
- 计算机硬件组成
- CPU
- 主板
- 内存
- 电源、主机箱
- 硬盘
- 显卡
- 键盘、鼠标
- 显示器
- 等…
计算机软件
- 计算机软件可以使计算机按照事先预定好的顺序完成特定的功能
- 计算机软件按照其功能划分为 系统软件 与 应用软件
- 系统软件:
- DOS(Disk Operating System),Windows,Linux,Mac,Android,iOS
- 应用软件
- WPS,QQ,微信,英雄联盟,绝地求生…
- 软件、开发、软件开发
- 人机交互(图形化界面,命令行)
DOS命令
- 常见DOS命令
- 盘符切换 - C:
- 查看当前目录下的所有文件 - dir
- 切换目录 - cd (change directory)
- 创建目录文件 - md
- 清理屏幕 - cls(clear screen)
- 删除文件 - del
- 删除文件夹 - rd
- 退出终端 - exit
- 查看电脑的IP - ipconfig
- ping命令 - ping www.baidu.com
- calc 计算器
- mspaint 画图
- notepad 记事本
计算机语言发展史
第一代语言
- 机器语言
- 我们都知道计算机的基本计算方式都是基于二进制的方式。
- 二进制:010111001010110010110100
- 这种代码是直接输入给计算机使用的,不经过任何的转换!
第二代语言
- 汇编语言
- 解决人类无法读机器语言的问题
- 指令代替二进制
- 目前应用:
- 逆向工程
- 机器人
- 病毒
- …
codesg seqment
start:
mov ax, 0123h ; 寄存器送入值
mov bx, 0457h
add ax, bx ; ax + bx 寄存器值相加
add ax, ax ; 算 ax 的平方
mov ax, 4c00h
int 21h ; 程序结束返回
codesg ends
end start ; 指定程序入口标号为 start
第三代语言
- 摩尔定律
- 当价格不变时,集成电路上可容纳的晶体管数目,约每隔18个月便会增加一倍,性能也将提升一倍。换言之,每一美元所能买到的电脑性能,将每隔18个月翻两倍以上
- 高级语言
- 大体上分为:面向过程和面向对象两大类。
- C语言是典型的面向过程的语言。C++、JAVA是典型的面向对象的语言。
- 聊聊各种语言:
- C语言
- C++语言
- JAVA语言
- C#语言
- Python、PHP、JavaScript
- …
Java帝国的诞生
C & C++
- 1972年C诞生
- 贴近硬件,运行极快,效率极高
- 操作系统,编译器,数据库,网络系统等
- 指针和内存管理
- 1982年C++诞生
- 面向对象
- 兼容C
- 图形领域、游戏等
反抗
- 我们要建立一个新的语言:
- 语法有点像C
- 没有指针
- 没有内存管理
- 真正的可移植性,编写一次,到处运行
- 面向对象
- 类型安全
- 高质量的类库
- …
Java初生
- 1995年的网页简单而枯燥,缺乏互动性。
- 图形界面的程序(Applet)
- Bill Gates说:这是迄今为止设计的最好的语言!
- Java 2 标准版(J2SE):去占领桌面
- Java 2 移动版(J2ME):去占领手机
- Java 2 企业版(J2EE):去占领服务器
- 大量的巨头加入
Java发展
Java 三高 ,高并发 ,高可用 ,高性能
- 他们基于Java开发了巨多的平台,系统,工具
- 构建工具:Ant,Maven,Jekins
- 应用服务器:Tomcat,Jetty,Jboss,Websphere,weblogic
- Web开发:Struts,Spring,Hibernate,myBatis
- 开发工具:Eclipse,Netbean,intellij idea,Jbuilder
- …
- 2006:Hadoop(大数据领域)
- 2008:Android(手机端)
- 一个伟大的帝国诞生了!
Java特性和优势
- 简单性
- 面向对象
- 可移植性
- 高性能
- 分布式
- 动态性
- 多线程
- 安全性
- 健壮性
- 思考:Java为什么能够成功
Java三大版本
- Write Once、Run Anywhere
- JavaSE:标准版(桌面程序,控制台开发…)
JavaME:嵌入式开发(手机,小家电…)- JavaEE:E企业级开发(web端,服务器开发…)
JDK、JRE、JVM
- JDK:Java Development Kit
- JRE:Java Runtime Environment
- JVM:JAVA Virtual Machine
Java开发环境搭建
-
安装JDK
- 百度搜索JDK8,找到下载地址
- 同意协议
- 下载电脑对应的版本
- 双击安装JDK
- 记住安装的路径
- 配置环境变量
- 我的电脑 - 右键 - 属性
- 环境变量 - JAVA_HOME
- 配置path变量
- 测试JDK是否安装成功
- 打开cmd
- java -version
-
卸载JDK
- 删除Java的安装目录
- 删除JAVA_HOME
- 删除path下关于Java的目录
- java -version
-
HelloWorld
- 随便新建一个文件夹,存放代码
- 新建一个Java文件
- 文件后缀名为.java
- Hello.java
- 编写代码
public class Hello { public static void main(String[] args) { System.out.print("Hello World!"); } }
- 编译javac java文件,回生成一个class文件
- 运行class文件,java class文件
Java程序运行机制
- 编译型
- 解释型
- 程序运行机制
- 源程序(*.java文件)- Java编译器 - 字节码( *.class文件)- 类装载器 - 字节码校验器 - 解释器 - 操作系统平台
Java基础语法
- 注释、标识符、关键字
- 数据类型
- 类型转换
- 变量、常量
- 运算符
- 包机制、JavaDoc
注释
- 平时我们编写代码,在代码量比较少的时候,我们还可以看懂自己写的,但是当项目结构一旦复杂起来,我们就需要用到注释了。
- 注释并不会被执行,是给我们写代码的人看的
- 书写注释是一个非常好的习惯
- Java中的注释有三种:
- 单行注释 //
- 多行注释 /* */
- 文档注释
标识符
- 关键字
abstract | assert | boolean | break | byte |
---|---|---|---|---|
case | cath | char | class | const |
continue | default | do | double | else |
enum | extends | final | finally | float |
for | goto | if | implements | import |
instanceof | int | interface | long | native |
new | package | private | protected | public |
return | strictfp | short | static | super |
switch | synchronized | this | throw | throws |
transient | try | void | volatile | while |
- Java所有的组成部分都需要名字。类名、变量以及方法名都被称为标识符
标识符注意点
- 所有的标识符都应该以字母( A-Z 或者 a-z ),美元符( $ ),或者下划线( _ )开始
- 首字符之后可以是字母( A-Z 或者 a-z ),美元符( $ ),或者下划线( _ )或数字的任何字符组合
- 不能使用关键字作为变量名或方法名。
- 标识符是 大小写敏感的
- 合法标识符举例:age,$salary,_value,_1_value
- 非法标识符举例:123abc,-salary,#abc
- 可以使用中文命名,但是一般不建议这样去使用,也不建议使用拼音,很low
数据类型
- 强类型语言
- 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
- 弱类型语言
- Java的数据类型分为两大类
- 基本类型(primitive types)
- 引用类型(reference type)
- 基本类型(primitive types)
什么是字节
- 位(bit):是计算机 内部数据 存储的最小单位,11001100是一个八位二进制数。
- 字节(byte):是计算机中 数据处理 的基本单位,习惯上用大写B来表示。
- 1B(byte,字节)= 8bit(位)
- 字符:是指计算机中使用的字母,数字,字和符号
- 1bit表示1位
- 1byte表示一个字节 1B=8b
- 1024B = 1KB
- 1024KB = 1M
- 1024M = 1G
数据类型扩展
// 整数 进制:二进制0b 十进制 八进制0 十六进制0x
int i = 10;
int i2 = 010; // 八进制
int i3 = 0x10; // 十六进制 0~9 A-F
System.out.println(i); // 10
System.out.println(i2); // 8
System.out.println(i3); // 16
// 浮点数 银行业务怎么表示?钱
// BigDecimal 数学工具类
// flaot 有限 离散 舍入误差 大约 接近但不等于
float f = 0.1f;
double d = 1.0 / 10;
System.out.println(f == d); // false
System.out.println(f); // 0.1
System.out.println(d); // 0.1
float f1 = 12312312312312f;
float f2 = f1 + 1;
System.out.println(f1 == f2); // true
// 字符
char c1 = 'a';
char c2 = '中';
System.out.println(c1); // a
System.out.println(c2); // 中
System.out.println((int) c1); // 97
System.out.println((int) c2); // 20013
// 所有的字符本质还是数字
// 编码 Unicode表:97 = a 2字节 0 - 65536 Excel(2的16次方 = 65536)
// U0000 UFFFF
char c3 = '\u0061';
System.out.println(c3); // a
// 转义字符
System.out.println("Hello\tWorld"); // Hello World
String sa = new String("hello world");
String sb = new String("hello world");
System.out.println(sa == sb); // false
String sc = "hello world";
String sd = "hello world";
System.out.println(sc == sd); // true
// 布尔值
boolean flag = true;
if(flag == true) {} // 新手
if(flag) {} // 老手 Less is More! 代码要精简易读
类型转换
- 由于Java是强类型语言,所以要进行有些运算的时候,需要用到类型转换。
- byte,short,char -> int -> long -> float -> double
- 运算中,不同类型的数据先转化为同一类型,然后进行运算。
- 强制类型转换
- 自动类型转换
int i = 128;
byte b = (byte) i; // 内存溢出
// 强制转换 (类型)变量名 高--低
// 自动转换 低--高
System.out.println(i); // 128
System.out.println(b); // -128
/*
* 注意点:
* 1. 不能对布尔值进行转换
* 2. 不能把对象类型转换为不相干的类型
* 3. 在把高容量转换到低容量的时候,强制转换
* 4. 转换的时候可能存在内存溢出,或者精度问题!
*/
System.out.println((int) 23.7); // 23
System.out.println((int) -45.89f); // -45
char c = 'a';
int d = c + 1;
System.out.println(d); // 98
System.out.println((char) d); // b
// 操作比较大的数的时候,注意处问题
// JDK7新特性 数字之间可以用下划线分割
int money = 10_0000_0000;
System.out.println(money); // 1000000000
int years = 20;
int total = money * years;
System.out.println(total); // -1474836480 计算的时候溢出了
long total2 = money * years; // 默认是int,转换之前已经存在问题了
System.out.println(total2); // -1474836480
long total3 = money * ((long) years); // 先把一个数转换为long
System.out.println(total3); // 20000000000
变量
- 变量是什么:就是可以变化的量!
- Java是一种强类型语言,每个变量都必须声明其类型。
- Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和 作用域
type varName = value;
// 数据类型 变量名 = 值; 可以使用逗号隔开来声明多个同类型变量。
- 注意事项:
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型。
- 变量名必须是合法的标识符。
- 变量声明是一条完整的语句,因此每一个声明都必须已分号结束
变量作用域
- 类变量
- 实例变量
- 局部变量
public class Variable {
static int allClicks = 0; // 类变量
String str = "hello world"; // 实例变量
public void method() {
int i = 0; // 局部变量
}
}
public class DBOperate {
// 类变量 static
static double salary = 25000;
// 属性:变量
// 实例变量:从属于对象 如果不自行初始化,这个类型的默认值 0 0.0
// 布尔值:默认是false
// 除了基本类型:其余的默认值都是null
String name;
int age;
// main方法
public static void main(String[] args) {
// 局部变量:必须声明和初始化值
int i = 10;
System.out.println(i); // 10
// 变量类型 变量名字 = new DBOperate();
DBOperate DBOperate = new DBOperate();
System.out.println(DBOperate.age); // 0
System.out.println(DBOperate.name); // null
// 类变量 static
System.out.println(salary); // 25000.0
}
// 其他方法
public void add() {
// System.out.println(i);
}
}
常量
- 常量(Constant):初始化(initialize)后不能再改变的值。
- 所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
final 常量名 = 值;
final double PI = 3.14;
- 常量名一般使用大写字符。
// 修饰符:不存在先后顺序
static final double PI = 3.14;
public static void main(String[] args) {
System.out.println(PI); // 3.14
}
变量的命名规范
- 所有变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则:monthSalary 除了第一个单词以外,后面的单词首字母大写 lastName
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则:Man,GoodMan
- 方法名:首字母小写和驼峰原则:run(),runRun()
运算符
- Java语言支持如下运算符:优先级()
- 算术运算符:+,-,*,/,%,++,–
- 赋值运算符:=
- 关系运算符:>,<,>=,<=,==,!=,instanceof
- 逻辑运算符:&&,||,!
- 位运算符:&,|,^,~,>>,<<,>>>(了解)
- 条件运算符:? :
- 扩展赋值运算符:+=,-=,*=,/=
// 二元运算符
int a = 10;
int b = 20;
System.out.println(a + b); // 30
System.out.println(a - b); // -10
System.out.println(a * b); // 200
System.out.println(a / (double) b); // 0.5
long a = 123123123123123L;
int b = 123;
short c = 10;
byte d = 8;
System.out.println(a + b + c + d); // long
System.out.println(b + c + d); // int
System.out.println(c + d); // int
// 关系运算符返回的结构:正确,错误 布尔值
// if
int a = 10;
int b = 20;
int c = 21;
// 取余,模运算
System.out.println(c % a); // c/a 21/10=2...1
System.out.println(a > b); // false
System.out.println(a < b); // true
System.out.println(a == b); // false
System.out.println(a != b); // true
// ++ -- 自增 自减 一元运算符
int a = 3;
int b = a++; // 执行完这行代码后,先给b赋值,再自增
int c = ++a; // 执行完这行代码前,先自增,再给b赋值
System.out.println(a); // 5
System.out.println(b); // 3
System.out.println(c); // 5
// 幂运算 2^3 2*2*2 = 8 很多运算,我们会使用一些工具类操作
double pow = Math.pow(2, 3);
System.out.println(pow); // 8.0
// 逻辑运算符
// 与(and) 或(or) 非(取反)
boolean a = true;
boolean b = false;
System.out.println("a && b:" + (a && b)); // 逻辑与运算:两个变量都为真,结果为true
System.out.println("a || b:" + (a || b)); // 逻辑或运算:两个变量有一个为真,则结果才为true
System.out.println("!(a&&b):" + (!(a && b))); // 如果是真,则变为假,如果是假则变为真
// 短路运算
int c = 5;
boolean d = (c < 4) && (c++ < 4);
System.out.println(d); // false
System.out.println(c); // 5
/*
* A = 0011 1100 B = 0000 1101
*
* A & B 0000 1100 A | B 0011 1101 A ^ B 0011 0001 ~B 1111 0010
*
* 2*8 = 16
* 效率极高!
* << 左移 *2
* >> 右移 /2
*
* 0000 0000 0
* 0000 0001 1
* 0000 0010 2
* 0000 0011 3
* 0000 0100 4
* 0000 1000 8
* 0001 0000 16
*/
System.out.println(2 << 3); // 16
int a = 10;
int b = 20;
a += b; // a = a + b;
a -= b; // a = a - b;
System.out.println(a); // 10
// 字符串连接符 +,String
System.out.println(a + b); // 30
System.out.println("" + a + b); // 1020
System.out.println(a + b + ""); // 30
// 三元运算符
// x ? y : z
// 如果x==true,则结果为y,否则结果为z
int score = 80;
String type = score < 60 ? "不及格" : "及格";
// if
System.out.println(type); // 及格
包机制
- 为了更好地组织类,Java提供了包机制,用于区别类名的命名空间。
- 一般利用公司域名倒置作为包名; www.baidu.com con.baidu.wwww
- 为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用 “import” 语句可完成此功能
JavaDoc
- javadoc命令是用来生成自己API文档的
- 参数信息
- @author 作者名
- @version 版本号
- @since 指明需要最早使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异抛出情况
package test9;
/**
* @author bing
* @version 1.0
* @since 1.8
*/
public class Doc {
String name;
/**
* @author bing
* @param name
* @return
* @throws Exception
*/
public String test(String name) throws Exception {
return name;
}
}
javadoc -encoding UTF-8 -charset UTF-8 Doc.java
Java流程控制
- 用户交互Scanner
- 顺序结构
- 选择结构
- 循环结构
- break & continue
- 练习
Scanner对象
- 之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入。java.util.Scanner 是Java5的新特性,我们可以通过 Scanner类来获取用户的输入。
- 基本语法:
Scanner s = new Scanner(System.in);
- 通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据。
package test9;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
// 创建一个扫描器对象,用于接收键盘数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方法接收:");
// 判断用户有没有输入字符串
if (scanner.hasNext()) {
// 使用next方法接收
String str = scanner.next(); // 程序会等待用户输入完毕
System.out.println("输出的内容为:" + str);
}
// 凡是属于IO流的类如果不关闭会一直占用资源,要养成好习惯用完就关掉
scanner.close();
}
}
package test9;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
// 从键盘接收数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine方式接收:");
// 判断是否还有输入
if (scanner.hasNextLine()) {
String str = scanner.nextLine();
System.out.println("输出的内容为:" + str);
}
scanner.close();
}
}
- next():
- 一定要读取到有效字符后才可以结束输入。
- 对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
- next() 不能得到带有空格的字符串。
- nextLine():
- 以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
- 可以获得空白。
package test9;
import java.util.Scanner;
public class Demo03 {
public static void main(String[] args) {
// 从键盘接收数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入数据:");
String str = scanner.nextLine();
System.out.println("输出的内容为:" + str);
scanner.close();
}
}
package test9;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 从键盘接收数据
int i = 0;
float f = 0.0f;
System.out.println("请输入整数:");
// 如果...那么
if (scanner.hasNextInt()) {
i = scanner.nextInt();
System.out.println("整数数据:" + i);
} else {
System.out.println("输入的不是整数数据!");
}
// 如果...那么
if (scanner.hasNextFloat()) {
f = scanner.nextFloat();
System.out.println("小数数据" + f);
} else {
System.out.println("输入的不是小数数据!");
}
scanner.close();
}
}
package test9;
import java.util.Scanner;
public class Demo05 {
public static void main(String[] args) {
// 我们可以输入多个数字,并求其总和平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果。
Scanner scanner = new Scanner(System.in);
// 和
double sum = 0;
// 计算输入了多少个数字
int m = 0;
// 通过循环判断是否还有输入,并在里面对每一次进行求和和统计
while (scanner.hasNextDouble()) {
double x = scanner.nextDouble();
m++; // m = m + 1
sum = sum + x;
System.out.println("你输入了第" + m + "个数据,然后当前结果sum=" + sum);
}
System.out.println(m + "个数的和为:" + sum);
System.out.println(m + "个数的平均值是:" + (sum / m));
scanner.close();
}
}
顺序结构
- Java的基本结构就是顺序将IE狗,除非特别指明,否则就按照顺序一句一句执行。
- 顺序结构是最简单的算法结构。
- 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。
选择结构
- if单选择结构
- if双选择结构
- if多选择结构
- 嵌套的if结构
- switch多选择结构
if单选择结构
- 我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
- 语法:
if(布尔表达式){ // 如果布尔表达式为true将执行的语句 }
```java
import java.util.Scanner;
public class IfDemo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容:");
String s = scanner.nextLine();
// equals 判断字符串是否相等
if (s.equals("Hello")) {
System.out.println(s);
}
System.out.println("End");
scanner.close();
}
}
if双选择结构
- 那现在有个需求,公司要收购一个软件,成功了,给人支付100万元,失败了,自己找人开发。这样的需求用一个if就搞不定了,我们需要有两个判断,需要一个双选择结构,所以就有了if-else结构。
- 语法:
if(布尔表达式){ // 如果布尔表达式的值为true }else { // 如果布尔表达式的值为false }
import java.util.Scanner;
public class IfDemo02 {
public static void main(String[] args) {
// 考试分数大于60就是及格,小于60分数不及格。
Scanner scanner = new Scanner(System.in);
System.out.println("请输入成绩:");
int score = scanner.nextInt();
if (score > 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
scanner.close();
}
}
if多选择结构
- 我们发现刚才的代码不符合实际情况,真实的情况还可能存在ABCD,存在区间多级判断,比如90-100就是A,80-90就是B等等,在生活中我们很多时候的选择也不仅仅只有两个,所以我们需要一个多选择结构来处理这类问题!
- 语法:
if(布尔表达式1){ // 如果布尔表达式1的值为true执行代码 }else if(布尔表达式2) { // 如果布尔表达式2的值为true执行代码 } else if(布尔表达式3) { // 如果布尔表达式3的值为true执行代码 }else { // 如果以上布尔表达式都不为true执行代码 }
import java.util.Scanner;
public class IfDemo03 {
public static void main(String[] args) {
// 考试分数大于60就是及格,小于60分数不及格。
Scanner scanner = new Scanner(System.in);
System.out.println("请输入成绩:");
int score = scanner.nextInt();
if (score == 100) {
System.out.println("恭喜满分");
} else if (score < 100 && score >= 90) {
System.out.println("A级");
} else if (score < 90 && score >= 80) {
System.out.println("B级");
} else if (score < 80 && score >= 70) {
System.out.println("C级");
} else if (score < 70 && score >= 60) {
System.out.println("D级");
} else if (score < 60 && score >= 0) {
System.out.println("不及格");
} else {
System.out.println("成绩不合法");
}
scanner.close();
}
}
嵌套的if结构
- 使用嵌套的if-else语句是合法的,也就是说你可以在另一个if或者else if语句中使用if或者else if语句。你可以像if语句一样嵌套else if…else。
- 语法:
if(布尔表达式1){ // 如果布尔表达式1的值为true执行代码 if(布尔表达式2){ // 如果布尔表达式2的值为true执行代码 } }
switch多选择结构
- 多选择结构还有一个实现方式就是switch case语句。
- switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
- switch语句中的变量类型可以是:
- byte、short、int或者char
- 从JavaSE7开始 switch支持字符串String类型了
- 同时case标签必须为字符串常量或字面量。
switch(expression) {
case value:
// 语句
break; // 可选
case value:
// 语句
break; // 可选
// 可以有任意数量的case语句
default: // 可选
// 语句
}
public class SwitchDemo01 {
public static void main(String[] args) {
// case穿透 switch匹配一个具体的值
char grade = 'C';
switch (grade) {
case 'A':
System.out.println("优秀");
break; // 可选
case 'B':
System.out.println("良好");
break;
case 'C':
System.out.println("及格");
break;
case 'D':
System.out.println("再接再厉");
break;
case 'E':
System.out.println("挂科");
break;
default:
System.out.println("未知等级");
}
}
}
public class SwitchDemo02 {
public static void main(String[] args) {
// 字符的本质还是数字
// 反编译 java---class(字节码文件)---反编译(IDEA)
String name = "冰冰";
switch (name) {
case "bingbing":
System.out.println("bingbing");
break;
case "冰冰":
System.out.println("冰冰");
break;
default:
System.out.println("弄啥嘞!");
}
}
}
循环结构
- while 循环
- do…while 循环
- for 循环
- 在Java5种引入了一种主要i用于数组的增强型for循环。
while循环
- while是最基本的循环,它的结构为:
while(布尔表达式) { // 循环内容、 }
- 只要布尔表达式为true,循环就会一直执行下去。
- 我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环。
- 少部分情况需要循环一直执行,比如服务器的请求响应监听等。
- 循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死崩溃!
public class WhileDemo01 {
public static void main(String[] args) {
// 输出1~100
int i = 0;
while (i < 100) {
i++;
System.out.println(i);
}
int i = 1;
while (i <= 100) {
System.out.println(i);
i++;
}
}
}
public class WhileDemo02 {
public static void main(String[] args) {
// 死循环
while(true) {
// 等待客户端连接
// 定时检查
// ...
}
}
}
public class WhileDemo03 {
public static void main(String[] args) {
// 计算1+2+3+...+100 = ?
int i = 0;
int sum = 0;
while (i <= 100) {
sum = sum + i;
i++;
}
System.out.println(sum); // 5050
System.out.println(i); // 101
int i = 0;
int sum = 0;
while (i < 100) {
i++;
sum = sum + i;
}
System.out.println(sum); // 5050
System.out.println(i); // 100
}
}
do…while 循环
- 对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
- do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
do { // 代码语句 }while(布尔表达式);
- while和do-while的区别:
- while先判断后执行,do…while是先执行后判断!
- do…while总是保证循环体会被至少执行一次!这是他们的主要差别。
public class DoWhileDemo01 {
public static void main(String[] args) {
int i = 0;
int sum = 0;
do {
sum += i;
i++;
} while (i <= 100);
System.out.println(sum);
}
}
public class DoWhileDemo02 {
public static void main(String[] args) {
int a = 0;
while (a < 0) {
System.out.println(a);
a++;
}
System.out.println("===");
do {
System.out.println(a); // 0
a++;
} while (a < 0);
}
}
for循环
- 虽然所有循环结构都可以用while或者do…while表示,但Java提供了另一种语句 - for循环,使一些循环结构变得更加简单。
- for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构。
- for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化; 布尔表达式; 更新) {
// 代码语句
}
public class ForDemo01 {
public static void main(String[] args) {
int a = 1; // 初始化条件
while (a <= 100) { // 条件判断
System.out.println(a); // 循环体
a += 2; // 迭代
}
System.out.println("while循环结束!");
// 初始化 条件判断 迭代
for (int i = 1; i <= 100; i += 2) {
System.out.println(i);
}
System.out.println("for循环结束!");
/*
* 关于for循环有以下几点说明:
* 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
* 然后,检测布尔表达式的值。如果是true,循环体被执行。如果为false,循环终止。
* 开始执行循环体后面的语句。执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)。
* 再次检测布尔表达式,循环执行上面的过程。
*/
// 死循环
for (;;) {
}
}
}
- 练习1:计算0到00之间的奇数和偶数的和
- 练习2:用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
- 练习3:打印九九乘法表
public class ForDemo02 {
public static void main(String[] args) {
// 练习1:计算0到00之间的奇数和偶数的和
int oddSum = 0;
int evenSum = 0;
for (int i = 0; i <= 100; i++) {
if (i % 2 != 0) { // 奇数
oddSum += i; // oddSum = oddSum + i;
} else { // 偶数
evenSum += i;
}
}
System.out.println("奇数的和:" + oddSum); // 2500
System.out.println("偶数的和:" + evenSum); // 2550
}
}
public class ForDemo03 {
public static void main(String[] args) {
// 练习2:用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
for (int i = 1; i <= 1000; i++) {
if (i % 5 == 0) {
System.out.print(i + "\t");
}
if (i % (5 * 3) == 0) { // 换行
System.out.println();
}
}
}
}
public class ForDemo04 {
public static void main(String[] args) {
// 练习3:打印九九乘法表
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(i + "*" + j + "=" + (i * j) + "\t");
}
System.out.println();
}
}
}
增强for循环
- 这里我们先只是见一面,做个了解,之后数组我们重点使用
- Java5 引入了一种主要用于数组或集合的增强型for循环
- Java增强了for循环语法格式如下:
for( 声明语句 : 表达式 ){ // 代码句子 }
- 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
public class ForDemo05 {
public static void main(String[] args) {
int[] numbers = { 10, 20, 30, 40, 50 }; // 定义了一个数组
for (int i = 0; i < 5; i++) {
System.out.println(numbers[i]); // 10 20 30 40 50
}
System.out.println("===");
// 遍历数组的元素
for (int x : numbers) {
System.out.println(x); // 10 20 30 40 50
}
}
}
break continue
- break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
- continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
- 关于goto关键字
- goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto,然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子- - -带标签的break和continue
- “标签” 是指后面跟一个冒号的标识符,例如:label:
- 对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
public class BreakDemo {
public static void main(String[] args) {
int i = 0;
while (i < 100) {
i++;
System.out.println(i);
if (i == 30) {
break;
}
}
System.out.println("123");
}
}
public class ContinueDemo {
public static void main(String[] args) {
int i = 0;
while (i < 100) {
i++;
if (i % 10 == 0) {
System.out.println();
continue;
}
System.out.print(i + "\t");
}
}
}
流程控制练习
public class TestDemo {
public static void main(String[] args) {
// 打印三角形 5行
for (int i = 1; i <= 5; i++) {
for (int j = 4; j >= i; j--) {
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
for (int j = 1; j < i; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
Java方法详解
- 何谓方法
- 方法的定义及调用
- 方法重载
- 命令行传参
- 可变参数
- 递归
什么是方法?
- System.out.println(),那么它是什么呢?类.对象.方法
- Java方法是语句的集合,它们在一起执行一个功能。
- 方法时解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他方法被引用
- 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展。
- 回顾:方法的命名规则?
public class Demo01 {
// main方法
public static void main(String[] args) {
// 实际参数:实际调用传递给它的参数
int sum = add(1, 2);
System.out.println(sum);
test();
}
// 加法
// 形式参数,用来定义作用的
public static int add(int a, int b) {
return a + b;
}
public static void test() {
for (int i = 1; i <= 1000; i++) {
if (i % 5 == 0) {
System.out.print(i + "\t");
}
if (i % (5 * 3) == 0) { // 换行
System.out.println();
}
}
}
}
方法的定义
- Java的方法类似于其他语言的函数,是一段 用来完成特定功能的代码片段,一般情况下,定义一个方法包含一下语法:
- 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
修饰符 返回值类型 方法名(参数类型 参数名) { ... 方法体 ... return 返回值; }
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
- 方法体:方法体包含具体的语句,定义该方法的功能。
方法调用
- 调用方法:对象名.方法名(参数列表)
- Java支持两种调用方法的方式,根据方法是否返回值来选择
- 当方法返回一个值的时候,方法调用通常当做一个值。例如:
int larger = max(30, 40);
- 如果方法返回值是void,方法调用一定是一条语句。
System.out.println("Hello Java!");
- 了解:值传递 和 引用传递
public class Demo02 {
public static void main(String[] args) {
int max = max(20, 20);
System.out.println(max);
}
// 比大小
public static int max(int num1, int num2) {
int result = 0;
if (num1 == num2) {
System.out.println("num1 == num2");
return num1; // 终止方法
}
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
}
方法的重载
- 重载就是在一个类中,有相同的函数名称,但形参不同的函数。
- 方法的重载的规则:
- 方法名称必须相同。
- 参数列表必须不同(个数不同、或类型不同、参数列表顺序不同等)。
- 方法的返回类型可以相同,也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
- 实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
public class Demo02 {
public static void main(String[] args) {
int max1 = max(20, 20);
double max2 = max(20, 30);
System.out.println(max1); // 20
System.out.println(max2); // 30
}
// 比大小
public static int max(int num1, int num2) {
int result = 0;
if (num1 == num2) {
System.out.println("num1 == num2");
return num1; // 终止方法
}
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
// 比大小
public static double max(double num1, double num2) {
double result = 0;
if (num1 == num2) {
System.out.println("num1 == num2");
return num1; // 终止方法
}
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
}
命令行传参
- 有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。
package test;
public class CommandLine {
public static void main(String[] args) {
for(int i=0;i<args.length;i++) {
System.out.println("agrs[" + i + "]:" + args[i]);
}
}
}
可变参数
- JDK1.5开始,Java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后加一个省略号(…)。
- 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
public class Demo04 {
public static void main(String[] args) {
// 调用可变参数的方法
printMax(34, 3, 3, 2, 56.5);
printMax(new double[] { 1, 2, 3 });
}
public static void printMax(double... numbers) {
if (numbers.length == 0) {
System.out.println("No argument passed"); // 未传递参数
return;
}
double result = numbers[0];
// 排序
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > result) {
result = numbers[i];
}
}
System.out.println("The max value is " + result); // 最大值是
}
}
public class Demo04 {
public static void main(String[] args) {
// Demo04 demo04 = new Demo04();
// demo04.test(1, 2, 3, 4, 5);
new Demo04().test(1, 2, 3, 4, 5);
}
public void method() {}
public void method(int i) {}
public void method(int i, int j) {}
public void method(int i, double j) {}
public void test(int... i) {
System.out.println(i[0]);
System.out.println(i[1]);
System.out.println(i[2]);
System.out.println(i[3]);
System.out.println(i[4]);
}
// public void test(int... i,int x) {} // error
public void test(int x, int... i) {}
}
递归
- A方法调用B方法,我们很容易理解!
- 递归就是:A方法调用A方法!就是自己掉自己
- 利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题你来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
- 递归结构包括两个部分:
- 递归头:什么时候不再用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
public class Demo06 {
// 5! 5*4*3*2*1
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n) {
if (n == 1) {
return 1;
} else {
return n * f(n - 1);
}
}
}
作业
- 写一个计算器,要求实现加减乘除功能,并且能够循环接收新的数据,通过用户交互实现。
- 思路:
- 写4个方法:加减乘除
- 利用循环+switch进行用户交互
- 传递需要操作的两个数
- 输出结果
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 为true无限循环
while (true) {
System.out.println("请输入第一个数:");
int number = scanner.nextInt();
System.out.println("请输入+ - * /选择计算方法:");
String num = scanner.next();
System.out.println("请输入第二个数:");
int number2 = scanner.nextInt();
switch (num) {
case "+":
add(number, number2);
break;
case "-":
minus(number, number2);
break;
case "*":
multiply(number, number2);
break;
case "/":
division(number, number2);
break;
}
}
}
// 加法
public static void add(int a, int b) {
System.out.println(a + b);
}
// 减法
public static void minus(int a, int b) {
System.out.println(a - b);
}
// 乘法
public static void multiply(int a, int b) {
System.out.println(a * b);
}
// 除法
public static void division(int a, int b) {
System.out.println(a / b);
}
}
数组
- 数组概述
- 数组声明创建
- 数组使用
- 多维数组
- Arrays类
- 稀疏数组
数组的定义
- 数组是相同类型数据的有序集合。
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排序组合而成。其中,每一个数组称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
数组声明创建
- 首先必须声明数组变量,才能在程序中使用数组。
- Java语言使用new操作符创建数组
- 数组的元素是通过索引访问的,数组索引从0开始。
- 获取数组长度:
arrays.length
public class ArrayDemo01 {
public static void main(String[] args) {
// 变量的类型 变量的名字 = 变量的值;
// 数组类型
int[] nums; // 1. 声明一个数组
int nums2[];
nums = new int[10]; // 2. 创建一个数组
// 3. 给数组元素中赋值
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
nums[3] = 4;
nums[4] = 5;
nums[5] = 6;
nums[6] = 7;
nums[7] = 8;
nums[8] = 9;
nums[9] = 10;
System.out.println(nums[9]); // 10
// 计算所有元素的和
int sum = 0;
// 获取数组长度:arrays.length
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
System.out.println("总和为:" + sum); // 55
}
}
内存分析
三种初始化
- 静态初始化
- 动态初始化
- 数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组已经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
package array;
public class ArrayDemo02 {
public static void main(String[] args) {
// 静态初始化:创建 + 赋值
int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Man[] mans = { new Man(), new Man() };
System.out.println(a[0]); // 1
System.out.println(mans[0]); // ArrayDemo02.Man@52e922
System.out.println(mans[1]); // ArrayDemo02.Man@25154f
// 动态初始化:包含默认初始化
int[] b = new int[10];
b[0] = 10;
System.out.println(b[0]); // 10
System.out.println(b[1]); // 0
}
}
package array;
public class Man {
}
数组的四个基本特点
- 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组边界
- 下标的合法区间:[0, length-1],如果越界就会报错:
public static void main(String[] args) { int[] a = new int[2]; System.out.println(a[2]); // error }
- java.lang.ArrayIndexOutOfBoundsException:数组下标越界异常!
- 小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度是确定的,不可变的。如果越界,则报:ArrayIndexOutOfBounds
int[] a = { 1, 2, 3, 4, 5 };
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
数组的使用
- 普通的for循环
- for-each 循环
- 数组作方法入参
- 数组作返回值
int[] arrays = { 1, 2, 3, 4, 5 };
// 打印全部的数组元素
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]); // 1 2 3 4 5
}
// 计算所有元素的和
int sum = 0;
for (int i = 0; i < arrays.length; i++) {
sum += arrays[i];
}
System.out.println("sum = " + sum); // sum = 15
// 查找最大元素
int max = arrays[0];
for (int i = 0; i < arrays.length; i++) {
if (arrays[i] > max) {
max = arrays[i];
}
}
System.out.println("max = " + max); // max = 5
public static void main(String[] args) {
// JDK1.5 没有下标
for (int array : arrays) {
System.out.print(array + " "); // 1 2 3 4 5
}
printArray(arrays); // 1 2 3 4 5
int[] reverse = reverse(arrays);
printArray(reverse); // 5 4 3 2 1
}
// 打印数组元素
public static void printArray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i] + " ");
}
}
// 反转数组
public static int[] reverse(int[] arrays) {
int[] result = new int[arrays.length];
// 反转的操作
for (int i = 0, j = result.length - 1; i < arrays.length; i++, j--) {
result[j] = arrays[i];
}
return result;
}
多维数组
- 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
- 二维数组
int a[][] = new int[2][5];
- 解析:以上二维数组a可以看成一个两行五列的数组。
- 思考:多维数组的使用?
num[1][0];
public static void main(String[] args) {
int[][] array = { { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 } };
printArray(array[0]); // 1 2
printArray(array[1]); // 2 3
System.out.println(array[2][0]); // 3
System.out.println(array[2][1]); // 4
System.out.println(array.length); // 4
System.out.println(array[0].length); // 2
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.println(array[i][j]);
}
}
}
// 打印数组元素
public static void printArray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i] + " ");
}
}
Arrays类
- 数组的工具类java.util.Arrays
- 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
- 查看JDK帮助文档
- Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)
- 具有以下常用功能:
- 给数组赋值:通过fill方法。
- 对数组排序:通过sort方法,按升序。
- 比较数组:通过equals方法比较数组中元素值是否相等。
- 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 2020, 1212, 3434, 20, 3, 30 };
System.out.println(a); // [I@52e922
// 打印数组元素Arrays.toString(a);
System.out.println(a.toString()); // [I@52e922
System.out.println(Arrays.toString(a)); // [1, 2, 3, 4, 2020, 1212, 3434, 20, 3, 30]
printArray(a); // [1, 2, 3, 4, 2020, 1212, 3434, 20, 3, 30]
Arrays.sort(a); // 数组进行排序:升序
System.out.println("\n" + Arrays.toString(a)); // [1, 2, 3, 3, 4, 20, 30, 1212, 2020, 3434]
// Arrays.fill(a, 0); // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Arrays.fill(a, 2, 4, 0);
System.out.println(Arrays.toString(a)); // [1, 2, 0, 0, 4, 20, 30, 1212, 2020, 3434]
}
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
if (i == 0) {
System.out.print("[");
}
if (i == a.length - 1) {
System.out.print(a[i] + "]");
} else {
System.out.print(a[i] + ", ");
}
}
}
冒泡排序
- 冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!
- 冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。
- 我们看到嵌套循环,应该立马就可以得出这个算法的 时间复杂值为O(n2)。
- 思考:如何优化?
// 冒泡排序
// 1. 比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们该交换她们的位置
// 2. 每一次比较,都会产生一个最大,或者最小的数字
// 3. 下一轮则可以少一次排序
// 4. 依次循环,直到结束
public static void main(String[] args) {
int[] a = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array) {
// 临时变量
int temp = 0;
// 外层循环,判断我们这个要走多少次
for (int i = 0; i < array.length - 1; i++) {
boolean flag = false; // 通过flag标识减少没有意义的比较
// 内层循环,比较判断两个数,如果第一个数,比第二个数大,则交换位置
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag = true;
}
}
if (flag == false) {
break;
}
}
return array;
}
稀疏数组
- 需求:编写五子棋游戏中,有序盘退出和续上盘的功能。
- 分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据。
- 解决:稀疏数组
稀疏数组介绍
- 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
- 左边是原始数组,右边是稀疏数组
// 1. 创建一个二维数组 11*11 0:没有棋子 1:黑旗 2:白旗
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
// 输出原始的数组
System.out.println("输出原始的数组");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
System.out.println("====================");
// 转换为稀疏数组保存
// 获取有效值的个数
int sum = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[0].length; j++) {
if (array1[i][j] != 0) {
sum++;
}
}
}
System.out.println("有效值的个数:" + sum);
// 2. 创建一个稀疏数组的数组
int[][] array2 = new int[sum + 1][3]; // [行][列]
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
// 遍历二维数组,将非零的值,存在稀疏数组中
int count = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
// 输出稀疏数组
System.out.println("稀疏数组");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0] + "\t" + array2[i][1] + "\t" + array2[i][2] + "\t");
}