容器概念
- 容器:是将多个数据存储到一起,每个数据称为该容器的元素。生活中的容器:水杯,衣柜,教室
数组的概述
- 数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式 对这些数据进行统一管理。 数组就是用于存储数据的长度固定的容器。
百度百科中对数组的定义:
所谓数组(array),就是相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,以便统一管理他们,然后用编号区分他们,这个名字称为数组名,编号称为下标或索引(index)。组成数组的各个变量称为数组的元素(element)。组中元素的个数称为数组的长度(length)。
特点:
- 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
- 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
- 数组的长度一旦确定,就不能修改。
- 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
数组的分类:
- 按照维度:一维数组、二维数组、三维数组、…
- 按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)
一维数组的声明格式有以下两种:
- 数组元素的类型[ ] 变量名称;
- 数组元素的类型 变量名称[ ];
数组元素的类型,可以是 java 中的任意类型,变量名称可以是任意合法的标识符,上面两种格式推荐是第一种,例如:
int [ ] a; Student[ ] stu int[ ] a, b, c // 在一行中也可以声明多个数组
我们单单在程序中声明了数据,而不给他初始化是无法使用的。数组的初始化:在内存当中创建一个数组,并且向其中赋予一些默认值。两种常见的初始化方式:
- 动态初始化(指定长度):在创建数组的时候,直接指定数组当中的数据元素个数。
- 静态初始化(指定内容):在创建数组的时候,不直接指定数据个数多少,而是直接将具体的数据内容进行指定。
动态初始化数组的格式:
- 数据类型[ ] 数组名称 = new 数据类型[数组长度];
解析含义:
- 左侧数据类型:创建的数组容器可以存储什么数据类型的数据。 元素的类型可以是任意的Java的数据类型。例如:int, String, Student等
- 左侧的中括号[ ] :代表我是一个数组
- 左侧数组名称:为定义的数组起个变量名,满足标识符规范,可以使用名字 *** 作数组。
- 右侧的new:代表创建数组的动作。关键字,创建数组使用的关键字。因为数组本身是引用数据类型,所以要用new创建数组对象。
- 右侧数据类型:必须和左边的数据类型保持一致
- 右侧中括号的长度:也就是数组当中,到底可以保存多少个元素 ,是一个int数字。
代码示例
// 创建一个数组,里面可以存放300个int数据 int[] arrayA = new int[300]; // 创建一个数组,能存放10个double类型的数据 double[] arrayB = new double[10]; // 创建一个数组,能存放5个字符串 String[] arrayC = new String[5];
静态初始化基本格式:
- 数据类型[] 数组名称 = new 数据类型[] { 元素1, 元素2, ... };
// 直接创建一个数组,里面装的全都是int数字,具体为:5、15、25 int[] arrayA = new int[] { 5, 15, 25, 40 }; // 创建一个数组,用来装字符串:"Hello"、"World"、"Java" String[] arrayB = new String[] { "Hello", "World", "Java" };
静态初始化省略格式:
- 数据类型[ ] 数组名称 = { 元素1, 元素2, ... };
// 省略格式的静态初始化 int[] arrayA = { 10, 20, 30 };
注意事项:
- 静态初始化没有直接指定长度,但是仍然会自动推算得到长度。
- 静态初始化标准格式可以声明和赋值分开进行
- 动态初始化也可以声明和赋值分开进行
- 静态初始化一旦使用省略格式,就不能声明和赋值分开进行
- 如果不确定数组当中的具体内容,用动态初始化;否则,已经确定了具体的内容,用静态初始化。
代码示例
public class Demo03Array { public static void main(String[] args) { // 静态初始化的标准格式,声明和赋值分开进行 int[] arrayB; arrayB = new int[] { 11, 21, 31 }; // 动态初始化也可以拆分成为两个步骤,声明和赋值分开进行 int[] arrayC; arrayC = new int[5]; // 静态初始化的省略格式,声明和赋值分开进行 // int[] arrayD; // arrayD = { 10, 20, 30 }; } }
如何调用数组的指定位置的元素
- 索引:每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引 (index),特点:连续,逐一增加,每次加1。
- 可以通过数组的索引访问到数组中的元素。 格式:数组名[索引]
- 也可以通过数组的索引给数组指定位置赋值
- 数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];
- 数组元素下标从0开始;长度为n的数组合法下标取值范围: 0到 n-1。
代码示例
public class Demo04ArrayUse { public static void main(String[] args) { // 静态初始化的省略格式 int[] array = { 10, 20, 30 }; System.out.println(array); // [I@75412c2f // 直接打印数组当中的元素 System.out.println(array[0]); // 10 System.out.println(array[1]); // 20 System.out.println(array[2]); // 30 System.out.println("============="); // 也可以将数组当中的某一个单个元素,赋值交给变量 int num = array[1]; System.out.println(num); // 20 } }
如何获取数组的长度
- 每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,语法: 数组名.length ,属性length的执行结果是数组的长度,int类型结果。由次可以推断出,数 组的最大索引值为数组名.length-1
代码示例
public class Demo03ArrayLength { public static void main(String[] args) { int[] arrayA = new int[3]; int[] arrayB = {10, 20, 30, 3, 5, 4, 6, 7, 8, 8, 65, 4, 44, 6, 10, 3, 5, 4, 6, 7, 8, 8, 65, 4}; int len = arrayB.length; System.out.println("arrayB数组的长度是:" + len); System.out.println("============="); int[] arrayC = new int[3]; System.out.println(arrayC.length); // 3 arrayC = new int[5]; System.out.println(arrayC.length); // 5 } }
如何遍历数组
代码示例
public class Demo07Array { public static void main(String[] args) { int[] arr = {11, 22, 33, 44, 55}; // 数组名.length System.out.println("arr数组中元素的个数为:" + arr.length); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } }
增强for 遍历数组,代码示例
public class Demo03 { public static void main(String[] args) { String [] strArr = new String[]{"蔡旭坤","特朗普","肖战","郭德纲"}; for (String s : strArr) { System.out.print(s+ " ");//蔡旭坤 特朗普 肖战 郭德纲 } } }
一维数组元素的默认初始化值
- 数组是引用类型,它的元素相当于类的成员变量,因此数组一经 分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化。
- 对于基本数据类型而言,默认初始化值各有不同
- 对于引用数据类型而言,默认初始化值为null(注意与0不同!)
代码示例
public class Demo { public static void main(String[] args) { // 动态初始化一个数组 int[] array = new int[3]; Object[] objects = new Object[4]; System.out.println(array); // 内存地址值 System.out.println(array[0]); // 0 System.out.println(objects[0]);//null } }Java虚拟机的内存划分
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。 JVM的内存划分如下图所示:
注意事项:
- 每new一次就必定会在堆空间开辟一个新的空间
- 数组的变量名称存在于栈空间中。而且保存了存储在数组中的首地址
一个数组的内存图
多个数组指向相同内存图
代码示例
public static void main(String[] args) { // 定义数组,存储3个元素 int[] arr = new int[3]; //数组索引进行赋值 arr[0] = 5; arr[1] = 6; arr[2] = 7; //输出3个索引上的元素值 System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); //定义数组变量arr2,将arr的地址赋值给arr2 int[] arr2 = arr; arr2[1] = 9; System.out.println(arr[1]); }
结论:引用类型传递的是内存地址值
需求:在编程竞赛中,有6个评委为参赛的选手打分,分数为0-100的整数分。选手的最后得分为:去掉一个最高分和一个最低分后 的4个评委平均值 (不考虑小数部分)。
import java.util.Scanner; public class Test5Array { public static void main(String[] args) { // 1.定义一个数组,用动态初始化完成数组元素的初始化,长度为6 int[] arr = new int[6]; // 2.键盘录入评委分数 Scanner sc = new Scanner(System.in); // 3.由于是6个评委打分,所以,接收评委分数的 *** 作,用循环 for (int i = 0; i < arr.length; i++) { System.out.println("请输入第" + (i+1) + "个评委的打分:"); int score = sc.nextInt(); if(score >= 0 && score <= 100){ // 合法的分值 arr[i] = score; }else{ // 非法的分值 System.out.println("您的打分输入有误, 请检查是否是0-100之间的"); i--; } } // 4.求出数组最大值 int max = arr[0]; for (int i = 1; i < arr.length; i++) { if(max < arr[i]){ max = arr[i]; } } // 5.求出数组最小值 int min = arr[0]; for (int i = 1; i < arr.length; i++) { if(min > arr[i]){ min = arr[i]; } } // 6.求出数组总和 int sum = 0; for (int i = 0; i < arr.length; i++) { sum += arr[i]; } // 7.按照计算规则进行计算得到平均分 int avg = (sum - max - min ) / 4; // 8.输出平均分 System.out.println(avg); } }二维数组
对于二维数组的理解,我们可以看成是一维数组 array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。
二维数组的声明格式如下:
注意:
int[] x, y[]; //x是一维数组,y是二维数组
和一维数组一样,如果只声明不赋值是不能使用的。下面介绍几种二维数组初始化的方式:
静态初始化
如果是静态初始化,右边new 数据类型[ ][ ]中不能写数字,因为行数和列数,由{ }的元素个数决定
class Test4{ public static void main(String [] args){ int [][] arr = new int[5][6]; //查找第一个一维数组的长度 System.out.println(arr.length); System.out.println("--->"+arr[0].length); //获取第一个一维数组内第二个元素 System.out.println("--->"+arr[0][1]);//0 System.out.println("--->"+arr[1].length); System.out.println("--->"+arr[2].length); System.out.println("--->"+arr[3].length); System.out.println("--->"+arr[4].length); System.out.println("--------------------------------------------------");//0 double [][] doubleArr = new double[3][]; System.out.println(doubleArr.length); //静态初始化给第一个一维数组赋值 doubleArr[0] = new double[]{3.14,6.28}; //Exception in thread "main" java.lang.NullPointerException System.out.println(doubleArr[0][0]); //动态初始化 给第二个一维数组赋值 doubleArr[1] = new double[5]; System.out.println(doubleArr[1][2]); } }
动态初始化(规则二维表:每一行的列数是相同的)
代码示例
public class Demo10Array { public static void main(String[] args) { //定义一个二维数组 int[][] arr = new int[3][2]; //定义了一个二维数组arr //这个二维数组有3个一维数组的元素 //每一个一维数组有2个元素 //输出二维数组名称 System.out.println(arr); //地址值 [[I@175078b //输出二维数组的第一个元素一维数组的名称 System.out.println(arr[0]); //地址值 [I@42552c System.out.println(arr[1]); //地址值 [I@e5bbd6 System.out.println(arr[2]); //地址值 [I@8ee016 //输出二维数组的元素 System.out.println(arr[0][0]); //0 System.out.println(arr[0][1]); //0 } }
动态初始化(不规则:每一行的列数可能不一样)
代码示例
public class Demo11Array { public static void main(String[] args) { //定义数组 int[][] arr = new int[3][]; System.out.println(arr); //[[I@175078b // System.out.println(arr[1][0]); NullPointerException System.out.println(arr[0]); //null System.out.println(arr[1]); //null System.out.println(arr[2]); //null //动态的为每一个一维数组分配空间 arr[0] = new int[2]; arr[1] = new int[3]; arr[2] = new int[1]; System.out.println(arr[0]); //[I@42552c System.out.println(arr[1]); //[I@e5bbd6 System.out.println(arr[2]); //[I@8ee016 System.out.println(arr[0][0]); //0 System.out.println(arr[0][1]); //0 //ArrayIndexOutOfBoundsException //System.out.println(arr[0][2]); //错误 arr[1][0] = 100; arr[1][2] = 200; } }
如何调用数组的指定位置的元素
// 定义一个名称为arr的二维数组,二维数组中有三个一维数组 // 每一个一维数组中具体元素也都已初始化 String[][] arr = new String[][]{{"a", "b", "c"}, {"e", "f"}, {"w", "|", "wed", "|wre"}}; //找到二维数组中的index为0一维数组 arr[0] //访问一维数组index 为2 第三个元素 System.out.println(arr[2][3]); //|wre
获取数组的长度
public class Demo0 { public static void main(String[] args) { // 定义一个名称为arr的二维数组,二维数组中有三个一维数组 // 每一个一维数组中具体元素也都已初始化 String[][] arr = new String[][]{{"a", "b", "1","c"}, {"e", "f"}, {"w", "|", "wed", "|wre"}}; //获取二维数组中一维数组的个数 System.out.println(arr.length);//3 //获取第一个一维数组的元素个数 System.out.println(arr[0].length); //4 } }
如何遍历二维数组
public class Demo0 { public static void main(String[] args) { // 定义一个名称为arr的二维数组,二维数组中有三个一维数组 // 每一个一维数组中具体元素也都已初始化 String[][] arr = new String[][]{{"a", "b", "1","c"}, {"e", "f"}, {"w", "|", "wed", "|wre"}}; //获取二维数组中一维数组的个数 for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) { System.out.print(arr[i][j]+ " "); } System.out.println(" "); } } }
二维数组中保存的是一维数组的地址值
求二维数组中的最大值和最小值
public class Demo12Array { public static void main(String[] args) { int [][] arr = {{10,20,30},{1,2000,3},{-100,200,300}}; //假设第一个一维数组的第一个元素是最大值 int maxNum = arr[0][0];//10 //假设第一个一维数组的第一个元素是最小值 int minNum = arr[0][0]; for(int i = 0;imaxNum){ maxNum = arr[i][j]; } //如果一个数比最小值还小 则 此数是最小值 if(arr[i][j]Arrays工具类 java.util.Arrays类即为 *** 作数组的工具类,包含了用来 *** 作数组(比 如排序和搜索)的各种方法。常见的如下所示:
代码示例
import java.util.Arrays; public class ArraysTest { public static void main(String[] args) { //1.boolean equals(int[] a,int[] b):判断两个数组是否相等。 int[] arr1 = new int[]{1,2,3,4}; int[] arr2 = new int[]{1,3,2,4}; boolean isEquals = Arrays.equals(arr1, arr2); System.out.println(isEquals); //2.String toString(int[] a):输出数组信息。 System.out.println(Arrays.toString(arr1)); //3.void fill(int[] a,int val):将指定值填充到数组之中。 Arrays.fill(arr1,10); System.out.println(Arrays.toString(arr1)); //4.void sort(int[] a):对数组进行排序。 Arrays.sort(arr2); System.out.println(Arrays.toString(arr2)); //5.int binarySearch(int[] a,int key) int[] arr3 = new int[]{-98,-34,2,34,54,66,79,105,210,333}; int index = Arrays.binarySearch(arr3, 210); if(index >= 0){ System.out.println(index); }else{ System.out.println("未找到"); } } }注意事项:
- 索引越界:访问了数组中不存在的索引对应的元素,造成索引越界问题 。数组角标越界的异常:ArrayIndexOutOfBoundsExcetion
- 空指针异常:访问的数组已经不再指向堆内存的数据,造成空指针异常。空指针异常:NullPointerException
- null:空值,引用数据类型的默认值,表示不指向任何有效对象
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)