首页 > 编程语言 >Java——数组

Java——数组

时间:2024-06-08 14:30:01浏览次数:12  
标签:arr Java 数组 int length arr2 arr1

一、数组介绍

数组是Java中的一种数据结构,用于存储一组相同类型的元素。它们在内存中是连续存储的,并且通过索引来访问元素。以下是关于Java数组的详细介绍:

1、数组的创建和初始化

在Java中,数组是一种对象,它可以存储固定大小的同类型元素。数组的大小在创建时确定,并且一旦创建就不能改变。

1)方法一:动态创建

第一步要声明数组变量:

// 声明数组变量
type[] arrayName; 
// 或者(C/C++形式声明)
type arrayName[];

上面两种都可以用来声明数组变量,但是更推荐第一种,下面为例子:

int[] arrExample1;
char arrExample2[];

第二步要分配大小:

使用new关键字来分配数组的内存。

// 分配内存并初始化数组
arrayName = new type[size];

下面为例子:

int[] arrExample1;
char arrExample2[];
arrExample1 = new int[5];//对第一个数组分配5个整型空间
arrExample1 = new char[10];//对第一个数组分配10个字符型空间

当然,这两步可以使用一条语句完成:

type[] arrayName = new type[size];

下面为例子:

double[] arrExample = new double[10];//声明一个double类型数组,并为其分配十个double的空间

动态创建对应的初始化

对于上面的动态创建数组,只能使用下标一个一个赋值,使用循环可以更方便赋值。

import java.util.Scanner;

public class Test {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int[] arrExample = new int[5];
		//输入整型,存入数组
		for(int i = 0; i < arrExample.length; i++) {
			System.out.println("请输入整数");
			arrExample[i] = input.nextInt();
		}
		//打印数组的每一个元素
		for(int i = 0; i < arrExample.length; i++) {
			System.out.println("arrExample[" + i + "] = " + arrExample[i]);
		}
	}
}

运行结果:

2)方法二:静态创建和初始化

你也可以通过以下方法来创建数组。

dataType[] arrayRefVar = {value0, value1, ..., valuek};

例子:

int[] arrExample = {1, 2, 3, 4, 5};

使用这种方式创建和初始化的数组的大小就是初始化时放入的所有元素的总大小。这样创建的数组是被初始化好的。

这样初始化就相当于:

int[] arrExample = new int[5];
int[0] = 1;
int[1] = 2;
int[2] = 3;
int[3] = 4;
int[4] = 5;

2、数组的属性和方法

数组是引用类型,数组型数据是对象。

1)数组的属性

数组的 length 属性用于获取数组的长度,即数组中元素的个数。

int[] arr = {1, 2, 3, 4, 5};
System.out.println("Array length: " + arr.length); // 输出: Array length: 5

2)数组的方法

尽管数组对象本身没有方法,但 Java 提供了 java.util.Arrays 类,该类包含了许多用于操作数组的静态方法。以下是一些常用的 Arrays 类方法:

Arrays.toString()

将数组转换为字符串表示形式。

import java.util.Arrays;

public class Test {
	public static void main(String[] args) {
		int[] arr = {1, 2, 3, 4, 5};
		System.out.println("arr: " + Arrays.toString(arr));
	}	
}

运行结果:

Arrays.fill()

用指定的值填充数组的每个元素。

import java.util.Arrays;

public class Test {
	public static void main(String[] args) {
		int[] arr = new int[10];
		Arrays.fill(arr,6);
		System.out.println("arr: " + Arrays.toString(arr));
	}	
}

运行结果:

Arrays.equals()

比较两个数组是否相等。

import java.util.Arrays;

public class Test {
	public static void main(String[] args) {
		int[] arr1 = {1, 2, 3};
		int[] arr2 = {1, 2, 3};
		int[] arr3 = {1, 2};

		System.out.println("arr1 equals to arr2 is " + Arrays.equals(arr1,arr2));
		System.out.println("arr1 equals to arr3 is " + Arrays.equals(arr1,arr3));
	}	
}

运行结果:

3、补充

1)默认初始化

当数组被创建后,没有被赋值,对于不同的数据类型它会被默认初始化为以下值:

intshortbytelongfloatdoublecharbooleanString
0000L0.0f0.0\u0000falsenull

2)下标范围

当使用下标访问数组的元素时,下标的范围应当在 0 到 (array.length - 1) 之间,如果超出了这个范围,就造成了下标越界异常。

3)数组赋值机制

对于一个数组的创建,例如下面:

int[] arrExample;
arrExample = new int[10];

第一步实际上是声明一个数组引用变量,然后第二步就是申请 10 个整型的空间,然后将这个空间的引用赋值给 arrExample 这个数组引用变量。就像 C 语言那样,数组名可以退化成首元素地址。对于这里的数组引用变量,实际上也可以说存储的是数组的引用。

然后下面我们将一个数组引用变量的值赋给另一个数组引用变量,实际上赋的值是地址:

int[] arr1 = new int[10];
int[] arr2 = arr1;

这里将数组引用变量 arr1 的值赋值给 arr2,这里实际上就是将 arr1 中的数组的地址赋值给 arr2,然后我们就可以使用 arr2 来访问原来的数组。

下面我们可以通过一段代码来验证:

public class Test {
	public static void main(String[] args) {
		int[] arr1 = new int[10];//这里的数组arr1的元素都被默认初始化为0
		int[] arr2 = arr1;
		//下面我们改动arr1中的元素
		for(int i = 0; i < arr1.length; i++) {
			arr1[i] = i;
		}
		//然后我们打印arr2中的元素
		for(int i = 0; i < arr2.length; i++) {
			System.out.println("arr2 的第" + i + "个元素 = " + arr2[i]);
		}
	}	
}

运行结果:

可以发现,虽然上面我们是对数组 arr1 的元素进行更改,但是数组 arr2 中的元素也与数组 arr1 发生了一样的变化,所以说,实际上这样对数组引用变量进行赋值,赋的值实际上是数组的地址。

这里对数组 arr2 的元素进行改动也会影响到数组 arr1。

二、数组细节

1、数组在内存中的存储

数组的元素数据存储在堆区:

在 Java 中,数组是一种对象。所有对象都是在堆区(heap memory)中分配的。因此,数组的数据存储在堆区。当我们创建一个数组时,JVM 会在堆区中为这个数组分配内存空间,用于存储数组的实际元素。

数组名是引用变量:

数组名本质上是一个引用变量。这个引用变量是存储在栈区的。这意味着数组名存储了对数组对象的引用(即数组对象在堆区中的地址)。当我们声明一个数组时,例如 int[] arr;,此时 arr 是一个引用变量,但它还没有指向任何实际的数组对象。只有当我们初始化数组时,例如 arr = new int[5];,JVM 才会在堆区中分配空间来创建数组对象,并将其地址赋给 arr

数组引用变量存储的是堆区地址:

引用变量中存储的是数组对象的堆区地址。这意味着通过数组名 arr 可以访问实际存储在堆区中的数组数据。所以说上面我们使用一个数组引用变量的值赋给另一个数组引用变量,实际上赋的值是地址。

2、数组的存储图解

三、对数组的操作

1、数组拷贝

上面我们提到如果我们将一个数组引用变量赋值给另一个数组引用变量,会导致两个数组引用变量访问的数组是同一个,也就是它们中存储的地址是同一个,这样本质上还是一个数组。

如果我们想要两个数组,是独立的空间,但是存储的元素个数和值大小都是一样的,改动一个不会影响另一个。需要怎么办呢,假设我们开始有一个数组,我们就可以再创建一个数组引用变量,然后开辟相应的空间,也就是创建对象,然后将对象的地址赋值给引用变量。这样我们就有两个空间独立的数组了。

然后我们遍历数组一,依次将数组一的元素赋值给数组二,这样就实现了数组拷贝。

public class Test {
	public static void main(String[] args) {
		int[] arr1 = {1, 2, 3, 4, 5};
		
		int[] arr2 = new int[arr1.length];//保证两个数组的空间大小一样
		
		for(int i = 0; i < arr1.length; i++) {
			arr2[i] = arr1[i];//依次将元素的值赋值
		}
		//然后我们对arr1进行改动
		arr1[0] = 666;
		//打印arr1
		System.out.println("arr1");
		for(int i = 0; i < arr1.length; i++) {
			System.out.println(arr1[i]);
		}

		//打印arr2
		System.out.println("arr2");
		for(int i = 0; i < arr2.length; i++) {
			System.out.println(arr2[i]);
		}
	}	
}

运行结果:

可以发现这里我们改动 arr1 没有影响 arr2,就是因为两者使用的是不同的内存空间。

2、数组反转

public class Test {
	public static void main(String[] args) {
		int[] arr1 = {1, 2, 3, 4, 5};

		//反转前的数组
		System.out.println("反转前的数组");
		for(int i = 0; i < arr1.length; i++) {
			System.out.print(arr1[i] + " ");
		}

		//进行反转
		for(int i = 0; i < arr1.length / 2; i++) {
			int temp = arr1[i];
			arr1[i] = arr1[arr1.length - 1 - i];
			arr1[arr1.length - 1 - i] = temp;
		}

		//反转后的数组
		System.out.println("\n反转后的数组");
		for(int i = 0; i < arr1.length; i++) {
			System.out.print(arr1[i] + " ");
		}
	}	
}

运行结果:

3、数组扩容

我们这里进行数组扩容的思路就是,先创建一个比要扩容的数组大一个元素空间的数组,然后将原数组的元素依次拷贝到新数组中,然后将要添加的值放到新数组的最后,然后将新数组的数组引用变量赋值给原数组的数组引用变量,也就是将新的数组的地址赋值给原来的数组引用变量。这样原来的数组引用变量就可以访问到扩容好的新数组了。

对于原数组空间,就无法再次被访问了,就会被 jvm 当垃圾回收,原数组空间就会被回收。

public class Test {
	public static void main(String[] args) {
		int[] arr = {1, 2, 3, 4, 5};//最开始的数组,我们需要对其进行扩容

		int[] newArr = new int[arr.length + 1];
		//这里我们创建一个新的数组,并开辟一个新空间,新空间比原来的数组的大小大一,这里就是扩容

		//然后将原来的数组中的元素依次赋值到新数组中
		for(int i = 0; i < arr.length; i++) {
			newArr[i] = arr[i];
		}

		//然后就是要添加扩容的数字
		int addNum = 10;

		//将要添加的数组放到新数组最后
		newArr[newArr.length - 1] = addNum;

		//然后将新的数组的引用变量赋值给原来的数组引用变量,
		//这样原来的数组引用变量就可以访问这个新的扩容好的数组,
		//然后原来的数组空间无法再次被引用,就被jvm当作垃圾回收掉了,其空间就被回收了
		arr = newArr;

		//这里打印扩容后的数组,使用原来的数组引用变量访问,发现数组扩容成功
		for(int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
	}	
}

运行结果:

可以发现这里实现了数组扩容,然后将要添加的数字添加到了扩容好的新数组最后。

标签:arr,Java,数组,int,length,arr2,arr1
From: https://blog.csdn.net/stewie6/article/details/139521373

相关文章

  • Java 实验8 集合类
    (一)实验目的1、掌握JAVA集合类中的Collection的特点及其应用情形;3、掌握Collection、熟悉集合的特点及应用。(二)实验内容和步骤1、仿照课堂练习的MyStack示例,使用LinkedList集合类实现一个先进先出的队列数据结构,可以往该结构中压入数据push()以及弹出数据pop(),并遵循先进入......
  • UES-10-增强数组
    创建数组Array.of()方法将接收的每个参数作为数组元素创建并返回数组。和Array构造器相比,用于函数参数更可靠。functioncreate(fun,value){returnfun(value);}letitems=create(Array.of,value);Array.of创建数组使用的是当前of()方法中的this,而不是Symb......
  • 【JAVASE】日期与时间类(上)
    一:概述从JAVASE8开始提供了java.time包,该包中有专门处理日期和时间的类。LocalDate  LocalDateTime  和LocalTime类的对象封装和日期、时间有关的数据,这三个类都是final类,而且不提供修改数据的方法,即这些类的对象的实体不可再发生变化,属于不可变对象。二:LocalDat......
  • ssm604基于Java Web的怀旧唱片售卖系统+vue【已测试】
    前言:......
  • Java毕业设计-基于springboot开发的善筹网(众筹)前后台实现设计-毕业论文(附毕设源代码)
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求/流程分析3、系统功能结构三、系统实现展示1、管理员功能实现1.1众筹管理1.2商品信息管理1.3商品类型管理四、毕设内容和源代码获取总结Java毕业设计-基于springboot开发的善筹网(众......
  • 华为OD刷题C卷 - 每日刷题 8(整形数组按个位值排序,停车场车辆统计)
    两段代码分别解决了两个不同的算法问题,下面是对它们的概述:1、(整形数组按个位值排序):这段代码是解决“整形数组按个位值排序”的问题。它提供了一个Java类Main,其中包含main方法,用于读取输入、执行排序并打印结果。代码首先使用Scanner从标准输入读取一行文本,该文本包含一个......
  • JAVA面向对象三大特征之继承
    目录1.继承概述2.继承的格式 3.继承的好处3.1继承的使用时机3.2注意4.继承中变量的访问特点5.总结1.继承概述在继承中我们可以把类分为两种一种是父类一种是子类,子类在继承父类后会获得父类中的属性和方法,在父类中定义过的属性和方法,子类中不需要再写一遍,同时子......
  • Java那些事儿 —— 写一篇妈妈也能看懂的Java学习笔记
    Java那些事儿——写一篇妈妈也能看懂的Java学习笔记小白也能看懂的Java学习笔记(因为我也是小白,所以写一点小白自己能看懂的东西)这本笔记包括但是不限于Java知识,(做开发没多久感觉自己忘记的差不多了,最近又看了几本书,心血来潮写一个笔记)写这个的目的意在自我复习,尽量让自......
  • JavaScript中的数据类型
    概要ECMAScript的类型一共分为两大类,值类型以及引用类型。值类型又称基础类型,具体如下:undefined未定义null空boolean布尔number数值string字符串symbol标记引用类型又称复杂类型Object(对象),具体如下:Object对象Function函数Array数组RegExp正则Date日期基......
  • 【Java笔记】第10章:接口
    前言1.接口的概念与定义2.接口的声明与语法3.接口的实现4.接口的继承5.接口的默认方法6.接口的静态方法7.接口的私有方法8.接口的作用9.接口与抽象类的区别10.接口在Java集合中的应用结语上期回顾:【Java笔记】第9章:三个修饰符个人主页:C_GUIQU归属专......