6.数组
编程语言中通常用变量来描述零散的、相互没有联系的单个数据,用数组来描述一组相互有联系的数据。
Java数组是具有相同数据类型的一组数据组成的、有序的集合,数组中的每个数据称为元素,每个元素都有一个编号,这个编号称为下标,下标从0开始。
java中数组是引用类型,数组元素可以是基本数据类型,也可以是引用类型。常用的数组有:一维数组、二维数组。
6.1.1 一维数据创建
1.定义一维数组
(1) 声明数组变量
数据类型名[] 数组名
或
数据类型名 数组名[]
//定义类,以后会学,当前可以忽略
class Student{
int id;
String name;
}
class Class{
Student[] students;
int size;
public void add(Student s){
students[size]=s;
size++;
}
}
int[] a;
Student[] stu;
//[]可以放在数据类型名前,也可以放在数据类型名后,但一般习惯放在数据类型名后。
int b[];
Class cls[];//[]可以放在数据类型名前,也可以放在数据类型名后,但一般习惯放在数据类型名后。
(2)分配数组内存空间
通过new
关键字来创建数组对象,并为其分配内存空间。
数组名 = new 数据类型名[数组长度];
int[] a = new int[5];//有5个元素,每个元素都是int类型的变量
Student[] stus = new Student[5];//有5个元素,每个元素都是Student类型的对象
采用下标访问数组元素,下标从0开始,到数组长度减1结束。
int n = a[0];
Student stu = new Student();
stu.name = "张三";
stu.age = 18;
stus[0]=stu;//将stu对象赋值给stus数组的第一个元素
stus[0].name+","+stus[0].age;
数组长度必须是一个大于0的整数,长度一旦确定,就不能再改变。
2。初始化数组
(1)静态初始化
即在声明的时候,直接用数据为其赋赋值,此时数组的长度就是元素个数。
数组名 = {元素1,元素2,元素3,...,元素n};
int intArray[]= {1,2,3,4,5};
for (int i=0; i<intArray.length; i++)
{
System.out.println(intArray[i]);
}
(2)动态初始化
动态初始化,即通过new关键字来为数组申请内存空间并赋值。
数组名 = new 数据类型[数组长度];
1)基本数据类型的数组:
int intArray[]=new int[5];
for (int i=0;i<5;i++)
{
System.out.println(intArray[i]); //默认值
}
intArray[0]=1;
intArray[1]=2;
intArray[2]=3;
intArray[3]=4;
intArray[4]=5;
for (int i=0;i<5;i++)
{
System.out.println(intArray[i]);
}
java的数组有几个特点:
数组所有元素初始化为默认值,整型都是0,浮点型是0.0,布尔型是false;
数组一旦创建后,大小就不可改变。
类类型(或叫引用类型)数组动态初始化后的值是null
2)类(class)类型的数组
String[] strArray = new String[2];
System.out.println(strArray[0]); // null->空引用
strArray[0]=new String ("abc"); //为元素分配存储空间
strArray[1]="123";
for (int i=0;i<strArray.length;i++)
System.out.println(strArray[i]);
“堆”并不是一个严格的术语,它泛指操作系统提供的一块内存区域,可以自由地存放数据。而栈则是一种运行时的数据结构,主要解决程序的运行问题,包括如何处理数据及函数调用的执行顺序等。
内存的划分分为堆和栈是为了更好地管理和利用内存资源,以及解决特定类型的数据存储和访问问题。
类类型数组申请的存储空间是在栈中,而数组的元素存储在堆中。在申请类类型数组元素的存储空间时,系统会为其分配一个引用(内存地址),这个引用存储在栈中,而引用指向的元素存储在堆中。
所以,对于类类型(引用类型)数组,数组和数组元素的存储空间需要分别申请。
3.一维数据的复制
分为数组元素的复制和数组名的复制
//数组元素复制
int [] a ={1,2,3};
int x=a[1] ;//变量x具有了数组元素a[1]的完全备份
x;
x=3;
a[1];
//数组名复制
int [] a ={1,2,3};
int [] b=a;//b和a指向同一个数组
b[1]
b[1]=4;
a[1];
//a和b管理着共同的存储空间。
小结
- 数组定义和赋值是两个不同的操作。可以使用静态初始化和动态初始化为数组创建(new)存储空间,也可以使用赋值语句将一个数组赋值给另一个数组(数组名复制)。
- 表态初始化数值型数据时,可以省略new 操作符。
- 类型类型数组的数组和数组元素均需通过new 操作符进行初始化。
- 数组元素复制是创建了一个新的变量,并为其分配了新的存储空间,新变量与原变量具有相同的值,但二者互不影响。
- 数组名复制是创建了一个新的引用,并使其指向原数组,新引用与原引用指向同一个数组,二者具有相同的存储空间。
- 数值数组的默认值是0。类类型数组的默认初始化值是null。
float floatArray[]=new float[]{1.1f,2.2f,3.3f};
3.9.2 一维数据访问
在java中,数组是一种数据存储结构,是一组相同类型的集合,用来存储多个同类型的数据,而数组遍历则是数组应用中最基本的操作。
数组遍历首先要知道数组的长度,然后通过索引访问数组中的元素。
数组名.length;
int[] a =new int[10];
for (int i=0;i<a.length;i++)
a[i]=(int)(Math.random()*100); //生成0到99的随机数,Math.Random()返回0到1之间的小数,所以这里用了(int)强制类型转换
for (int i=0;i<a.length;i++)
System.out.println(a[i]);
for (int i=0;i<a.length;i++){
System.out.println(a[i]);
}
Math.random()*100
foreach循环,是增强的for的新特性,主要用来遍历数组,集合等。
for (元素类型 临时变量名 : 数组名)// 数组名可以是obj对象,后面的章节会讲到
{访问x的语句; }
int arr[] = {1,2,3,4,5,6,7,8,9};
for(int x : arr){
System.out.println(x);
}
int i=1;
for (int x : arr){
i++;
x=x+i;
System.out.println(x);//临时亦是的值可以改变,但是不会改变原数组的值
}
for(int y : arr){
System.out.println(y); //原数组的值没有改变
}
for(int i=1;i<arr.length;i++){
arr[i]=arr[i]+i;
System.out.println(arr[i]); //原数组的值发生了改变
}
- Java语言foreach循环的原理是,通过迭代器遍历数组,每次迭代器返回一个元素,然后将其赋值给临时变量,然后执行循环体。
- 临时变量不是引用,而是一个值,是一个根据对应数组元素的值生成的新值(完全拷贝)。所以在循环体中,对临时变量的修改,不会影响原数组。
- 由于foreach执行时要比forttgile循环额外创建一个临时变量,这会导致额外的内存开销和CPU消耗,所以foreach循环的效率比for循环低。
- foreach循环更简洁,可以提高代码的可维护性和可读性;不是在处理大量数据的情况下,性能差差可以忽略。
// 使用Arrays.toString() 快速打印一维数组
import java.util.Arrays;
Arrays.toString(arr);
小结
- 遍历数组可以使用for循环,for循环可以访问数组索引,for each循环直接迭代每个数组元素,但无法获取索引;
- 使用Arrays.toString()可以快速获取数组内容。
练习:
请按倒序遍历数组并打印每个元素:
int[] ns = { 1, 4, 9, 16, 25 };
// 倒序打印数组元素:
for (???) {
System.out.println(???);
}
//或者
public class Main {
public static void main(String[] args) {
int[] ns = { 1, 4, 9, 16, 25 };
// 倒序打印数组元素:
for (???) {
System.out.println(???);
}
}
}