为什么需要数组?
有时候需要存储或处理一系列数据,数组就可以充当这样的角色,它在内存中是相连的数据,并且在栈中的引用只有一个,如果不用数组,那数据就得一个一个定义一个一个声明,浪费内存空间,显然不合理。
什么是数组?
数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。 即:数(数据)组(一组)就是一组数据
Java的数组要求所有的数组元素具有相同的数据类型。因此,在一个数组中,数组元素的类型是唯一的,即一个数组里只能存储一种数据类型的数据,而不能存储多种数据类型的数据
数组本身是一个引用数据类型,数组内存储的类型可以是基本类型 也可以是引用类型
总结:
①数组是一个引用数据类型
②数组是在堆内存中的一串连续的地址存在
③数组在初始化时必须指定长度
⑤堆内存的数组长度一旦确定 不能再次发生改变
⑥栈内存的变量中存储的是数组的地址引用
⑦数组内部存储的类型可以是基本的 也可一是引用
数组的特点:
(1)数组是一个对象,是一种引用数据类型。可以表示一组数据的集合。
(2)数组只能保存一种类型的数据。
(3)数组可以使用 new 关键字 进行初始化。
(4)数组中的每一个数据称为 元素 element。元素是在堆内存中分配的。而且是连续分配的。
(5)数组的每一个元素都有一个序号,专业的称谓:下标、索引、角标。下标是从0开始的、升序的、连续的、0序的。
(6)数组有一个属性:长度的属性,表示数组中元素的个数 该属性是 int 类型。 通过 数组名.length 来访问该属性。
(7)数组中元素的下标的取值范围是:[0~length-1]。
(8)通过new 关键字 在堆内存中元素被分配空间之后。每个元素被jvm 赋予默认值。
默认值规则:整数:0 浮点数:0.0 char:’\u0000’ boolean:false 引用数据类型:null。
(9)数组的每个元素通过 数组名[下标] 来访问。每个元素都是一个变量。和变量的用法一致。
(10)数组变量、数组引用 保存的是 数组的实际元素的在堆内存中的"首地址"。
(11)[ ] 代表的是 数组这种类型。
(12)求下标是 n 的元素的地址:首地址+元素字节数*n。 数组根据下标访问元素的效率非常快。(随机访问)。
(13)数组的长度可以是 0,但是不能是 负数。
(14)数组的长度一旦确定,就不能更改了。数组是定长的。
数组的声明和创建:
1.首先必须声明数组变量,才能在程序中使用数组。
数据类型[] 变量名;//强烈建议用这种命名
数据类型 变量名[];//只要知道就可以,c、c++是这种写法,要区分开来
2.Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];
3.数组的元素是通过索引访问的,数组索引从0开始
4.获取数组长度的方法:arrays.length
//声明一个数组 int[] nums; //创建一个数组 nums = new int[10]; //给数组元素中赋值 nums[0]=1; nums[1]=2; nums[2]=3; nums[3]=4; System.out.println(nums.length);
数组快速入门(案例分析)
/* 它们的体重分别是 3kg,5kg,1kg,3.4kg,2kg,50kg 。 请问这六只鸡的总体重是多少?平均体重是多少? */ public class Array01 { //编写一个 main 方法 public static void main(String[] args) { // double hen1 = 3; // double hen2 = 5; // double hen3 = 1; // double hen4 = 3.4; // double hen5 = 2; // double hen6 = 50; // double totalWeight = hen1 + hen2 + hen3 + hen4 + hen5 + hen6; // double avgWeight = totalWeight / 6; // System.out.println("总体重=" + totalWeight + "平均体重=" + avgWeight); //比如,我们可以用数组来解决上一个问题 => 体验 // //定义一个数组 //解读 //1. double[] 表示 是 double 类型的数组, 数组名 hens //2. {3, 5, 1, 3.4, 2, 50} 表示数组的值/元素,依次表示数组的 // 第几个元素 // double[] hens = {3, 5, 1, 3.4, 2, 50, 7.8, 88.8,1.1,5.6,100}; //遍历数组得到数组的所有元素的和, 使用 for //解读 //1. 我们可以通过 hens[下标] 来访问数组的元素 // 下标是从 0 开始编号的比如第一个元素就是 hens[0] // 第 2 个元素就是 hens[1] , 依次类推 //2. 通过 for 就可以循环的访问 数组的元素/值 //3. 使用一个变量 totalWeight 将各个元素累积 System.out.println("===使用数组解决==="); //提示: 可以通过 数组名.length 得到数组的大小/长度 //System.out.println("数组的长度=" + hens.length); double totalWeight = 0; for( int i = 0; i < hens.length; i++) { //System.out.println("第" + (i+1) + "个元素的值=" + hens[i]); totalWeight += hens[i]; } System.out.println("总体重=" + totalWeight + "平均体重=" + (totalWeight / hens.length) ); } }
数组的使用
使用方式 1-动态初始化:
动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值
简单的来讲动态初始化就是指定长度
执行动态初始化时,程序员只需指定数组长度,即为每个数组元素指定所需的内存空间,系统将负责为这些数组元素分配初始值。
使用方式 2-动态初始化:
先声明数组
语法:数据类型 数组名[]; 也可以 数据类型[] 数组名;
int a[]; 或者 int[] a;
创建数组
语法: 数组名=new 数据类型[大小];
a=new int[10];
使用方式 3-静态初始化:
静态初始化:初始化时由程程序员显示指定每个数组元素的初始值,由系统决定数组长度
简单的来讲静态初始化就是指定内容
静态初始化就是将数组的元素放到大括号中,元素之间用逗号(,)分隔
数组使用注意事项和细节:
(1) 数组是多个相同类型数据的组合,实现对这些数据的统一管理
(2) 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。
(3) 数组创建后,如果没有赋值,有默认值
int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null
(4) 使用数组的步骤 1. 声明数组并开辟空间 2 给数组各个元素赋值 3 使用数组
(5) 数组的下标是从 0 开始的。
(6) 数组下标必须在指定范围内使用,否则报:下标越界异常,比如int [] arr=new int[5]; 则有效下标为 0-4
(7) 数组属引用类型,数组型数据是对象(object)
案例分析:
//请求出一个数组 int[]的最大值 {4,-1,9, 10,23},并得到对应的下标 public class ArrayExercise02 { public static void main(String[] args) { int[] arr = {4,-1,9,10,23}; int max = arr[0];//假定第一个元素就是最大值 int maxIndex = 0; for(int i = 1; i < arr.length; i++) {//从下标 1 开始遍历 arr if(max < arr[i]) {//如果 max < 当前元素 max = arr[i]; //把 max 设置成 当前元素 maxIndex = i; } } //当我们遍历这个数组 arr 后 , max 就是真正的最大值,maxIndex 最大值下标 System.out.println("max=" + max + " maxIndex=" + maxIndex); } }
数组拷贝
编写代码 实现数组拷贝(内容复制)
//将 int[] arr1 = {10,20,30}; 拷贝到 arr2 数组, //要求数据空间是独立的. int[] arr1 = {10,20,30}; //创建一个新的数组 arr2,开辟新的数据空间 public class ArrayCopy { public static void main(String[] args) { int[] arr2 = new int[arr1.length];//大小 arr1.length; for(int i = 0; i < arr1.length; i++) { //遍历 arr1 ,把每个元素拷贝到 arr2 对应的元素位置 arr2[i] = arr1[i]; } arr2[0] = 100;//修改 arr2, 不会对 arr1 有影响. System.out.println("====arr1 的元素===="); //输出 arr1 for(int i = 0; i < arr1.length; i++) { System.out.println(arr1[i]);//10,20,30 } System.out.println("====arr2 的元素===="); for(int i = 0; i < arr2.length; i++) { System.out.println(arr2[i]);// } } }
数组反转
把数组的元素内容反转。
//要求:把数组的元素内容反转。 //arr {11,22,33,44,55,66} -->{66, 55,44,33,22,11} public class ArrayReverse { public static void main(String[] args) { int[] arr = {11, 22, 33, 44, 55, 66};//定义数组 int temp = 0; int len = arr.length; //计算数组的长度 for( int i = 0; i < len / 2; i++) { temp = arr[len - 1 - i];//保存 arr[len - 1 - i] = arr[i]; arr[i] = temp; } System.out.println("===翻转后数组==="); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t");//66,55,44,33,22,11 } } }
数组添加/扩容/缩减
实现动态的给数组添加元素效果,实现对数组扩容。
/* 要求:实现动态的给数组添加元素效果,实现对数组扩容。 1.原始数组使用静态分配 int[] arr = {1,2,3} 2.增加的元素 4,直接放在数组的最后 arr = {1,2,3,4} 3.用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n */ import java.util.Scanner; public class ArrayAdd02 { public static void main(String[] args) { Scanner myScanner = new Scanner(System.in); int[] arr = {1,2,3};//初始化数组 do { int[] arrNew = new int[arr.length + 1]; //遍历 arr 数组,依次将 arr 的元素拷贝到 arrNew 数组 for(int i = 0; i < arr.length; i++) { arrNew[i] = arr[i]; } System.out.println("请输入你要添加的元素"); int addNum = myScanner.nextInt(); //把 addNum 赋给 arrNew 最后一个元素 arrNew[arrNew.length - 1] = addNum; //让 arr 指向 arrNew, arr = arrNew; //输出 arr 看看效果 System.out.println("====arr 扩容后元素情况===="); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } //问用户是否继续 System.out.println("是否继续添加 y/n"); char key = myScanner.next().charAt(0); if( key == 'n') { //如果输入 n ,就结束 break; } }while(true); System.out.println("你退出了添加..."); } }
数组的缩减和添加原理相同就不举例说明了