Java编程基础-2

学习任何一门语言,都要从基础开始。本文将针对Java的运算符,结构语句以及数组进行讲解。

1. 运算符

Java中,运算符可分为算术运算符、赋值运算符、比较运算符、逻辑运算符、位运算符、条件运算符。

1.1 算术运算符

表1-算术运算符
运算符 运算 范例 结果
+ 正号 a = 3; +a; 3
- 负号 b = 3; -b; -3
+ 5 + 5 10
- 3 - 2 1
* 3 * 4 12
/ 除(取商) 7 / 5 1
% 取模(取余数) 7 % 5 2
++ 自增(前) a = 3; b = ++a; a = 4,b = 4
++ 自增(后) a = 3; b = a++; a = 4,b = 3
-- 自减(前) a = 3; b = --a; a = 2,b = 2
-- 自减(后) a = 3; b = a--; a = 2,b = 3

tip:(自减同理)

  • 自增(前):++a,是在赋值前就进行自增,赋值前a=3,b=++a,给b赋值之前,先计算++a,所以此时a变为4,再加自增后的值赋值给b,最终b=4
  • 自增(后):a++,是先进行赋值,然后再进行自增。赋值前a=3,b=a++,先将a赋值给b,所以此时b=3,然后a再进行自增,所以a=4,最终a=4,b=3

1.2 赋值运算符

表2-赋值运算符
运算符 运算 范例 结果
= 赋值 a = 3; b = 2; a = 3; b = 2;
+= 加等于 a = 3; b = 2; a+=b; a = 5; b= 2
-= 减等于 a = 3; b = 2; a-=b; a = 1; b= 2
*= 乘等于 a = 3; b = 2; a*=b; a = 6; b= 2
/= 除等于 a = 3; b = 2; a/=b; a = 1; b= 2
%= 模等于 a = 3; b = 2; a%=b; a = 1; b= 2

tip:在赋值过程中,运算顺序从右到左,将右边表达式的结果赋值给左边的变量。
例如:

int x,y,z;
x = y = z = 10;  //为三个变量同时赋值

但是要注意,这样写是不可以的:

int x = y = z = 10;  //错误的,因为没有预先声明变量y,z的数据类型

在上表中,除了=号外,其余都是特殊的赋值运算符,例如:

  • +=a+=b等价于a = a + b
  • -=a-=b等价于a = a - b
  • *=a*=b等价于a = a * b
  • /=a/=b等价于a = a / b
  • %=a%=b等价于a = a % b

1.3 逻辑运算符

表3-逻辑运算符
运算符 运算 范例 结果 运算符 运算 范例 结果
& true & true true | true | true true
true & false false true | false true
false & false false false | false false
false & true false false | true true
^ 异或 true & true true || 短路或 true || true true
true & false false true || false true
false & false false false || false false
false & true false false || true true
&& 短路与 true & true true ! !true false
false && false false !false true
false && false false
false && true false

tip

  1. 逻辑运算符可以针对结果为布尔值的表达式进行逻辑运算。例如:
    5 > 3 && 1!=0 结果为true,因为5 > 3true1!=0true,所以结果为true
  2. 短路运算符&&||可以提前终止表达式的计算,即如果左边的表达式已经可以确定结果,则不再计算右边的表达式。例如使用短路与(&&):
    false && true 结果为false,因为false已经可以确定结果,所以不再计算右边的表达式true

再举个例子来深入了解短路与(&&) 和 与(&) 二者区别:

public class Demo2 {
    public static void main(String[] args) {
        int x,y,z;
        x = y = z = 0;
        boolean a,b;
        a = x > 0 & y++ > 1; // 与运算符
        System.out.println("a=" + a + ",y=" + y); // a=false,y=1
        
        b = x > 0 && z++ > 1; // 短路与运算符
        System.out.println("b=" + b + ",z=" + z); // b=false,z=0

    }
}

与运算符,必须计算符号两边的表达式,x>0false,还要再计算y++ > 1,由于是后自增,所以0 > 1,为false,计算完成后,y自增,所以输出a=false,y=1

短路与运算符,如果左边结果为false,则不再计算右边的表达式。只需要计算符号左边的表达式,x>0false,就不再计算右边的表达式,所以z++ > 1 不会被计算,输出b=false,z=0

  • 与:有false则为false,否则为true;
  • 或:有true则为true,否则为false;
  • 短路与:有false则为false,否则为右边表达式的值;
  • 短路或:有true则为true,否则为右边表达式的值;
  • 非:取反,true变false,false变true。
  • 异或:相同为false,不同为true。

1.4 位运算符

表4-位运算符
运算符 运算 范例 结果 运算符 运算 范例 结果
& 按位与 0 & 0 0 | 按位或 0 | 0 0
0 & 1 0 0 | 1 1
1 & 1 1 1 | 1 1
1 & 0 0 1 | 0 1
^ 按位异或 0 ^ 0 0 ~ 取反 ~0 1
0 ^ 1 1 ~1 0
1 ^ 1 0
1 ^ 0 1
<< 左移 00000010<<2 00001000 >> 右移 01100010>>2 00011000
10010011<<2 01001100 11100010>>2 11111000
>>> 无符号右移 01100010>>>2 00011000
11100010>>>2 00011000

tip
位运算符针对二进制位进行操作。

  • &:按位与,有0则0,否则为1;
  • |:按位或,有1则1,否则为0;
  • ^:按位异或,相同为0,不同为1;
  • ~:取反,对每个二进制位取反,即0变1,1变0;
  • <<:左移,将运算数的各二进位全部左移若干位,由最高位的符号位决定,低位补0;
  • >>:右移,将运算数的各二进位全部右移若干位,由最低位的符号位决定,高位补0;
  • >>>:无符号右移,将运算数的各二进位全部右移若干位,高位丢弃,高位补0。

例如:

public class Demo3 {
    public static void main(String[] args) {
        int x = 60; // 60 = 0011 1100
        int y = 13; // 13 = 0000 1101
        int z = 0;
        z = x & y;    // 12 = 0000 1100  按位与 有0则0
        System.out.println("x & y = " + z); // x & y = 12
        
        z = x | y;    // 61 = 0011 1101 按位或 有1则1
        System.out.println("x | y = " + z); // x | y = 61
        
        z = x ^ y;    // 49 = 0011 0001 按位异或 相同为0,不同为1
        System.out.println("x ^ y = " + z); // x ^ y = 49
        
        z = ~x;       // -61 = 1100 0011 取反 每位取反
        System.out.println("~x = " + z); // ~x = -61
        
        z = x << 2;   // 240 = 1111 0000 左移 各二进位全部左移2位,低位补0
        System.out.println("x << 2 = " + z); // x << 2 = 240
        
        z = x >> 2;   // 15 = 0000 1111 右移 各二进位全部右移2位,高位看符号位,现在符号位为0,则补0
        System.out.println("x >> 2 = " + z); // x >> 2 = 15
        
        z = x >>> 2;  // 15 = 0000 1111 无符号右移 各二进位全部右移2位,低位丢弃,高位补0
        System.out.println("x >>> 2 = " + z); // x >>> 2 = 15
    }
}

输出:

x & y = 12
x | y = 61
x ^ y = 49
~x = -61
x << 2 = 240
x >> 2 = 15
x >>> 2 = 15

1.5 条件运算符

条件运算符,也称作是三元(或三目)运算符,它根据条件表达式的真假来决定执行哪个表达式。语法格式如下:

表达式1 ? 表达式2 : 表达式3;

例如:

int x = 10;
int y = 20;
int z = x > y ? x : y;
//10 > 20 为false,所以执行表达式2,即z = y,故z = 20。

System.out.println(z); // 20

tip

  1. 条件运算符的表达式1、表达式2和表达式3都是表达式,可以是任意有效的表达式。
  2. 条件运算符的作用是根据表达式1的真假来决定执行表达式2还是表达式3。如果表达式1为真,则执行表达式2,否则执行表达式3。
  3. 条件运算符的结果是根据表达式2或表达式3的结果来确定的。

1.6 运算符优先级

运算符的优先级决定了运算顺序,优先级高的运算符先进行运算。Java语言中运算符的优先级从高到低依次为:

优先级运算符
1() [] .
2++ -- ! ~
3* / %
4+ -
5<< >> >>>
6< > <= >=
7== !=
8&
9^
10|
11&&
12||
13? :
14= += -= *= /= %= &= ^= |= <<= >>= >>>=

2. 选择结构语句

2.1 if条件语句

2.1.1 if语句

if语句是指如果满足某种条件,则执行某段代码。
if语句的语法格式如下:

if(表达式){
   //语句块1
}

其中,表达式为布尔表达式,如果表达式为true,则执行语句块1,否则不执行。(注意大小写)

例如,如果一个人的年龄不足18岁,则可以判定这个人是未成年人

if(age < 18){
   System.out.println("这个人是未成年人");
}

2.1.2 if...else语句

if...else语句是指如果满足某种条件,则执行某段代码,否则执行另一段代码。
if...else语句的语法格式如下:

if(表达式){
   //语句块1
}else{
   //语句块2
}

其中,表达式为布尔表达式,如果表达式为true,则执行语句块1,否则执行语句块2。(注意大小写)

例如,如果一个人的年龄不足18岁,则可以判定这个人是未成年人,否则是成年人

if(age < 18){
   System.out.println("这个人是未成年人");
}else{
   System.out.println("这个人是成年人");
}

2.1.3 if...else if...else语句

if...else if...else语句是指如果满足某种条件,则执行某段代码,否则判断下一个条件,如果满足,则执行该段代码,否则执行最后一段代码。
if...else if...else语句的语法格式如下:

if(表达式1){
   //语句块1
}else if(表达式2){
   //语句块2
}else if(表达式3){
   //语句块3
}else{
   //语句块4
   //.... 以此类推
}

其中,表达式1、表达式2、表达式3为布尔表达式,如果表达式1为true,则执行语句块1,否则判断表达式2,如果表达式2为true,则执行语句块2,否则判断表达式3,如果表达式3为true,则执行语句块3,否则执行语句块4。(注意大小写)

例如,判断一个人的年龄,如果年龄小于18岁,则判定为未成年人,如果年龄大于等于18岁,但小于等于30岁,则判定为青少年,如果年龄大于30岁,则判定为成年人

if(age < 18){
   System.out.println("这个人是未成年人");
}else if(age >= 18 && age <= 30){
   System.out.println("这个人是青少年");
}else{
   System.out.println("这个人是成年人");
}

2.2 switch条件语句

switch条件语句是指根据表达式的值来执行不同的代码块。
switch语句的语法格式如下:

switch(表达式){
   case 常量1:
      //语句块1
      break;
   case 常量2:
      //语句块2
      break;
   case 常量3:
      //语句块3
      break;
   //.... 以此类推
   default:
      //默认语句块
      break;
}

其中,表达式为整型表达式,常量1、常量2、常量3为常量表达式,如果表达式的值等于常量1,则执行语句块1,如果表达式的值等于常量2,则执行语句块2,如果表达式的值等于常量3,则执行语句块3,以此类推。如果表达式的值不等于任何常量,则执行default语句块。(注意大小写)

例如,根据月份来判断季节,如果月份是1、2、3月,则是春天;如果月份是4、5、6月,则是夏天;如果月份是7、8、9月,则是秋天;如果月份是10、11、12月,则是冬天。

int month = 7;
switch(month){
   case 1:
      System.out.println("春天");
      break;
   case 2:
     System.out.println("春天");
      break;
   case 3:
      System.out.println("春天");
      break;
   case 4:
      System.out.println("夏天");
      break;
   case 5:
      System.out.println("夏天");
      break;
   case 6:
      System.out.println("夏天");
      break;
   case 7:
      System.out.println("秋天");
      break;
   case 8:
      System.out.println("秋天");
      break;
   case 9:
      System.out.println("秋天");
      break;
   case 10:
      System.out.println("冬天");
      break;
   case 11:
      System.out.println("冬天");
      break;
   case 12:
      System.out.println("冬天");
      break;
   default:
      System.out.println("月份错误");
      break;
}

通过这样编写,我们可以根据不同的月份来判断季节,并执行相应的代码。但是我们发现,每三个月为一个季节,如果有12个月,那么我们需要编写12个case语句,这显然不合理。因此,我们可以使用多个case标签并列书写,并编写一次执行语句即可。

如下:

int month = 7;
switch(month){
   case 1:
   case 2:
   case 3:
      System.out.println("春天");
      break;
   case 4:
   case 5:
   case 6:
      System.out.println("夏天");
      break;
   case 7:
   case 8:
   case 9:
      System.out.println("秋天");
      break;
   case 10:
   case 11:
   case 12:
      System.out.println("冬天");
      break;
   default:
      System.out.println("月份错误");
      break;
}

输出:

秋天

3. 循环结构语句

3.1 while循环语句

while循环语句是指当满足某种条件时,重复执行某段代码。
while循环语句的语法格式如下:

while(表达式){
   //语句块
}

其中,表达式为布尔表达式,如果表达式为true,则执行语句块,否则退出循环。(注意大小写)

例如,打印1到10的整数

int i = 1;
while(i <= 10){
   System.out.println(i);
   i++;
}

3.2 do...while循环语句

do...while循环语句是指先执行某段代码,然后判断表达式是否为true,如果为true,则继续执行,否则退出循环
do...while循环语句的语法格式如下:

do{
   //语句块
}while(表达式);

其中,表达式为布尔表达式,如果表达式为true,则执行语句块,否则退出循环。(注意大小写)

例如,打印1到10的整数

int i = 1;
do{
   System.out.println(i);
   i++;
}while(i <= 10);

3.3 for循环语句

for循环语句是指重复执行某段代码,直到满足某种条件为止。
for循环语句的语法格式如下:

for(初始化表达式; 循环条件表达式; 迭代表达式){
   //语句块
}

其中,初始化表达式初始化变量的表达式循环条件表达式布尔表达式,如果表达式true,则执行语句块,否则退出循环迭代表达式更新变量的表达式,在每次循环结束后执行。(注意大小写)

例如,打印1到10的整数

for(int i = 1; i <= 10; i++){
   System.out.println(i);
}

3.4 循环嵌套

循环结构语句可以嵌套,即一个循环结构语句中可以包含另一个循环结构语句。我们最常用的是for循环嵌套,其语法格式如下:

for(初始化表达式; 循环条件表达式; 迭代表达式){
   //语句块1
   for(初始化表达式; 循环条件表达式; 迭代表达式){
      //语句块2
   }
   //语句块3
}

其中,初始化表达式循环条件表达式迭代表达式语句块1语句块2语句块3的语法格式与for循环语句相同。

例如,打印九九乘法表

for(int i = 1; i <= 9; i++){
   for(int j = 1; j <= i; j++){ 
      System.out.print(i + "x" + j + "=" + i*j + "\t");
   }
   System.out.println();
}

输出:

1x1=1	1x2=2	1x3=3	1x4=4	1x5=5	1x6=6	1x7=7	1x8=8	1x9=9	
2x1=2	2x2=4	2x3=6	2x4=8	2x5=10	2x6=12	2x7=14	2x8=16	2x9=18	
3x1=3	3x2=6	3x3=9	3x4=12	3x5=15	3x6=18	3x7=21	3x8=24	3x9=27	
4x1=4	4x2=8	4x3=12	4x4=16	4x5=20	4x6=24	4x7=28	4x8=32	4x9=36	    
.................

在上述代码中,我们使用了两个for循环语句,第一个for循环用于打印行,第二个for循环用于打印列和对应的值。输出语句中的\t用于控制输出的对齐。print()用于向控制台输出内容,但是执行完后不会进行换行。而println()同样用于输出内容,但是执行后会自动换行。

3.5 跳转语句

3.5.1 break语句

break语句是指终止当前循环,并跳出循环体
例如:

for(int i = 1; i <= 10; i++){
   if(i == 5){
      break;
   }
   System.out.println(i);
}

for循环用于打印1到10的整数,但是我们加了if判断,当 i 等于 5的时候,就不再继续执行循环体,直接跳出循环,此时用到了break语句。

输出:

1
2
3
4

tip:循环结构中的break语句只会跳出当前所在循环,如果嵌套了多层循环',则只会跳出使用了break语句的那层循环。如果想要在内层循环中使用break跳出外层循环,则需要预先在外层循环做一个标记,然后再使用break进行跳出指定的外层循环。

public static void main(String[] args) {
    outer:for(int i = 1; i <= 3; i++){ //outer进行标记
        for(int j = 1; j <= 3; j++){
            if(j == 2){
                break outer; //直接跳出外层循环
            }
            System.out.println("i=" + i + " j=" + j);
        }
    }
}

3.5.2 continue语句

continue语句是指跳过当前循环的剩余语句,并开始下一次循环

例如:

public static void main(String[] args) {
    int sum = 0;
    for(int i = 1; i <= 10; i++){
        if(i %2 == 0){
            continue;
        }
        sum +=i;
    }
    System.out.println(sum);

}

for循环用于打印1到10的整数,但是我们加了if判断,当 i %2 (%取余)等于 0 (即等于偶数) 的时候,就不再执行累加操作,直接跳过本次循环,进入到下次循环,此时用到了continue语句。

4. 数组

现在需要统计某公司的员工的工资情况,然后计算平均工资,最高工资等。假如有100个员工,根据之前的知识,我们就需要声明100个变量来分别记住每个员工的工资,这样就太过麻烦。这个时候,我们就可以在java中使用数组来记住这100名员工的工资。

4.1 数组的定义

数组是指一组数据集合数组中的每个数据都称作元素。在数组中可以存放任意类型的元素,但是同一个数组里存放的元素类型必须一致。数组的元素可以用索引来访问。数组还可以分为一维数组多维数组
在java中,数组的定义有三种,数组的定义格式如下:

数据类型[] 数组名 = new 数据类型[数组长度];
数据类型[] 数组名 = {元素1, 元素2, 元素3, ...};
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3, ...};

其中,数据类型为数组中元素的数据类型,数组名为数组的名称,数组长度为数组的长度,元素1元素2元素3为数组的元素。

以上三种定义数组的方式,都可以创建数组,但是第一种定义方式比较常用,第二种定义方式可以简化数组的创建,第三种定义方式可以同时创建数组和初始化数组元素。实际使用如下:

public class ArrayDemo {
    public static void main(String[] args) {
        // 第一种定义方式
        int[] arr1 = new int[5];
        // 第二种定义方式
        Object[] arr2 = {1, "张三", "tom", 4, 5};
        // 第三种定义方式
        String[] arr3 = new String[]{"1", "223", "李斯"};
    }
}

关于数组在内存中的存储方式,这里以上述定义数组的第一种方式为例。第一种数组定义的方式,相当于在内存中定义了5int类型的变量,第一个变量的名称为arr1[0],第二个变量arr1[1],以此类推。最后一个变量的名称为arr1[4]。数组的类型为int,所以这些变量的初始值都是0。可以将上面一句代码分为两剧来写,如下:

int[] arr1;   //声明一个int[]类型的数组
arr1 = new int[5]; //创建一个长度为5的数组,并将数组地址赋值给数组类型的变量arr1

第一行代码声明了一个int[]类型的数组,此时arr1会占用一块内存单元,他并没有被分配初始值。

第二行代码创建一个长度为5的数组,并将数组地址赋值给arr1变量。此时arr1变量就指向了这块内存单元,他已经被分配了初始值。

4.2 数组的访问

想要访问数组中的元素,可以通过下标来访问,数组的下标从0开始,即arr[0]表示数组的第一个元素,arr[1]表示数组的第二个元素,以此类推。需要注意的是,数组中的最小索引0最大索引数组长度-1。在Java张,为了方便获取数组的长度,提供了一个length属性。程序中可以通过数组名.length来获取数组的长度。

如例:

public class ArrayDemo1 {
    public static void main(String[] args) {
        //1.第一种方式定义数组
        int[] arr1 = new int[5];
        System.out.println("访问数组第一个:" + arr1[0]);
        System.out.println("访问数组最后一个" + arr1[4]);
        System.out.println("=====================");
        //2.第二种方式定义数组
        Object[] arr2 = {1, "张三", "tom", 4};
        System.out.println("数组的长度为:" + arr2.length);
        System.out.println("访问数组第一个:" + arr2[0]);
        System.out.println("访问数组最后一个" + arr2[3]);
        System.out.println("=====================");
        // 第三种定义方式
        String[] arr3 = new String[]{"1", "223", "李斯"};
        //4.输出数组元素
        System.out.println("数组的长度为:" + arr3.length);
        System.out.println("访问数组第一个:" + arr3[0]);
        System.out.println("访问数组最后一个" + arr3[2]);

    }
}

输出:

访问数组第一个:0
访问数组最后一个0
=====================
数组的长度为:4
访问数组第一个:1
访问数组最后一个4
=====================
数组的长度为:3
访问数组第一个:1
访问数组最后一个李斯

根据输出可以看出,第一种定义数组方式定义的int[]类型的数组中元素的初始值都是0,这是因为数组被创建成功后,如果没有赋值,就会被自动赋予一个默认值,不同元素类型的默认初始值不同。

Java中不同数据类型元素的默认初始值如下:

数据类型默认初始值
byte,short,int,long0
float,double0.0
char一个空字符 即'\u0000'
booleanfalse
引用数据类型null,表示变量不引用任何对象

如果我们在使用数组时,不想使用这些初始值,可以显式地为这些元素赋值,也可以对定义数组是的指定初始值就行修改,如下:

public class ArrayDemo2 {
    public static void main(String[] args) {
        //1.第一种方式定义数组
        int[] arr1 = new int[5];
        System.out.println("访问数组第一个:" + arr1[0]);
        //为数组指定元素进行初始化赋值
        arr1[0] = 10;
        System.out.println("访问数组第一个:" + arr1[0]);
        System.out.println("=====================");
        //2.第二种方式定义数组
        Object[] arr2 = {1, "张三", "tom", 4};
        System.out.println("访问数组第一个:" + arr2[0]);
        //为数组定义时指定的初始值进行修改
        arr2[0] = "hello";
        System.out.println("访问数组第一个:" + arr2[0]);
        System.out.println("=====================");
        // 第三种定义方式
        String[] arr3 = new String[]{"1", "223", "李斯"};
        System.out.println("访问数组第一个:" + arr3[0]);
        //为数组定义时指定的初始值进行修改
        arr3[0] = "你好";
        //4.输出数组元素
        System.out.println("访问数组第一个:" + arr3[0]);

    }
}

输出:

访问数组第一个:0
访问数组第一个:10
=====================
访问数组第一个:1
访问数组第一个:hello
==========
访问数组第一个:1
访问数组第一个:你好

tip:每个数组的索引都有一个范围,即0~length-1。如果索引超出了这个范围,程序就会报错,出现数组索引越界的异常(ArrayIndexOutOfBoundsException 即为数组索引越界异常)。

4.3 数组的遍历

在操作数组时,经常需要一次访问数组中的每个元素,这种操作称未数组的遍历,经常使用的是通过循环使用下标来获取,如例:

public class ArrayDemo3 {
    public static void main(String[] args) {
        String[] arr3 = {"hello", "world", "java"};
        //遍历数组
        for(int i = 0; i < arr3.length; i++){
            System.out.println("数组的第" + (i+1) + "个元素为:" + arr3[i]);
        }
    }
}

输出:

数组的第1个元素为:hello
数组的第2个元素为:world
数组的第3个元素为:java

上面例子定义了一个长度为3的arr数组,数组下标的取值范围是02,由于for循环中定义的变量i的值在循环过程中为02,因此可以作为索引,依次去访问数组中的元素。

4.4 数组最值

在操作数组时,经常需要获取数组中元素的最值,如例:

public class ArrayDemo4 {
    public static void main(String[] args) {
        //1. 定义一个int数组
        int[] arr4 = {10, 20, 30, 40, 50};
        //2. 定义变量max用于记录最大值,首先假设第一个元素为最大值
        int max = arr4[0];
        //3. 定义变量min记录最小值,同理最大值
        int min = arr4[0];
        for(int i = 1; i < arr4.length; i++){
            if(arr4[i] > max){
                max = arr4[i];
            }else if(arr4[i] < min){
                min = arr4[i];
            }
        }
        System.out.println("数组中元素的最大值为:" + max);
        System.out.println("数组中元素的最小值为:" + min);
    }
}

输出:

数组中元素的最大值为:50
数组中元素的最小值为:10

上述例子,定义了临时变量max和min,分别记录最大值和最小值。首先假设数组首元素为最大值和最小值,然后使用for循环对数组进行遍历,在遍历的过程中,如果元素比max大,则将该元素赋值给max,如果比min小,则将该元素赋值给min。这样一来,变量max和min就能够获取到数组中的最值

4.5 数组排序

在操作数组时,经常需要对数组进行排序。接下来讲解一种比较经典和常用的数组排序--冒泡排序。

首先,我们先来看一下冒泡排序的整个过程:

  1. 从第一个元素开始,比较相邻的两个元素,直到最后两个元素完成比较。如果第一个元素大于第二个元素,则交换它们的位置。整个过程完成后,数组中的最大元素就位于数组的最后一个位置。这样就完成了第一轮比较。
  2. 除了最后一个元素,其他元素都与它比较,如果它大于它后面的元素,则交换它们的位置。这样,数组的前面n-1个元素就完成了第二轮比较。
  3. 重复步骤2,直到数组排序完成。

知道了冒泡排序的过程,我们就通过一个案例来实现它。

public class ArrayDemo5 {
    public static void main(String[] args) {
        //1. 定义一个int数组
        int[] arr5 = {5, 3, 8, 6, 2, 7, 1, 4};
        //2. 冒泡排序
        for(int i = 0; i < arr5.length-1; i++){
            for(int j = 0; j < arr5.length-1-i; j++){
                if(arr5[j] > arr5[j+1]){
                    int temp = arr5[j];
                    arr5[j] = arr5[j+1];
                    arr5[j+1] = temp;
                }
            }
        }
        //3. 输出排序后的数组
        System.out.println("排序后的数组为:");
        for(int i = 0; i < arr5.length; i++){
            System.out.print(arr5[i] + " ");
        }
    }
}

输出:

排序后的数组为:
1 2 3 4 5 6 7 8 

上述案例,定义了一个int数组,然后使用冒泡排序算法对其进行排序。首先,使用两个for循环,外层循环控制排序轮数,内层循环控制每一轮比较的次数。在内层循环中,使用if语句进行元素的比较,如果前一个元素大于后一个元素,则交换它们的位置。这样,数组的前面n-1个元素就完成了第二轮比较。

最后,使用一个for循环输出排序后的数组。

4.6 多维数组

在程序中可以通过一个数组来保存某个班的学生成绩,那如果我们要统计多个班的学生成绩呢。这时就需要用到多维数组,多维数组可以简单地理解为数组中嵌套数组。在程序总,比较常见的是二维数组。

二维数组,可以看成是特殊的一维数组,其定义方式有很多种,比较常见的几种有:

//第一种  可以看成是三个int[]类型的数组,每个数组的长度又为4
int[][] arr6 = new int[3][4]; // 定义3行4列的二维数组  

//第二种
int[][] arr7 = {{1,2,3},{4,5,6},{7,8,9}}; // 定义3行3列的二维数组

//第三种  只指定二维数组的长度,不确定每个数组的元素个数
int[][] arr8 = new int[3][]; // 定义3行0列的二维数组

接下来通过统计公司三个销售小组中每个小组的总销售额,以及整个公司销售额的案例来熟悉二维数组的使用,如例:

public class ArrayDemo6 {
    public static void main(String[] args) {
        //1. 定义一个二维数组,用于存储三个销售小组的销售额
        int[][] arr = new int[3][];
        arr[0] = new int[]{11,12};  
        arr[1] = new int[]{21,22,23};  
        arr[2] = new int[]{31,32,33,34};  
        //2. 定义变量记录公司的总销售额
        int sum = 0;
        for(int i = 0; i < arr.length; i++){
            // 3. 定义变量记录小组的总销售额
            int groupSum = 0;
            for(int j = 0; j < arr[i].length; j++){
                groupSum += arr[i][j];
            }
            sum += groupSum;
            System.out.println("小组" + (i+1) + "的总销售额为:" + groupSum + " 万元");
        }
        System.out.println("公司的总销售额为:" + sum + "  万元");
    }
}

输出:

小组1的总销售额为:23 万元
小组2的总销售额为:66 万元
小组3的总销售额为:130 万元
公司的总销售额为:219  万元

上述代码中,定义了一个二维数组,用于存储三个销售小组的销售额。然后,使用两个for循环,外层循环控制销售小组,内层循环控制每个小组的销售额。在内层循环中,使用变量groupSum记录每个小组的销售额,并将其累加到变量sum中。最后,输出每个小组的销售额和公司的总销售额。