流程控制语句
用来控制程序的走向,程序默认采用从主方法进入 从上到下、从左到右的方式进行代码的执行
如果希望通过条件来控制流程的走向,那么就必须了解流程控制语句
流程控制语句的种类
-
判断
-
循环
条件判断
- if 判断
if 假如、如果
语法: if(boolean类型的表达式) { … 满足条件的执行代码 … }
int score = 650 ;
if (score > 710) {
System.out.println("恭喜,您被清华大学录取");
}
- if / else 判断
else 否则
boolean hasCar = false;
if (hasCar) {
System.out.println("开车上学");
}else{
System.out.println("走路上学");
}
- 多分支条件判断
if / else if / else
if 是出现在判断的最前面,不能省略
else if 可以出现的次数是 0 ~ N 个
else 只能出现在 判断的尾部、最多只能出现 1 次
练习:
给定一个成绩、输出该成绩对应的 优良中差
java.util.Scanner 类
用来接收从键盘输入的内容
next():
从键盘上获取输入的字符串、当用户按下回车后才会将键盘录入的内容读取到程序中
会按照 空格 对 输入的内容 进行分割,每次只读取一部分,直到将所有内容读取完成后,
才会再次读取键盘输入的内容
nextLine() : 按下回车后、读取输入的一行内容
nextInt() : 当下回车后,从键盘读取数字,本质和 next() 一样, 如果内容不是数字,则会报错
switch 选项
是实现判断的另一种手段、更加适用于枚举特性
switch 穿透 : 当 处理的值 满足某一个 case 的时候, 会默认执行 当前 case 和 后面所有的 case
如果不希望 switch 某一个 case 拥有穿透功能,可以在case 分支中,添加一个 break 关键字, 打断 switch 穿透
int month = 3;
int day = 0 ;
if ( month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month ==10 || month == 12 ) {
day = 31 ;
}else if (month == 4 || month == 6 || month == 9 || month == 11) {
day = 30 ;
}else {
day = 28 ;
}
将上述 if 代码 更改 switch 代码
int day = 0 ;
switch(month) {
case 1, 3, 5, 7, 8, 10, 12 : day = 31 ; break ;
case 4, 6, 9, 11 : day = 30 ; break ;
default : day = 28 ;
}
System.out.println(day);
switch 可以处理的数据类型 包含
byte 、 short、 int 、 char 、 enum 、 Byte 、 Short 、 Integer 、 Character 、
Java7 版本新增了 对 String 类的支持
switch JDK14 新特性
- case 支持 用 逗号 来处理多个值
- case 中的 冒号 可以更改为 -> , 可以解决switch穿透,不用在添加break
- 如果使用 -> 且 case 分支代码不止一行,必须使用 { … } 进行包裹
- switch 可以作为 表达式 使用,case 分支 可以通过 yield 关键字 返回表达式的结果
如果 case 分支中的 代码 只有 一行,则可以省略 { …} , 当省略了大括号的时候,必须省略 yield
switch 作为表达式,那么结果 必须添加;
, 表达式不能单独使用,可以使用赋值运算
switch 作为表达式的时候,必须使用 default 分支
循环
将 重复的事情交给 计算机进行处理
- while 循环
while(循环条件) {
重复的事情
}
循环条件是一个 boolean 表达式
循环的三要素: 1. 循环的起始值(计数器), 2. 循环的条件 , 3. 对循环的控制
当一个循环无法确定循环条件,直接使用 while(true), 通过 break 或者 continue 来控制循环
- do … while 循环
do {
//重复的事情
}while(循环条件) ;
do … while 无论条件是否成立,循环体中的代码至少会运行一次
while … 条件如果不成立、则循环体中的代码不会被执行
从键盘中不断的输入字符串、直到输入end结束循环
- for循环
是三种循环中,写法上最简单的一个循环、也是使用频率最高的一种循环方式
能用 for循环实现的、不推荐使用 while / do… while
for( 循环起始条件 ; 循环条件 ; 循环控制 ) {
循环体
}
当程序进入 for循环的时候,会首先执行 循环起始条件、在执行 循环条件(如果成立),执行循环体
当循环体执行完成后、执行循环的控制 、循环控制执行后,在执行循环条件(如果成立),执行循环体
for循环中定义的循环控制变量、只能在for循环中使用,但while循环中定义的循环控制变量,出了while循环仍旧可以使用
当循环次数固定推荐使用 for循环、当循环次数不固定、推荐使用while循环
数组
数组是用来存储一组有序的数据的容器
数组中存储数据的地址是连续的
数组中存储数据的类型是一致的
数组一旦创建、长度不可改变
声明数组
1. 类型[] 变量名 ; (推荐写法)
2. 类型 变量名[] ; (官方不推荐的写法)
创建数组
1. 变量名 = new 类型[数组长度] ;
2. 变量名 = new 类型[]{ val, val1, val2, val3, ...} ;
声明并创建数组
1. 类型[] 变量名 = new 类型[长度] ;
2. 类型[] 变量 = new 类型[] {val, val1, val2 ....} ;
3. 类型[] 变量名 = {val, val2, val3 ...} ;
错误的写法
类型[] 变量名 ;
变量名 = {val, val2 , ...}
数组的基本操作
- 获取 数组中的指定位置的元素
数组变量[index]
index 指的是 数组中的索引,从 0 开始
- 修改 数组中指定位置的元素
数组变量[index] = val ;
index的值的范围是 0 ~ 数组的长度 - 1
- 获取数组的长度
数组.length
- 遍历数组
for(int i= 0 ; i < array.length; i++) {
int x = array[i] ;
...
}
- 数组的最大小值
int max = array[0] ; // 定义一个最大值,默认数组中的第一个元素是大的
int min = array[0] ; //
for(int i = 1 ; i < array.length ; i++) {
if (max < array[i] ) {
max = array[i] ;
}
if (min > array[i]) {
min = array[i] ;
}
}
数组的排序
- 冒泡排序
数组中两个相邻的数字进行比较、并交换,将大的数字沉到数组的尾部(升序排列)
// 外层循环 控制 排序的次数
for (int i = 1; i < array.length ; i++) {
// 内层循环 控制 比较的次数
for (int j = 0; j < array.length - i; j++) {
// 比较 两个相邻的数字
if (array[j] > array[j + 1]) {
// 交换两个数字
array[j] = array[j] ^ array[j + 1];
array[j + 1] = array[j] ^ array[j + 1];
array[j] = array[j] ^ array[j + 1];
}
}
}
- 选择排序
数组中的一个元素和它后面所有的元素进行比较、并交换,将小的数字沉到数组的头部(升序排列)
// 外层循环控制循环次数, 从 0 开始
for(int i = 0 ; i < array.length - 1 ; i++) {
// 内存循环 控制 比较次数
for(int j = i+ 1 ; j < array.length ; j++) {
// 使用 array[i] 和 array[j] 进行比较
if (array[i] > array[j]) {
array[i] = array[i] ^ array[j] ;
array[j] = array[i] ^ array[j] ;
array[i] = array[i] ^ array[j] ;
}
}
}
- 插入排序
将元素插入到数组中已经排序好的位置中
// 从数组的第二个元素 开始进行排序 , i 代表要进行排序的元素的索引
for(int i = 1 ; i< array.length ; i++) {
// 将要插入的数字 保存起来
int n = array[i] ;
int j ;
for(j = i - 1 ; j >= 0 ; j--) {
// 比较 要插入的元素 和 前一个元素 谁大, 如果 插入的元素,比 前一个元素 小
if (n < array[j] ) {
array[j + 1] = array[j] ;
}else{
break ;
}
}
array[j + 1] = n ;
}
数组的维护
向数组中添加或者删除元素、返回的一定是一个新的数组
System.arraycopy(src, srcOffset , dest, offset, length) : 将指定的数组内容拷贝到另一个数组中
src : 要进行复制的数组
offset : 要进行复制的数组的起始位置
dest : 进行存储新数据的数组
offset: 从新数组的哪一个位置存储数据
length : 拷贝的长度
-
向数组中添加一个元素
-
向数组中删除一个元素
采用一段连续的存储单元来存储数据。
对于指定下标的查找,时间复杂度为O(1);
通过给定值进行查找,需要遍历数组,逐一比对给定关键字和数组元素,时间复杂度为O(n)
当然,对于有序数组,则可采用二分查找,插值查找,斐波那契查找等方式,可将查找复杂度提高为O(logn);
对于一般的插入删除操作,涉及到数组元素的移动,其平均复杂度也为O(n)
冒泡、选择排序时间复杂度是 O(n^2)
Arrays 工具类的使用
- Arrays.toString(array) : 将指定的数组以字符串的形式表示,返回一个字符串
- Arrays.sort(array) : 对指定的数组 按照升序进行排序 (底层采用的快速排序)
- Arrays.sort(array, from, to) : 将数组的 from … to 之间的元素进行 排序
- Arrays.copyOf(array, newLen) : 将数组中从第1个元素到 newLen长度的内容拷贝到新数组中
- Arrays.copyOfRange(array, from , to) : 将数组的 from … to 之间的元素拷贝到新数组中
- Arrays.stream(array).max() : 求数组的最大值
- Arrays.stream(array).min() : 求数组的最小值
- Arrays.stream(array).sum() : 求数组的和
- Arrays.stream(array).average() : 求数组的平均值
to:截至位置,不包含
ArrayUtils 工具类的使用
不是 JDK 自带的, 是 apache 提供的,封装在了 commons-lang3.jar 中
jar 是 一个压缩文件、jar里面压缩的是 .class 字节码文件
Java中 jar的下载,推荐在 http://www.mvnrepository.com 网站中下载
在 idea的项目中,新建一个文件夹,推荐叫 lib
将下载好的 jar 拷贝到 lib 文件夹下
将 lib 文件夹作为 库 ( 选中 lib 右键 —> add as Libary )
-
add : 向数组尾部添加一个元素
-
addAll : 向数组尾部添加 多个元素
-
addFirst : 向数组头部添加一个元素
-
remove : 根据索引删除指定位置的元素
-
removeElement : 删除数组中指定的元素
-
removeAllOccurrences :删除数组中指定的元素的所有
-
clone() : 克隆一个数组,返回一个新数组,和原数据内容一样
-
toObject() : 将 基本类型数组 转成 包装类型数组
-
toPrimitive() : 将 包装类数组 转成 基本数据类型数组