JavaSE3️⃣程序基础 - 流程控制&数组操作

1、流程控制

在 Java 中,分号 ; 作为语句结束。

使用流程控制语句,可实现条件判断、循环、程序跳转等功能。

1.1、输入输出

Java 内置 System 类中,提供了输入输出相关功能。

  • System.out:标准输出流。
  • System.err:标准错误输出流。
  • System.in:标准输入流。

1.1.1、out

标准输出流

  1. println()打印并换行(print line)。

    System.out.println("A");
    System.out.println("B");
    /* 输出内容
    A
    B
    
    */
    
  2. print()打印

    System.out.print("A");
    System.out.print("B");
    
    /* 输出内容
    AB
    */
    
  3. printf()格式化打印(format)。

    1. 占位符%):按指定格式打印内容。

      占位符 说明
      %d 输出十进制整数
      %x 输出十六进制整数
      %f 输出浮点数
      %e 输出科学计数法表示的浮点数
      %s 字符串
    2. 示例

      // 整数:23
      System.out.printf("整数:%d", 23);
      
      // 十六进制:1e
      System.out.printf("十六进制:%x", 30);
      
      // 浮点数:3.14
      System.out.printf("浮点数:%.2f", 3.1415);
      

1.1.2、err

标准错误输出流:用于打印错误消息、用户应立即注意的信息。

用法与 out 相同,区别是以红色字体输出。

// 整数:23
System.err.printf("整数:%d", 23);

// 十六进制:1e
System.err.printf("十六进制:%x", 30);

// 浮点数:3.14
System.err.printf("浮点数:%.2f", 3.1415);

1.1.3、in

标准输入流:需要结合 Scanner(简单的文本扫描程序)使用。

  1. 导包java.util.Scanner
  2. 创建对象:传入标准输入流作为参数。
  3. 读取用户输入
    1. next()
    2. nextLine()
    3. nextInt(), nextDouble() ...
  4. 运行程序

示例:计算 BMI(公式 = 体重 / 身高2

import java.util.Scanner;

public class CalculateBMI {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入身高(m):");
        double height = scanner.nextDouble();
        System.out.print("输入体重(kg):");
        double weight = scanner.nextDouble();

        System.out.printf("BMI:%.2f", weight / (height * height));
    }
}

1.2、条件判断

1.2.1、if

① 语法

  1. if:若布尔表达式成立(true),执行代码块。

    if (布尔表达式) {
    	// 代码
    }
    
  2. if-else:若布尔表达式不成立(false),执行 else 代码块。

    if (布尔表达式1) {
    	// 代码
    } else {
        // 代码
    }
    
  3. 多重 if:依次判断布尔表达式,直到成立。

    if (布尔表达式1) {
    	// 代码1
    } else if (布尔表达式2) {
        // 代码2
    } else if (布尔表达式n) {
        // 代码n
    } else {
        // 代码3
    }
    

② 示例

  1. 判断成绩是否合格

    Scanner scanner = new Scanner(System.in);
    int score = scanner.nextInt();
    
    if (score >= 60) {
        System.out.println("合格");
    } else {
        System.out.println("不合格");
    }
    
  2. 判断成绩等级

    Scanner scanner = new Scanner(System.in);
    int score = scanner.nextInt();
    
    if (score < 60) {
        System.out.println("D");
    } else if (score < 80) {
        System.out.println("C");
    } else if (score < 90) {
        System.out.println("B");
    } else {
        System.out.println("A");
    }
    

③ 使用说明

  1. 使用

    1. 若代码块只包含一条语句,可省略 {}(不推荐使用)。
    2. if 是必须的,else 是可选的
  2. 条件范围:多重 if 语句中,小范围条件在前,大范围条件在后

  3. 临界值:根据业务需求,需要判断布尔表达式中的不等号是否取临界值 =

  4. 不同数据类型的判断相等

    1. 基本类型==(浮点数除外,需要判断差值是否小于很小的值)

    2. 引用类型equals(),注意 NPE 问题。

      // 基本类型
      int score = 60;
      if (score == 60) {
          // ...
      }
      
      // 基本类型——浮点数
      double base = 0.00001;
      double x;
      if (Math.abs(x - 0.1) < base) {
          System.out.println("x 是 0.1");
      }
      
      // 引用类型:短路运算符&&避免NPE
      String str = "Hello";
      if (str != null && str.equals("Hello")) {
          // ...
      }
      

1.2.2、switch

① 语法

  1. 根据表达式计算结果,匹配相应的 case 并跳转执行。

  2. 执行 case 中的代码,直到关键字 break 结束。

  3. 若没有匹配到任何 case 结果,执行 default 代码块(若有)。

    switch (表达式) {
        case 情况1:
            // 代码1
            break;
        case 情况2:
            // 代码2
            break;
        default:
            // 默认代码
            break;
    }
    

② 示例

System.out.println("请选择游戏选项:")
int option = scanner.nextInt();

switch (option) {
    case 1:
        System.out.println("1-单人游戏");
        break;
    case 2:
        System.out.println("2-双人游戏");
        break;
    case 3:
        System.out.println("3-退出游戏");
        break;
    default:
        System.out.println("输入有误");
        break;
}

③ 使用说明

  1. 使用:在选项较多的情况下,使用 switch-case多重 if 结构更清晰。
  2. case 的特点
    1. 穿透性:若没有使用 break 结束 case 语句块,默认会执行之后所有 case 代码块。
    2. 顺序:在正确使用 break 的基础上,不需要考虑多个 case 的顺序。
  3. switch 版本特性
    • 5-:支持 byte, short, int, char 及其包装类型。
    • 5:支持 switch 枚举。
    • 7:支持 switch 字符串。
    • 12:引入新语法。
      • switch 可返回值,case 无需 break 语句。
      • 引入 yield 关键字用于返回值。

1.3、循环

指定循环条件,满足时执行循环,不满足时跳出。

1.3.1、while

先判断条件,再执行循环体。

  1. 语法:每次执行循环前,判断条件是否成立。

    • true:执行一遍循环体。

    • false:跳到 while 循环末尾,执行后续代码。

      while (布尔表达式) {
      	// 循环体
      }
      // 后续代码
      
  2. 至少执行次数:1 次布尔表达式计算,0 次循环体

  3. 注意

    1. 计数器:先执行代码逻辑,再更新计数器。
    2. 死循环:若 while 条件有误,可能导致程序死循环,CPU 占满。

示例:计算从 low 到 high 的所有整数之和。

int low = 100, high = 300;

int sum = 0;
int i = low; // 计数器

// while计算
while (i <= high) {
    sum += i;
    i++;
}
System.out.println(sum);

// 验证答案
int result = (low + high) * (high - low + 1) / 2;
System.out.println(result);

1.3.2、do-while

先执行循环体,再判断条件。

  1. 语法:每次循环中先执行循环体,再判断条件是否成立。

    • true:执行一遍循环体。

    • false:跳到 do-while 循环末尾,执行后续代码。

      do {
      	// 循环体
      } while (布尔表达式);
      
  2. 至少执行次数1 次循环体,1 次布尔表达式计算。

  3. 注意:计数器的正确使用、死循环的避免。

示例:计算从 low 到 high 的所有整数之和。

int low = 100, high = 300;

int sum = 0;
int i = low;

// while计算
do {
    sum += i;
    i++;
} while (i <= high);
System.out.println(sum);

// 验证答案
int result = (low + high) * (high - low + 1) / 2;
System.out.println(result);

1.3.3、for

使用计数器

  1. 语法:初始化计数器,每次循环前判断条件是否成立。

    • true:执行循环体,更新计数器。

    • false:跳到 for 循环末尾,执行后续代码。

      // 简单循环
      for (初始化语句; 结束条件; 更新语句) {
          // 循环体
      }
      
      // 嵌套循环
      for (初始化语句; 结束条件; 更新语句) {
          for (初始化语句; 结束条件; 更新语句) {
              // 循环体
          }
      }
      
  2. 至少执行次数

    • 1 次初始化语句(若有)。
    • 1 次结束条件判断(若有)。
    • 0 次循环体,0 次更新语句。
  3. 注意

    1. 应避免过多层级的嵌套 for 循环。
    2. 临界值:根据业务需求,需要判断初始化条件和结束条件是否取等号 =
    3. 灵活性:for 可以缺少初始化语句、结束条件、更新语句中的任意一个或多个。
    4. 计数器更新:若定义了更新语句,则尽量避免在循环体中手动更新计数器。
    5. 功能强化:Java 5 引入增强 for 循环(foreach),简化可迭代数据类型(如数组、集合)的遍历操作。

示例

  1. 计算从 low 到 high 的所有整数之和。

    int low = 100, high = 300;
    
    int sum = 0;
    
    // while计算
    for (int i = low; i <= high; i++) {
        sum += i;
    }
    System.out.println(sum);
    
    // 验证答案
    int result = (low + high) * (high - low + 1) / 2;
    System.out.println(result);
    
  2. 输出数组中的所有元素。

    String[] array = {"A", "B", "C"};
    
    // for
    for (int i = 0; i < array.length; i++) {
        System.out.println(array[i]);
    }
    // foreach
    for (String str : array) {
        System.out.println(str);
    }
    

1.4、跳转

  1. 使用在循环体中使用,跳出循环

    1. 通常配合 if,在满足条件时跳出循环。
    2. 嵌套循环中,只跳出当前一层
  2. 关键字

    1. break:跳出当前循环。
    2. continue:提前结束本轮循环,执行下一轮。
  3. 示例

    for (int i = 1; ; i++) {
        // 跳过偶数
        if (i & 2 == 0) {
            continue;
        }
    
        // 结束循环
        if (i == 50) {
            break;
        }
    }
    
    // 嵌套循环
    for (int i = 1; i < 10; i++) {
        for (int j = 1; j < 10; j++) {
            if (...) {
                break;
            }
        }
        // break跳到这里
    }
    

2、数组操作

2.1、遍历

遍历(traverse):通过索引下标,访问数组的每一个元素。

2.1.1、一维数组

按实际需求,选择适合的遍历形式。

  1. for:通过索引访问元素。

    int[] nums = {1, 2, 3, 4, 5};
    
    for (int i = 0; i < nums.length; i++) {
        System.out.print(nums[i] + " ");
    }
    
  2. foreach:按顺序访问元素。

    for (int num : nums) {
        System.out.print(num + " ");
    }
    
  3. Arrays.toString():将数组内容转换成字符串形式。

    System.out.println(Arrays.toString(nums));
    

2.1.2、二维数组

按实际需求,选择适合的遍历形式。

  1. 双层 for:通过索引访问元素。

    int[][] nums = {
        {1, 2, 3},
        {4, 5, 6, 7},
        {8, 9}
    };
    
    for (int i = 0; i < nums.length; i++) {
        for (int j = 0; j < nums[i].length; j++) {
            System.out.print(nums[i][j] + " ");
        }
        System.out.println();
    }
    
  2. 双层 foreach:按顺序访问数组/元素。

    for (int[] num : nums) {
        for (int n : num) {
            System.out.print(n + " ");
        }
        System.out.println();
    }
    
  3. 结合 for/foreach

    for (int i = 0; i < nums.length; i++) {
        for (int num : nums[i]) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
    
    for (int[] num : nums) {
        for (int j = 0; j < num.length; j++) {
            System.out.print(num[j] + " ");
        }
        System.out.println();
    }
    
  4. Arrays.deepToString():将数组内容转换成字符串形式。

    System.out.println(Arrays.deepToString(nums));
    

2.2、排序

排序(sort):将数组元素按一定规则进行排列,会修改数组内容。

常用排序方式:冒泡、插入、归并、快排、堆....

2.2.1、冒泡排序

  1. 特点:每轮循环中,依次比较相邻的两个元素,若顺序错误则交换。
  2. 命名由来:每个元素都像气泡一样,在每次循环后最大(最小)的元素浮到数组的末尾。

示例:升序排序。

  1. 双层 for:外层代表循环次数,内层用于依次比较相邻元素。

  2. 临界条件

    1. 外层:前 n - 1 次循环即可完成排序,第 n 次循环无意义(只有一个元素,无需比较)
    2. 内层:每经过一轮循环,新一轮中需要比较的元素个数 - 1。
  3. 交换:定义临时变量 tmp 进行交换。

    int[] nums = {10, 5, 37, 20, 3, 1, 58};
    
    // 冒泡排序
    for (int i = 0; i < nums.length - 1; i++) {
        for (int j = 0; j < nums.length - 1 - i; j++) {
            if (nums[j] > nums[j + 1]) {
                int tmp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = tmp;
            }
        }
    }
    

2.2.2、Arrays.sort()

Arrays 工具类提供 sort() 方法,数组长度 n 决定排序方式。

插入/快排/归并

结论👉 源码:Arrays.sort()

  1. [1, 47):插入
  2. [47, 286):快排
  3. [286, +∞)
    1. 无结构:快排
    2. 有结构:归并

2.3、命令行参数

main 方法:Java 程序的入口

  1. 方法参数列表:一个 String 数组,用于接收命令行参数。
  2. 使用方式
    1. 通过命令行方式运行 Java 程序时,JVM 会接收用户输入的参数,传给 main 方法。
    2. 由程序员自行编写相应的解析规则。

示例:传入版本

  1. 编写程序

    public class MyMain {
        public static void main(String[] args) {
            for (String arg : args) {
                if ("-version".equals(arg)) {
                    // do something ...
                    break;
                }
            }
        }
    }
    
  2. 编译并运行:打开 MyMain 所在的命令行窗口。

    # 编译
    javac MyMain.java
    # 运行:传入参数
    java MyMain -version
    
  3. args:JVM 接收 -version,传给 main 方法

    // args内容:["-version"]
    
  4. 程序遍历 args 数组,找到 -version,执行代码

    // do something ...
    break;
    
posted @ 2022-12-26 00:10  Jaywee  阅读(40)  评论(0编辑  收藏  举报

👇