数组的概念
概念
- 用于存储数据的长度固定的容器,保证多个数据的数据类型要一致
特点
- 长度一旦确定就不能修改
- 创建数组时会在内存中开辟一整块连续的空间
- 通过下标直接定位到任意一个元素,存取元素的速度快
数组的定义
静态初始化
int[] arr = {1,2,3,4,5};//正确
int[] arr;
arr = {1,2,3,4,5};//错误
int[] arr = new int[]{1,2,3,4,5};//正确
int[] arr;
arr = new int[]{1,2,3,4,5};//正确
int[] arr = new int[5]{1,2,3,4,5};//错误的,后面有{}指定元素列表,就不需要在[长度]指定长度。
动态初始化
int[] arr = new int[5];
int[] arr;
arr = new int[5];
数组元素的访问
public static void main(String[] args) {
//定义存储int类型数组,赋值元素1,2,3,4,5
int[] arr = {1,2,3,4,5};
//为0索引元素赋值为6
arr[0] = 6;
//获取数组0索引上的元素
int i = arr[0];
System.out.println(i);
//直接输出数组0索引元素
System.out.println(arr[0]);
}
数组的遍历
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
//打印数组的属性,输出结果是5
System.out.println("数组的长度:" + arr.length);
//遍历输出数组中的元素
System.out.println("数组的元素有:");
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
}
数组元素的默认值
JVM虚拟机的内存划分
区域名称 |
作用 |
程序计数器 |
程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址 |
本地方法栈 |
当程序中调用了native的本地方法时,本地方法执行期间的内存区域 |
方法区 |
存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 |
堆内存 |
存储对象(包括数组对象),new来创建的,都存储在堆内存。 |
虚拟机栈 |
用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。 |
数组的内存图
两个变量指向一个数组
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]);
}
数组使用过程中常见异常
数组下标越界异常 ArrayIndexOutOfBoundsException
public static void main(String[] args) {
int[] arr = {1,2,3};
System.out.println(arr[3]);
}
数组空指针异常 NullPointerException
public static void main(String[] args){
//声明一个String[]类型的数组,用来存储三个学生的姓名
String[] names = new String[3];
int count = names[0].length(); //names[0]初始值为null
System.out.println("第一个学生姓名的字数:" + count);
}
数组的常见操作
数组找最值及其下标
int[] arr = {4,5,6,1,9};
//找最大值
int max = arr[0];
for(int i=1; i<arr.length; i++){
if(arr[i] > max){
max = arr[i];
}
}
//最大值可能有重复的,所以下标有多个
for(int i=0; i<arr.length; i++){
if(max == arr[i]){
System.out.print(i+"\t");
}
}
数组扩容
int[] arr = {1,2,3,4,5,6,7,8,9};
//如果要把arr数组扩容,增加1个位置
//(1)先创建一个新数组,它的长度 = 旧数组的长度+1
int[] newArr = new int[arr.length + 1];
//(2)复制元素
//注意:i<arr.length 因位arr比newArr短,避免下标越界
for(int i=0; i<arr.length; i++){
newArr[i] = arr[i];
}
//(3)把新元素添加到newArr的最后
newArr[newArr.length-1] = 10;
//(4)如果下面继续使用arr,可以让arr指向新数组
arr = newArr;
//(4)遍历显示
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
数组截取
int[] arr = {11,22,33,44,55,66,77,88,99};
int start = 2;
int end = 6;
//1、创建一个新数组,新数组的长度 = end-start ;
int[] newArr = new int[end-start];
//2、赋值元素
for(int i=0; i<newArr.length; i++){
newArr[i] = arr[start + i];
}
//3、遍历显示
for(int i=0; i<newArr.length; i++){
System.out.println(newArr[i]);
}
数组反转
int[] arr = {1,2,3,4,5,6,7,8,9};
//(1)计算要交换的次数: 次数 = arr.length/2
//(2)首尾对称位置交换
for(int i=0; i<arr.length/2; i++){//循环的次数就是交换的次数
int temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
//(3)遍历显示
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
案例1:评委打分
public static void main(String[] args){
int[] scores = {5,4,6,8,9,0,1,2,7,3};
int max = scores[0];
int min = scores[0];
double sum = 0;
for (int i = 0; i < scores.length; i++) {
if(max < scores[i]){
max = scores[i];
}
if(min > scores[i]){
min = scores[i];
}
sum += scores[i];
}
double score = (sum - max - min)/(scores.length-2);
System.out.println("得分:" + score);
}
案例2:打印小写字母和大写字母
public static void main(String[] args) {
char[] letters = new char[26];
for (int i = 0; i < letters.length; i++) {
letters[i] = (char)('a' + i);
}
for (int i = 0; i < letters.length; i++) {
System.out.println(letters[i] + "->" + (char)(letters[i] -32));
}
}