【JavaSE】数组的定义与使用

news2024/9/23 13:26:47

【本节目标】

1. 理解数组基本概念

2. 掌握数组的基本用法

3. 数组与方法互操作

4. 熟练掌握数组相关的常见问题和代码

目录

 1. 数组的基本概念

1.1什么是数组

1.2 数组的创建及初始化

1.3 数组的使用

2. 数组是引用类型

2.1基本类型变量与引用类型变量的区别

2.2再谈引用变量

 2.3 认识 null

3. 数组的应用场景

3.1作为函数的参数

3.2 作为函数的返回值

4. 数组练习

4.1 数组转字符串

4.2 数组排序

4.3 数组拷贝 

5. 二维数组


1. 数组的基本概念

1.1什么是数组

数组:可以看成是相同类型元素的一个集合在内存中是一段连续的空间。

比如现实中的车库:

 在java中,包含6个整形类型元素的数组,就相当于上图中连在一起的6个车位,从上图中可以看到:

1. 数组中存放的元素其类型相同

2. 数组的空间是连在一起的

3. 每个空间有自己的编号,其实位置的编号为0,即数组的下标。

1.2 数组的创建及初始化

T:表示数组中存放元素的类型

T[]:表示数组的类型

N:表示数组的长度

数组的创建:

int[] array1 = new int[10]; // 创建一个可以容纳10个int类型元素的数组
double[] array2 = new double[5]; // 创建一个可以容纳5个double类型元素的数组
String[] array3 = new String[3]; // 创建一个可以容纳3个字符串元素的数组

数组的初始化:

下面,我们来创建并初始化一个整形数组:

 也可以采用C语言中创建数组的形式,但是一般不建议使用这种方式:

还可以使用下面这种方式来创建数组,这种方法和第一种方式没有任何区别,第一种方法只是这种方法的简写。

 在上面,我们定义了一个数组,并对其进行了初始化。注意,如果创建了数组并且进行了初始化,则方括号[ ] 不能加数字,加了数字编译器会报错:

错误示范:

 数组的初始化主要分为动态初始化以及静态初始化。

1. 动态初始化:在创建数组时,直接指定数组中元素的个数

 2. 静态初始化:在创建数组时不直接指定数据元素个数,而直接将具体的数据内容进行指定

 【注意事项】

静态初始化虽然没有指定数组的长度,编译器在编译时会根据{}中元素个数来确定数组的长度。

静态初始化时, {}中数据类型必须与[]前数据类型一致。

静态初始化可以简写,省去后面的new T[]。(注意:虽然省去了new T[ ], 但是编译器编译代码时还是会还原)

静态和动态初始化也可以分为两步,但是省略格式不可以

int[] array1;
array1 = new int[10];

int[] array2;
array2 = new int[]{10, 20, 30};

// 注意省略格式不可以拆分, 否则编译失败
// int[] array3;
// array3 = {1, 2, 3};

因此,数组进行整体赋值的时候,只有一次机会,那就是定义的时候。 

如果没有对数组进行初始化,数组中元素有其默认值

 如果数组中存储元素类型为基类类型,默认值为基类类型对应的默认值,比如:

 值得注意的是,boolean类型数组默认初始值是false

如果数组中存储元素类型为引用类型,默认值为null

1.3 数组的使用

数组中元素访问

数组在内存中是一段连续的空间,空间的编号都是从0开始的,依次递增,该编号称为数组的下标,数组可以通过 下标访问其任意位置的元素

int[] array = {1,2,3,4};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
System.out.println(array[3]);

 输出结果:

 也可以通过[ ]对数组中的元素进行修改:

 【注意事项】

1. 数组是一段连续的内存空间,因此支持随机访问,即通过下标访问快速访问数组中任意位置的元素

2. 下标从0开始,介于[0, N)之间不包含N,N为元素个数,不能越界,否则会报出下标越界异常。

在写代码的过程中,我们经常会出现类似下面的这种错误提示:

这是由于数组下标越界异常导致的,只要数组的下标不是一个合法的下标范围,都会出现这个错误提示。

在数组中可以通过 数组对象.length 来获取数组的长度

 记住不要在length后面加括号

大家有没有想过,下面的代码的结果会是什么呢

 程序输出结果:

其实,这输出的是数组的地址,在数组名这个变量中,存放的是地址,我们把数组名这个变量叫做引用变量,或者直接叫做引用

遍历数组

所谓 "遍历" 是指将数组中的所有元素都访问一遍, 访问是指对数组中的元素进行某种操作,比如:打印。

方式一:普通for循环

 方式二:增强for循环(for-each循环)

for-each 是 for 循环的另外一种使用方式. 能够更方便的完成对数组的遍历. 可以避免循环条件和更新语句写错 

 这个方法是在遍历这个数组的时候,把数组当中的元素进行赋值给 x

两种方法输出结果相同:

方式三:

在java中,有一个将整形数组转成字符串的方法:

在使用前,我们需要加上这句代码:

import java.util.Arrays;

 也可以写成这种形式:

2. 数组是引用类型

2.1基本类型变量与引用类型变量的区别

基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值;

而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址。

 在上述代码中,a、b、arr,都是函数内部的变量,因此其空间都在main方法对应的栈帧中分配。

a、b是内置类型的变量,因此其空间中保存的就是给该变量初始化的值。

array是数组类型的引用变量,其内部保存的内容可以简单理解成是数组在堆空间中的首地址。

2.2再谈引用变量

public static void func() {
    int[] array1 = new int[3];
    array1[0] = 10;
    array1[1] = 20;
    array1[2] = 30;

    int[] array2 = new int[]{1,2,3,4,5};
    array2[0] = 100;
    array2[1] = 200;

    array1 = array2;
    array1[2] = 300;
    array1[3] = 400;
    array2[4] = 500;

    for (int i = 0; i < array2.length; i++) {
        System.out.println(array2[i]);
    }
}

 1.array1 = array2, 即让array1去引用array2引用的数组空间, 此时array1和array2实际是一个数组。

2.通过array1将数组2和3号位置元素修改为300,400,此时arrray2也能看到数组中修改的结果,因为array1和array2引用的是同一个数组。

3.通过array2将数组4号位置元素修改为500,此时array1也能看到数组中修改的结果,因为array1和array2引用的是同一个数组。

4.通过array2对数组中元素进行打印,输出100,200,300,400,500.

 总结:

 这句代码的意思就是array2 这个引用指向了array1这个引用所指向的对象。

问题:

一个引用能不能同时指向多个对象?

答案:不能。

 2.3 认识 null

null 在 Java 中表示 "空引用" , 也就是一个不指向对象的引用.

 null 的作用类似于 C 语言中的 NULL (空指针), 都是表示一个无效的内存位置. 因此不能对这个内存进行任何读写操 作. 一旦尝试读写, 就会抛出 NullPointerException.

注意: Java 中并没有约定 null 和 0 号地址的内存有任何关联.

3. 数组的应用场景

3.1作为函数的参数

在函数传参的时候,如果参数是基本数据类型,我们在函数中修改形参的值,并不会改变实参。因为形参是实参的一份临时拷贝。

 但是,如果函数参数传递的是像数组这样的引用数据类型,方法外部的数组内容也发生改变

public static void main(String[] args) {
    int[] arr = {1, 2, 3};
    func(arr);
    System.out.println("arr[0] = " + arr[0]);
}
public static void func(int[] a) {
    a[0] = 10;
    System.out.println("a[0] = " + a[0]);
}

发现在func方法内部修改数组的内容, 方法外部的数组内容也发生改变. 因为数组是引用类型,按照引用类型来进行传递,是可以修改其中存放的内容的。 

分析下面的代码:

public class Test {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4};
        //分别调用func1和func2之后,arr数组里面的值分别是多少?
        System.out.println(Arrays.toString(arr));
    }
    public static void func1(int[] array){
        array[0] = 99;
    }
    public static void func2(int[] array){
        array = new int[]{11,22,33,44,55};
    }
}

当我们只调用func1,程序运行的结果:

 当我们只调用func2,程序运行的结果:

分析:

调用func1: 

 

调用func2: 

 总结: 所谓的 "引用" 本质上只是存了一个地址. Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实 只是将数组的地址传入到函数形参中. 这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大).

3.2 作为函数的返回值

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

这个程序定义了一个Test类,其中包含了一个func方法和一个main方法。

func方法是一个静态方法,返回类型为int[]。在方法体内,它创建了一个包含整数元素的数组arr,并将其初始化为{1,2,3,4,5}。然后,它返回这个数组。

main方法是程序的入口点。在方法体内,它调用func方法,并将返回的数组存储在名为ret的变量中。然后,它使用Arrays.toString方法将ret数组转换为字符串,并通过System.out.println打印输出。

输出结果:

 

4. 数组练习

4.1 数组转字符串

在之前,我们已经讲到了将数组转成字符串进行输出的方法:

使用这个方法后续打印数组就更方便一些.

Java 中提供了 java.util.Arrays 包, 其中包含了一些操作数组的常用方法.

对于toString()这个方法,我们也可以自己来实现:

public static String myToString(int[] array) {
        if(array == null){
            return "null";
        }
        if(array.length == 0){
            return "[]";
        }
        String ret = "[";
        for (int i = 0; i < array.length; i++) {
            ret += array[i];
            if (i < array.length - 1) {
                ret += ", ";
            }
        }
        ret += "]";
        return ret;
    }

4.2 数组排序

还有可以对数组进行排序的方法:                                                                                      

 

 

 也可以指定要排序的区间:

 

 要注意的是,在java中的区间一般都是左闭右开 [  ) .

冒泡排序算法思路

假设排升序:

1. 将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来后最大元素 就在数组的末尾

2. 依次从上上述过程,直到数组中所有的元素都排列好

public static void bubbleSort(int[] array) {
        //i 代表排序的趟数
        for (int i = 0; i < array.length - 1; i++) {
            boolean flag = true;//优化
            for (int j = 0; j < array.length - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    int tmp = array[j];
                    array[j] = array[j + 1];
                    array[j+1]=tmp;
                    flag = false;
                }
            }
            if(flag){
                break;
            }
        }
    }

冒泡排序性能较低。

4.3 数组拷贝 

在Java中,有几种方式可以进行数组的拷贝。

1.使用循环逐个拷贝元素:可以使用循环将源数组的元素一个个复制到新数组中。例如:

public class Test {
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};
        int[] copy = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            copy[i] = array[i];
        }
        System.out.println(Arrays.toString(copy));
    }
}

2.使用Arrays.copyOf方法:Arrays类提供了一个名为copyOf的方法,它可以用于将源数组的元素复制到新数组中。例如:

 而且,Arrays.copyOf方法还可以用来给数组扩容

3.使用System.arraycopy方法:System类提供了一个名为arraycopy的静态方法,它可以用于将源数组的一部分元素复制到目标数组的指定位置。例如:

 注意:数组当中存储的是基本类型数据时,不论怎么拷贝基本都不会出现什么问题,但如果存储的是引用数据类 型,拷贝时需要考虑深浅拷贝的问题,关于深浅拷贝在后续详细给大家介绍。

5. 二维数组

二维数组的创建方法:

 注意:[ ] 内不能加数字,同时,数组的每一行元素都必须使用大括号括起来,否则会报错:

除此之外,还可以这样定义二维数组:

 和C语言不同的是,C语言二维数组可以省略行,但不能省略列,java恰恰相反,java在定义二维数组的时候,可以省略列,但不能省略行。

下面是错误示例:

 

 对于一个二维数组:

 

 通过下面的代码即可验证:

 程序输出的是两串地址:

 二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组.

因此,对于下面的代码:array.length求出的是数组的行数,array[0].length求出的是列数。

 输出结果:

 对于二维数组,我们还可以这样玩:

同时这是一个不规则的二维数组,它的列不相同 -

 注意:new int[ ] 不能声省略:

 

 二维数组的遍历:

int[][] array = new int[][]{{1,2,3},{4,5,6}};
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                System.out.print(array[i][j]+" ");
            }
            System.out.println();
        }

 使用for-each遍历二维数组:

 

将二维数组转成字符串:

Arrays.deepToString是一个用于将多维数组转换为字符串的方法,它可以打印多维数组的内容。

使用Arrays.deepToString方法可以方便地将二维数组转换为字符串表示形式,而不需要自己编写遍历和拼接字符串的代码。

下面是使用Arrays.deepToString方法的示例:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/811144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

慎思笃行,兴业致远:金融行业的数据之道

《中庸》中说&#xff0c;“博学之&#xff0c;审问之&#xff0c;慎思之&#xff0c;明辨之&#xff0c;笃行之”。这段话穿越千年&#xff0c;指引着中国千行百业的发展。对于金融行业来说&#xff0c;庞大的数据量可以说是“博学”的来源。但庞大的数据体量&#xff0c;既是…

网络通讯(服务端搭建)

一.本篇概况 本篇文章主要以C语言为主&#xff0c;通过C语言中所设定的函数以及环境来将网络通讯的服务端进行搭建。注&#xff1a;本篇并未涉及服务端与客户端之间的收发数据。 二.代码实现 1.初始化套接字库&#xff1a; if(WSAStartup(MAKEWORD(2, 2), &wsaData) ! 0…

你真的了解Java中的数组吗?

你真的了解Java中的数组吗&#xff1f; 数组是基本上所有语言都会有的一种数据类型&#xff0c;它表示一组相同类型的数据的集合&#xff0c;具有固定的长度&#xff0c;并且在内存中占据连续的空间。在C&#xff0c;C等语言中&#xff0c;数组的定义简洁清晰&#xff0c;而在J…

PDF.js实现搜索关键词高亮显示效果

在static\PDF\web\viewer.js找到定义setInitialView方法 大约是在1202行&#xff0c;不同的pdf.js版本不同 在方法体最后面添加如下代码&#xff1a; // 高亮显示关键词---------------------------------------- var keyword new URL(decodeURIComponent(location)).searchP…

【C语言进阶篇】看完这篇结构体文章,我向数据结构又进了一大步!(结构体进阶详解)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言1 结构体的声明1.1 结构的基础知识1.2 结构的声明1.2.1 . 匿名结构体类型声明1.2.2 匿名结构…

【深度学习实践】垃圾检测

简介 本项目使用深度学习目标检测开源框架PaddleDetection中的yolox算法实现了垃圾检测&#xff0c;本文包含了从头训练yolox模型和直接使用训练好的模型进行推理的代码及相关权重。 一、数据集准备 本次训练的数据集为coco格式&#xff0c;共包含150张垃圾的照片&#xff0…

每日一题——丢失的数字

丢失的数字 题目链接 注&#xff1a;这一题的解法建立在位运算——异或^的基础之上&#xff0c;如果位运算和异或操作符不太了解&#xff0c;建议先看看&#xff1a; 位运算详解 只出现一次的数字 思路 同样&#xff0c;这题要求时间复杂度为O(n)&#xff0c;空间复杂度为O…

二叉树中的深搜

一)计算布尔二叉树的值 2331. 计算布尔二叉树的值 - 力扣&#xff08;LeetCode&#xff09; 1)计算布尔二叉树需要从叶子节点向上进行计算&#xff0c;从下向上进行计算 2)完整二叉树是同时拥有左孩子和右孩子&#xff0c;或者是完全没有右孩子 3)当我只是盯着根节点来看的时候…

JSON Web 令牌 (JWT)攻击

一、什么是JSON Web 令牌 &#xff08;JWT&#xff09; JSON Web令牌&#xff08;JWT&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在网络应用间传递声明信息。它是一种轻量级、自包含的安全性传输格式&#xff0c;通常用于在身份验证和授权过程…

三更博客系统(完整笔记+前后台系统代码实现)

三更博客前后端分离系统 前后端分离博客系统1.技术栈2.创建工程3.博客前台3.0 准备工作3.1 SpringBoot和MybatisPuls整合配置测试 3.1 热门文章列表3.1.0 文章表分析3.1.1 需求3.1.2 接口设计3.1.3 基础版本代码实现3.1.4 使用VO优化3.1.5 字面值处理 3.2 Bean拷贝工具类封装3.…

C#百万数据处理

C#百万数据处理 在我们经验的不断增长中不可避免的会遇到一些数据量很大操作也复杂的业务 这种情况我们如何取优化如何去处理呢&#xff1f;一般都要根据业务逻辑和背景去进行合理的改进。 文章目录 C#百万数据处理前言一、项目业务需求和开发背景项目开发背景数据量计算业务需…

OpenFeign原理浅析

OpenFeign原理我个人觉得是非常简单的&#xff0c;如果你对Spring非常了解&#xff0c;知道FactoryBean&#xff0c;以及注入bean的方式&#xff0c;并掌握动态代理&#xff0c;那么自己实现一个类似这样的Http代理客户端是一点问题也没有的&#xff01; 使用流程 首先我们先过…

BLE连接、配对和绑定

参考&#xff1a;一篇文章带你解读蓝牙配对绑定 参考&#xff1a;BLE安全之SM剖析(1) 参考&#xff1a;BLE安全之SM剖析&#xff08;2&#xff09; 参考&#xff1a;BLE安全之SM剖析(3) 参考&#xff1a;https://blog.csdn.net/chengbaojin/article/details/103691046 参考&…

【MQTT5】原生PHP对接Uni H5、APP、微信小程序实时通讯消息服务

文章目录 视频演示效果前言一、分析二、全局注入MQTT连接1.引入库2.写入全局连接代码 二、PHP环境建立总结 视频演示效果 【uniapp】实现买定离手小游戏 前言 Mqtt不同环境问题太多&#xff0c;新手可以看下 《【MQTT】Esp32数据上传采集&#xff1a;最新mqtt插件&#xff08;支…

Flowable-服务-骆驼任务

目录 定义图形标记XML内容Flowable与Camel集成使用示例设计Came路由代码 定义 Camel 任务不是 BPMN 2.0 规范定义的官方任务&#xff0c;在 Flowable 中&#xff0c;Camel 任务是作为一种特殊的服务 任务来实现的。主要做路由工作的。 图形标记 由于 Camel 任务不是 BPMN 2.…

BMI指数计算小工具Java

现在越来越多的人关注健康&#xff0c;关注身材管理&#xff0c;不妨做个小工具&#xff0c;计算自己的BMI&#xff0c;给自己制定合理的健身或减肥计划&#xff0c;享受健康生活&#xff01;&#xff01;&#xff01;BMI的计算标准从网上找的&#xff0c;不知道是否准确&#…

❤ yarn 和npm 的使用

❤ yarn 和npm 的使用 yarn 版本1的使用 yarn 简介 Yarn是facebook发布的一款取代npm的包管理工具。 yarn特点&#xff1a; 1&#xff0c;速度超快。 Yarn 缓存了每个下载过的包&#xff0c;所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率&#xff0c;因…

TransGPT 开源交通大模型开源

TransGPT 是开源交通大模型&#xff0c;主要致力于在真实交通行业中发挥实际价值。 它能够实现交通情况预测、智能咨询助手、公共交通服务、交通规划设计、交通安全教育、协助管理、交通事故报告和分析、自动驾驶辅助系统等功能。 TransGPT 作为一个通用常识交通大模型&#…

cmd相关操作命令

1.根据端口号查询对应进程的PID netstat -ano | findstr 端口号 例如&#xff1a;netstat -ano | findstr 9080&#xff1b;该端口所属进程的PID为6684 2.根据PID查询对应进程 tasklist | findstr PID 例如&#xff1a;tasklist | findstr 6684&#xff1b;该PID所属进程名为…

啥都收费,不仅智能电视没人买了,连电视盒子也卖不出了

分析机构给出的数据指今年上半年国内的电视盒子销量跌破百万至92.9万台&#xff0c;同比下滑29%&#xff0c;享受额更是大跌32%&#xff0c;显示出电视盒子即使大幅降价也没人买了&#xff0c;导致消费者远离电视在于收费太离谱了。 一、啥都收费 如今的智能电视其实并不智能&a…