Java基础-数组的使用

导读:本篇文章讲解 Java基础-数组的使用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

数组的定义

数组就是用来存储一批同种类型数据的内存区域(可以理解成容器)。

我们简单的认识一下数组:

// 20, 10, 80, 60, 90
int[] arr = {20, 10, 80, 60, 90};

// 牛二, 西门, 全蛋
String[] names = {"牛二", "西门", "全蛋"};

那关于数组我们需要学会什么

  1. 在程序中如何去定义数组存储数据,具体格式是什么样的
  2. 怎么去获取,修改数组中的数据
  3. 怎么结合数组解决一些实际业务
  4. 数组在内存中具体是怎么去工作的
  5. 避免入坑,同时可以在出现问题后立即排查问题所在

静态初始化数组

静态初始化数组: 定义数组的时候直接给数组赋值。

静态初始化数组的格式如下:

  • 完整格式: 数据类型[] 数组名 = new 数据类型[] {元素1, 元素2, 元素3, ...};
double[] scores = new double[]{89.9, 99.5, 59.5, 88.0};
int[] ages = new int[]{12, 24, 36}
  • 简化格式: 数据类型[] 数组名 = { 元素1,元素2 ,元素3,… };
int[] ages = {12, 24, 36};
  • 在内存中的表现如下

在这里插入图片描述

注意:数组变量名中存储的是数组在内存中的地址,数组是引用类型。


数组的访问

数组元素的访问格式: 数组名称[索引]

  • 索引从0开始, 索引0代表第一个数组元素, 以此类推
public static void main(String[] args) {
    int[]  ages = {12, 24, 36};

  	// 获取数组元素
    System.out.println(ages[0]); // 12
    System.out.println(ages[1]); // 24
    System.out.println(ages[2]); // 36
  
  	// 获取数组元素并且重新赋值
  	ages[2] = 40;
    System.out.println(ages[2]); // 40
}

数组的长度属性: 数组名称.length

// 获取数组的长度(也就是数组元素的个数)
System.out.println(ages.length); // 3
  • 那么数组的最大索引值该怎么表示? 其实长度减一就是最大索引值
System.out.println(ages.length - 1); // 2

在这里插入图片描述


数组的注意事项

数据类型[] 数组名也可以写成 数据类型 数组名[]

int[] ages =...;  
int ages[] =...;  

double[] scores = ...;
double scores[] = ...;

什么类型的数组只能存放什么类型的数据,否则报错。

// 错误写法, 不能放其他数据类
int[] arr = new int[]{10, 20, "kaisa"}

数组一旦定义出来,程序执行的过程中,长度、类型就固定了


动态初始化数组

动态初始化数组: 定义数组的时候只确定元素的类型和数组的长度,之后再存入具体数据。

数组的动态初始化格式: 数组类型[] 数组名称 = new 数据类型[数组长度]

// 先确定元素的类型和数组的长度
int[] arr = new int[3];

// 再赋值
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
System.out.println(arr[0]); // 10
System.out.println(arr[1]); // 20
System.out.println(arr[2]); // 30

元素默认值规则: 当我们有定义数组的长度和类型, 没有赋值时, 数组元素的默认值遵守以下规则

数据类型 明细 默认值
基本类型 byte、short、char、int、long 0
基本类型 float、double 0.0
基本类型 boolean false
引用类型 类、接口、数组、String null

两种初始化的的使用场景总结、注意事项说明:

  • 动态初始化只指定数组长度,后期赋值,适合开始知道数据的数量,但是不确定具体元素值的业务场景。
  • 静态初始化开始就存入元素值,适合一开始就能确定元素值的业务场景。
  • 两种格式的写法是独立的,不可以混用

数组的遍历

数组的遍历介绍:

  • 数组遍历: 就是一个一个的访问数组的所有元素
  • 为什么要遍历? 搜索, 数据统计等等都需要用到遍历

我们可以使用for循环遍历数组, 如下:

public static void main(String[] args) {
    int[] nums = {10, 20, 30, 40};

    for (int i = 0; i < nums.length; i++) {
        System.out.println(nums[i]);
    }
}

案例: 遍历数组求和

需求: 某部门5名员工的销售额分别是:16、26、36、6、100,请计算出他们部门的总销售额。

分析:

  • 把这5个数据放到数组中
  • 遍历数组中每个元素, 然后在外面定义求和变量把他们累加起来。

代码演示:

public static void main(String[] args) {
    int totalMoney = 0;
    int[] money = {16, 26, 36, 6, 100};

    for (int i = 0; i < money.length; i++) {
        totalMoney+=money[i];
    }

    System.out.println(totalMoney); // 184
}

案例: 数组元素求最大值

例如我们有一个int类型数组, 我们如何求出数组元素中的最大值

分析:

  • 把颜值数据拿到程序中去,用数组装起来。
  • 定义一个变量用于记录最大值,这个变量建议默认存储第一个元素值作为参照
  • 遍历数组的元素,如果该元素大于变量存储的元素,则替换变量存储的值为该元素
  • 循环结束后输出最大值变量即可。

演示代码:

public static void main(String[] args) {
    int[] nums = {168, 120, 68, 68, 931, 654, 264};

    // 定义一个变量保存最大值
    int max = 0;

    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > max) {
            max = nums[i];
        }
    }

    // 输出最大值
    System.out.println(max);
}

数组的排序

数组排序: 就是对数组中的元素,进行升序(由小到大)或者降序(由大到小)的操作。

数组排序的技术:

  • 冒泡排序

  • 选择排序

  • 快速排序

  • 插入排序

数组搜索相关的技术:

  • 二分搜索

  • 分块查找

  • 哈希表查找

目前我们先学习冒泡排序

冒泡排序的思想:

  • 每次从数组中找出最大值放在数组的后面去。

实现冒泡排序的关键步骤分析:

  • 确定总共需要做几轮:数组的长度-1
  • 每轮比较几次: 数组的长度 - 数组的第几轮
  • 当前位置大于后一个位置则交换数据

在这里插入图片描述

演示代码:

public static void main(String[] args) {
    int[] nums = {168, 120, 68, 68, 931, 654, 264};

    // 设置变量用于替换数组元素位置
    int transfer = 0;

  	// 定义一个外部循环控制总共需要冒几轮
    for (int i = 1; i < nums.length - 1; i++) {
      	// 定义一个内部循环,控制每轮依次往后比较几个位置
        for (int j = 0; j < nums.length - i); j++) {
            // 满足条件则替换数组元素位置
            if (nums[j] > nums[j+1]) {
                transfer = nums[j];
                nums[j] = nums[j+1];
                nums[j+1] = transfer;
            }
        }
    }

    // 循环遍历数组
    for (int i = 0; i < nums.length; i++) {
        System.out.println(nums[i]);
    }
}

数组的内存

Java 中内存分配为如下几种:

  • 方法区
  • 本地方法栈
  • 寄存器

我们只需要学习前三种

  • 方法区: 字节码文件加载时进入的内存

  • 栈内存: 方法运行时所进入的内存变量也是在这里

  • 堆内存: new 出来的东西会在这块内存中开辟空间并产生地址

例如有如下代码:

public class Test {
  public static void main(String[] args) {
  	int a = 10;
    
		int[] arr = new int[]{11, 22, 33};
    
  	System.out.println(arr[0]);
  	System.out.println(arr[1]);
	  System.out.println(arr[2]);
	}
}

  • Test类和main方法会放在方法区, 然后运行main方法会在栈内存中运行

  • 定义的变量a, 会直接在栈内存中保存变量a的值

  • 定义的数组, 会在堆内存中开辟一块空间, 用于保存数组的元素, 而栈内存中保存的是指向堆内存中数组的地址

下面我用一幅图展示在内存中的表现吧

在这里插入图片描述

我们再来看一段代码:

public class Test2{
  public static void main(String[] args) {
    int[] arr1 = {11, 22, 33};
    int[] arr2 = arr1;

    // 两个数组指向堆内存中同一个地址
    System.out.println(arr1); // [I@776ec8df
    System.out.println(arr2); // [I@776ec8df

    // 改变一个数组元素的值, 另一个也会改变
    arr2[1] = 99;
    System.out.println(arr1[1]); // 99
    System.out.println(arr2[1]); // 99
	}
}
  • 这是因为数组arr1和arr2在栈内存中保存的地址是一样的, 我们来看看内存图吧

在这里插入图片描述

数组使用常见问题

问题1:如果访问的元素位置超过最大索引,执行时会出现ArrayIndexOutOfBoundsException(数组索引越界异常)

int[] arr = new int[]{11, 22, 33};

System.out.println(arr[2]); // 正常访问

// System.out.println(arr[3])  // 出现异常 
  • 会出现ArrayIndexOutOfBoundsException异常

问题2:如果数组变量中没有存储数组的地址, 而是null, 在访问数组信息时会出现NullPointerException(空指针异常)

arr = null;
System.out.println(arr); // null

// System.out.println(arr.length)  // 出现异常 
  • 会出现NullPointerException异常

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/120110.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!