JavaSE 04 数组

1、数组

用于保存一组数的容器。

2、数组的优点

⑴ 代码简洁,同时开辟一组空间。
⑵ 数组的空间是连续的。
⑶ 分类存储,查找方便。

3、数组的特点

⑴ 数组的声明时,数据类型可以是基本数据类型,也可以是引用数据类型。
⑵ 数据类型已经声明后,其保存的数据类型必须一致。
⑶ 数据本身属于引用数据类型,所以其遵循引用数据类型的存储和使用的特点
⑷ 数组名存放在栈中,里面保存了堆中的一组连续空间的首项 [0] 的地址值。数组元素保存在堆中,且是连续的。
基本数据类型和引用数据类型在内存中的保存

4、数组的四要素

数据类型 数组名 数组元素(可以是多个) 下标(0 ~ 数组长度 - 1)

5、访问数组的元素

数组名[下标]

6、数组的声明和使用

⑴ 声明: ① 数据类型[ ] 数组名;
② 数据类型 数组名[ ];
示例: int[ ] arr; // 告诉内存要开辟一串空间,数据类型为int类型,数组名【引用名】为arr。但这是还没有真正开辟空间
⑵ 开辟空间
数组名 = new 数据类型[数组长度];
示例: arr = new int[5];
⑶ 赋值
数组名[下标] = 值;
示例:arr[0] = 10;
⑷ 使用
数组名[下标];
示例:System.out.println(arr[0]); // 10

注意:① 第⑴、⑵步可以合为一步:
数据类型[ ] 数组名 = new 数据类型[数组长度];
示例: String[ ] strs = new String[10];
②下标必须在数组长度的范围之内,否则会报异常:ArrayIndexOutOfBoundsException
③ 数组声明并开辟长度时,必须指定数组的长度,否则会报错:缺少数组维。
④ 数组如果没有显式地赋值,则系统将为其赋予默认值:
int 0
double 0.0
char ‘\u0000’
boolean false
String null
⑤ 声明并初始化数组元素值,可以合并在一起:
double[ ] scores = new double(){2.4, 4.5, 5.6, 7.8};

int[ ] numbers = {2, 23, 34, 48, 23};
但是:
int[ ] num;
num = {2, 234, 34, 72};
这是错误的!(错误: 非法的表达式开始)

7、数组使用的类型

⑴ 静态初始化:


① 步骤1:声明数组并初始化数组元素的值
示例:int[ ] numbers = {2, 3, 45, 76, 21};
② 步骤2:使用
示例:System.out.println(numbers[0]);

⑵ 动态初始化:


① 步骤1:声明数组并开辟长度
示例:String[ ] strs = new String[5];
② 步骤2:给数组元素赋值
示例:strs[0] = “ABC”; strs[1] = “DNF”; strs[3] = “Good”
③ 步骤3:使用
示例:System.out.println(strs[1]);

8、数组的简单使用

⑴ 循环打印


数据类型[ ] 数组名 = new 数组类型[ ]{元素值1, 元素值2, …, 元素值n};
for(int i = 0 ;i < 数组名.length; i++){
System.out.println(数组名[i]);
}

示例:
String[ ] strs = new String[ ]{“ABC”, “DNF”, “GOOD”, “Happy”, “Import”};
for (int i = 0 ; i < strs.length; i++) {
System.out.println(strs[i]);
}

⑵ 求和


注意:数据类型需要为数值型
数据类型[] 数组名 = {元素值1, 元素值2, …, 元素值n};
int sum = 0;
for(int i = 0; i < 数组名.length; i++){
sum += 数组名[i];
}

示例:      int[] numbers = {23, 15, 82, 23, 93, 28};
            int sum = 0;
            for (int i = 0; i < numbers.length; i++) {
              sum += numbers[i];
            }
            System.out.println("和为:" + sum); // 和为:264

⑶ 求最值

  注意:数据类型需要为数值型

  ① 求最大值
     示例:
      int[] numbers = {223, 135, 820, 213, 193, 128};
      int max = numbers[0]; // 注意:这里需要<b>将最大值默认为数组的第一个元素【角标为0】</b>
      for (int i = 1; i < numbers.length; i++) { // 因为最大值(max)的声明时,已经将数组的第一个元素的值赋值给了max。所以这里就<b>从角标1开始【即第二个元素】</b>
        if (numbers[i] > max) { // 如果遇到了比max大的值,就更新max
          max = numbers[i];
        }
      }
      System.out.println("最大值为:" + max); // 最大值为:820

  ② 求最小值,并附带角标
     示例:
       int[] nums = {23, 34, 28, 29, 19, 9, 23, 11};
       int min = nums[0];
       int index = 0; // 这里用index变量来保存角标
       for (int i = 1;i < nums.length; i++) {
         if (nums[i] < min) {
           min = nums[i];
           index = i; // 当找到比min小的元素值时,就更新index所保存的角标的值
         }
       }
       System.out.println("最小值为:" + min + ", 其角标为:" + index); // 最小值为:9, 其角标为:5

⑷ 查找

示例:

      import java.util.Scanner;

      Scanner input = new Scanner(System.in);
      String[] usernames = {"Tom", "John", "White", "Danny", "Conan"}; // 定义一个数组名为usernames的数组,里面静态赋值了5个元素值

      System.out.print("请输入用户名:");
      String name = input.next(); // 用于保存用户输入的用户名

      int i = 0; // 这个for循环的循环变量初始值可以放在循环的外面,循环结束后打印输出角标
      for (; i < usernames.length; i++) {
        if (name.equals(usernames[i])) {  // 逐一匹配姓名
          System.out.println("欢迎登录 " + name + "!");
          break; // 找到了就退出循环
        } else if (i == usernames.length - 1) { // 到了usernames数组的最后一项【Conan】,还是没有匹配到
          System.out.println("没有找到该用户!");
        }
      }

      if (i < 5) { // i等于5时,就是没有匹配到姓名【当匹配到时,因为if中有break,所以i就不会再执行i++,所以i这时就等于角标值】
        System.out.println("角标 : " + i);
      }

      input.close();

⑸ 排序 【冒泡排序】

思想:先从角标0开始,让角标0和角标1比较,让较大的那个放到后面。然后让角标1和角标2比较,也让较大的那个放到后面。这样依次比较,<b>最终达到从小到大的排序效果</b>。

    示例:
        int[] nums = {31, 21, 16, 18, 36};  将这个数组从小到大排序
    分析:① 这个nums数组的长度为5,所以需要排序4次。
          ② 第一次排序需要交换4次;第二次排序需要交换3次;第三次排序需要交换2次;第四次排序需要交换1次。

          排序次数             交换次数
              1                  4
              2                  3
              3                  2
              4                  1
          ③ 所以需要使用嵌套for循环来实现排序功能。

    模版:
        for(int i = 1; i < 数组长度; i++){
          for(int j = 0; j < 数组长度 - i; j++){
            根据相邻两个元素值的“大小”,来交换数组[j]和数组[j + 1]的位置
          }
        }

    用嵌套for循环实现上述示例:
       for(int i = 1; i < nums.length; i++){
         for(int j = 0; j < nums.length - i; j++){
           if(nums[j] > nums[j + 1]){
             nums[j] += nums[j + 1];
             nums[j + 1] = nums[j] - nums[j + 1];
             nums[j] = nums[j] - nums[j + 1];
           }
         }
       }

    输出效果:
       排序前:
        31      21      16      18      36
       排序后:
        16      18      21      31      36

9、数组的复杂使用

⑴ 数组的赋值


语法: int[ ] arr1 = {23, 34, 12, 10, 8, 32};
            int[ ] arr2;
            arr2 = arr1; // 数组的赋值

注意:① 基本数据类型赋值时,赋的是一个值(即变量值),而其中一个的改变不会影响到另外一个。
引用数据类型赋值时,赋的是一个地址,二者共同引用同一个空间,其中一个的改变会影响到另外一个

示例: (继续上面的语法代码)

   System.out.println("修改数组arr2前的arr1:");
   for(int j = 0; j < arr1.length; j++){
     System.out.print(arr1[j] + "\t");
   }

   for(int i = 1; i < arr2.length; i += 2){
     arr2[i] = i;
   }

   System.out.println("\n修改数组arr2后的arr1:");
   for(int j = 0; j < arr1.length; j++){
     System.out.print(arr1[j] + "\t");
   }
   System.out.println("\n修改数组arr2后的arr2:");
   for(int j = 0; j < arr2.length; j++){
     System.out.print(arr2[j] + "\t");
   }

输出结果:
修改数组arr2前的arr1:
23    34    12    10    8    32
修改数组arr2后的arr1:
23     1     12    3      8     5
修改数组arr2后的arr2:
23     1     12    3      8     5

因为修改数组arr2后,数组arr1中的元素的值也跟着改变了,所以数组(引用数据类型)的赋值,赋的是地址值。
基本数据类型和引用数据类型的赋值

如果不想出现修改其中一个数组的元素值,另外一个数组的元素值也跟着改变的情况,则需要: 另外开辟一块新的空间,将其中一个数组循环赋值给另外一个数组。
代码:
数据类型[ ] 数组1 = {元素值1, 元素值2, …, 元素值n};
数据类型[ ] 数组2 = new 数据类型[数组1.length];
for(int i = 0; i < 数组1.length; i++){
  数组2[i] = 数组1[i];
}

⑵ 数组的反转


① 方法一【借助于中间变量】:
将数组循环,交换开头和结尾的对应位置,直到数组长度的一半为止。
② 方法二【借助新的数组】:
⒈新建一个长度和旧数组长度一样的新数组;⒉将旧数组倒着赋值给新数组;⒊再将新数组的地址值赋值给旧数组。

 示例:
    int[] nums = {19, 23, 35, 47, 56, 68};
    System.out.println("原数组:");
    for (int i = 0; i < nums.length; i++) {
      System.out.print(nums[i] + "\t");
    }

    System.out.println("\n方法一【借用中间变量】:"); // 借用中间变量,来交换元素的位置

    int temp; // 中间变量,在交换数组元素位置时,用于暂时保存元素值
    for (int i = 0, j = nums.length - 1; i < nums.length / 2; i++, j--) { // 只需要交换到数组长度的一半位置即可(奇数长度为:除以2的结果舍掉小数)
      temp = nums[i];
      nums[i] = nums[j];
      nums[j] = temp;
    }

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

    System.out.println("\n方法二【借用新数组】:"); // 借用新数组

    int[] numsNew = new int[nums.length];
    for (int i = nums.length - 1, j = 0; i >= 0; i--, j++) { // 将旧数组倒着赋值给新数组
      numsNew[j] = nums[i];
    }
    nums = numsNew; // 将新数组的地址值赋值给旧数组

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

 输出结果:
      原数组:
      19      23      35      47      56      68
      方法一【借用中间变量】:
      68      56      47      35      23      19
      方法二【借用新数组】:
      19      23      35      47      56      68

⑶ 数组的添加【在数组的尾部添加】


数组的长度一旦固定,就不能再次更改。所以所有数组的添加都要新建数组。
添加步骤:① 创建一个新的数组,长度为旧数组长度 + 1。
② 遍历旧的数组,并赋值到新的数组。数组角标一一对应。
③ 新数组的尾部(length - 1) = 要添加的元素。
④ 将新数组的地址值赋值给旧的数组。

 示例: int[] nums = {23, 54, 31, 34};

        int[] numsNew = new int[nums.length + 1]; // 新建一个长度比旧数组长度多1的新数组 ①
        for(int i = 0; i < nums.length; i++){ // 循环遍历旧数组,并将元素值一一对应地复制给新数组 ②
          numsNew[i] = nums[i];
        }

        int add = 10; // 要插入的数组元素 ③
        numsNew[numsNew.length - 1] = add;

        nums = numsNew; // 将新数组的地址值赋值给旧数组。 ④

     遍历nums的结果为:23      54      31      34      10

⑷ 数组的添加【创建数组时,开辟足够长的长度】


添加步骤:① 新建足够长的数组。
② 定义一个记录当前数组元素总量的int类型的变量。
③ 在添加元素之前,先要判断当前记录元素总量的变量是否已经等于或大于数组的长度。如果大于,则不要添加,否则下角标越界。
④ 添加新元素的方法为:数组名[记录元素总量的变量] = 元素;
⑤ 每添加一个新的元素,就让记录元素总量的变量加1。
示例:
int[] nums = new int[100]; // 假定100够用了
int total = 0; // 记录nums数组的元素总量【当前 为0个】

if(total >= nums.length){ // 判断是否已经无法再添加元素了
     return;
}

nums[total] = 10; // 添加元素
total++; // 让total加1

⑸ 数组的插入


插入步骤:① 创建一个新数组,长度比旧数组长度多1。
② 将旧数组的元素值循环赋值给新数组。
③ 新数组: 从要插入的 index角标位置的下一位开始, 循环将元素向后移动一位
④ 将要插入数组元素,赋值给新数组[index]。
⑤ 将新数组的地址值赋值给旧数组。

   示例: String[] names = {"John", "White", "Tom", "Danny"};
            String[] namesNew = new String[names.length + 1]; // ①
            for(int i = 0; i < names.length; i++){ // ②
              namesNew[i] = names[i];
            }

            String addName = "Bill"; // 要插入的数组元素
            int index = 2; // 要插入的角标位置
            for(int j = namesNew.length - 1; j > index; j--){ // ③
              namesNew[j] = namesNew[j - 1];
            }

            namesNew[index] = addName; // ④
            names = namesNew; // ⑤

      遍历names的结果为:John    White   Bill    Tom     Danny

⑹ 数组元素的删除


删除步骤:① 首先找到要删除的数组元素的所在位置(找下标)。
② 从要删除的元素的位置开始,循环前移每个元素的位置。 直到倒数第二个数组元素。
③ 将数组的最后一个元素赋为初始值(null、false或0 等)。

示例:

public class Test {

public static void main(String[] args) {
int[] nums = {23, 31, 49, 29, 3, 19};

for (int a = 0; a < nums.length; a++) { 
  System.out.print(nums[a] + "\t"); // 23      31      49      29      3       19
}

System.out.println();

int num = 49; // 假定要删除49,这个数组元素

int index = 0;
for (int i = 0; i < nums.length; i++) {
  if (num == nums[i]) {
    index = i;
    break;
  }
}

for (int j = index; j < nums.length - 1; j++) {
  nums[j] = nums[j + 1];
}
nums[nums.length - 1] = 0;

int[] newNums = new int[nums.length - 1];
for (int k = 0; k < newNums.length; k++) {
  newNums[k] = nums[k];
}
nums = newNums;

for (int a = 0; a < nums.length; a++) {
  System.out.print(nums[a] + "\t"); // 23      31      29      3       19
}
System.out.println();
}
}

10、二维数组

可以称为多个一维数组的组合。
int[ ][ ] nums;
也可以写成:int[ ] nums[ ];【配合着内存图,就可以很清楚地理解二维数组是什么】

Java也支持三维、四维…
int[ ][ ][ ] nums;
int[ ][ ][ ][ ] nums;

二维数组在内存中的存储

特点:
⑴ 同样地,二维数组也具备四要素(数据类型,数组名,数组元素,下标【行下标和列下标,都是从0开始】)。
⑵ 访问二维数组中的某个元素,需要通过
数组名[行下标][列下标] 来访问。
⑶ 数组名.length 来获取二维数组的长度(行数);
数组名[行数].length可以获取某一行的列数。

11、二维数组的声明和使用

⑴ 动态初始化:

① 声明并开辟长度(二维数组的长度)。
   ⒈ 知道行数和列数:
    数据类型[ ][ ] 数组名 = new 数据类型[行数][列数];
    2.不知道列数:
    数据类型[ ][ ] 数组名 = new 数据类型[行数][ ];

  注意:列数可以省略,但是行数不能省略。

② 赋值:
  ⒈ 固定列数:
     for(int i = 0; i < 数组名.length; i++){
       for(int j = 0; j < 数组名[i].length; j++){
          数组名[i][j] = 元素值;
       }
     }

  ⒉ 不固定列数:
      for(int i = 0; i < 数组名.length; i++){
        数组名[i] = new 数据类型[数组长度];
        for(int j = 0; j < 数组名[i].length; j++){
          数组名[i][j] = 元素值;
        }
      }

   ③ 使用:
      for(int i = 0; i < 数组名.length; i++){
        for(int j = 0; j < 数组名[i].length; j++){
          数组名[i][j]; // 数组元素
        }
      }

⑵ 静态初始化:


数据类型[ ][ ] 数组名 = new 数据类型{{ … }, { … }, { … }, …};

数据类型[ ][ ] 数组名 = {{ … }, { … }, { … }, …};

12、增强for循环

属于一种循环机制,是JDK5.0之后出现的新特性。
它可以遍历集合或数组。

语法: for(元素的数据类型 元素名 : 数组名){
元素名 // 操作每一个元素
}

执行原理:每次从数组或集合中取出对应的元素,直到取不出元素为止。

特点:⑴ 每次只能移动一位。
⑵ 只能向下移动。
⑶ 只能访问,不能修改。

示例:
⑴ 遍历一维数组
int[] numbers = {23, 37, 48, 54, 30};
for(int number : numbers){
System.out.print(number + “\t”);
}
输出结果:23 37 48 54 30

 ⑵ 遍历二位数组
    char[][] chs = {{'a', 'b'}, {'c', 'd', 'e'}, {'f'}};

    for (char[] ch : chs) {
      for(char c : ch){
        System.out.print(c + "\t");
      }
      System.out.println();
    }

   输出结果: a       b
              c       d       e
              f
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值