第6周 6.1 一维数组

安绍峰 / 2024-10-13 / 原文

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]);

img

img

“堆”并不是一个严格的术语,它泛指操作系统提供的一块内存区域,可以自由地存放数据。而栈则是一种运行时的数据结构,主要解决程序的运行问题,包括如何处理数据及函数调用的执行顺序等。
内存的划分分为堆和栈是为了更好地管理和利用内存资源,以及解决特定类型的数据存储和访问问题。
类类型数组申请的存储空间是在栈中,而数组的元素存储在堆中。在申请类类型数组元素的存储空间时,系统会为其分配一个引用(内存地址),这个引用存储在栈中,而引用指向的元素存储在堆中。
所以,对于类类型(引用类型)数组,数组和数组元素的存储空间需要分别申请。

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管理着共同的存储空间。

小结

  1. 数组定义和赋值是两个不同的操作。可以使用静态初始化和动态初始化为数组创建(new)存储空间,也可以使用赋值语句将一个数组赋值给另一个数组(数组名复制)。
  2. 表态初始化数值型数据时,可以省略new 操作符。
  3. 类型类型数组的数组和数组元素均需通过new 操作符进行初始化。
  4. 数组元素复制是创建了一个新的变量,并为其分配了新的存储空间,新变量与原变量具有相同的值,但二者互不影响。
  5. 数组名复制是创建了一个新的引用,并使其指向原数组,新引用与原引用指向同一个数组,二者具有相同的存储空间。
  6. 数值数组的默认值是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(???);
        }
    }
}