当前位置: 首页 > news >正文

JavaSE 数组从入门到面试全解析

JavaSE 数组从入门到面试全解析

在 Java 编程的世界里,数组是一种基础且重要的数据结构。无论是初学者入门,还是开发者面试,数组都是绕不开的知识点。本文将从数组的基础知识讲起,逐步深入,并解答面试中关于数组的常见问题。

数组基础知识

数组的定义

数组是相同类型数据的有序集合。它可以存储多个相同类型的元素,这些元素在内存中占据连续的空间,通过索引来访问。

数组的特点

  • 数组中的元素必须是相同类型。

  • 数组的长度是固定的,一旦创建,长度就不能改变。

  • 数组中的元素可以是基本数据类型,也可以是引用数据类型。

  • 数组本身是引用数据类型,它存储在堆内存中。

数组的声明

在 Java 中,数组的声明有两种方式:

// 方式一
数据类型[] 数组名;
// 方式二
数据类型 数组名[];

例如:

int[] arr1;
int arr2[];

通常推荐使用方式一,这种方式更能体现数组是一种引用类型。

数组的初始化

数组的初始化有静态初始化和动态初始化两种方式。

静态初始化

静态初始化是在声明数组的同时为数组元素赋值,数组的长度由赋值的元素个数决定。

// 完整语法
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ..., 元素n};
// 简化语法
数据类型[] 数组名 = {元素1, 元素2, ..., 元素n};

示例:

int[] arr1 = new int[]{1, 2, 3, 4, 5};
int[] arr2 = {6, 7, 8, 9, 10};
动态初始化

动态初始化是先指定数组的长度,然后再为数组元素赋值,数组元素会有默认值(基本数据类型的默认值如 int 为 0,boolean 为 false 等;引用数据类型的默认值为 null)。

数据类型[] 数组名 = new 数据类型[长度];

示例:

int[] arr = new int[5];
arr[0] = 1;
arr[1] = 2;
// 依次为其他元素赋值

数组的访问

数组通过索引来访问元素,索引从 0 开始,最大索引为数组长度减 1。

数组名[索引]

示例:

int[] arr = {1, 2, 3};
System.out.println(arr[0]); // 输出1
arr[1] = 4;
System.out.println(arr[1]); // 输出4

数组的遍历

遍历数组就是依次访问数组中的每个元素,常用的方式有 for 循环和增强 for 循环(foreach)。

for 循环遍历
int[] arr = {1, 2, 3, 4, 5};
for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);
}
增强 for 循环遍历

增强 for 循环更简洁,但不能修改数组元素的值(如果修改,不会影响原数组)。

int[] arr = {1, 2, 3, 4, 5};
for (int num : arr) {System.out.println(num);
}

数组的常见操作

数组的复制

可以使用System.arraycopy()方法或Arrays.copyOf()方法来复制数组。

  • System.arraycopy():public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length),其中 src 是源数组,srcPos 是源数组复制的起始位置,dest 是目标数组,destPos 是目标数组接收复制元素的起始位置,length 是复制的长度。
int[] src = {1, 2, 3, 4, 5};
int[] dest = new int[5];
System.arraycopy(src, 0, dest, 0, 3);
// dest数组此时为{1, 2, 3, 0, 0}
  • Arrays.copyOf():public static T[] copyOf(T[] original, int newLength),original 是源数组,newLength 是新数组的长度。如果新长度大于源数组长度,多余部分用默认值填充;如果小于,只复制前 newLength 个元素。
int[] src = {1, 2, 3, 4, 5};
int[] dest1 = Arrays.copyOf(src, 3); // dest1为{1, 2, 3}
int[] dest2 = Arrays.copyOf(src, 7); // dest2为{1, 2, 3, 4, 5, 0, 0}
数组的排序

可以使用Arrays.sort()方法对数组进行排序,该方法对基本数据类型数组采用双轴快速排序算法,对引用数据类型数组采用 TimSort 算法。

int[] arr = {3, 1, 4, 1, 5, 9};
Arrays.sort(arr);
// 排序后arr为{1, 1, 3, 4, 5, 9}
数组的查找
  • 线性查找:逐个遍历数组元素,查找目标值。
public static int linearSearch(int[] arr, int target) {for (int i = 0; i < arr.length; i++) {if (arr[i] == target) {return i;}}return -1;
}
  • 二分查找:要求数组必须是有序的,通过不断缩小查找范围来查找目标值。Arrays.binarySearch()方法实现了二分查找。
int[] arr = {1, 3, 5, 7, 9};
int index = Arrays.binarySearch(arr, 5); // index为2
int index2 = Arrays.binarySearch(arr, 4); // 查找不到,返回-3(插入点为2,-(2 + 1) = -3)

面试常见问题及答案

问题 1:数组和集合有什么区别?

答案:数组和集合的区别主要体现在以下几个方面:

  • 长度方面:数组的长度是固定的,一旦创建就不能改变;而集合的长度是可变的,可以动态地添加或删除元素。

  • 存储类型方面:数组可以存储基本数据类型,也可以存储引用数据类型;而集合只能存储引用数据类型(如果要存储基本数据类型,需要使用对应的包装类)。

  • 功能方面:集合提供了丰富的方法来操作元素,如添加、删除、查找等,而数组的操作相对简单,很多功能需要自己实现。

  • 类型安全方面:泛型出现后,集合可以提供编译时的类型安全检查;而数组在编译时也会进行类型检查,但在某些情况下可能会出现类型转换异常。

问题 2:数组的初始化方式有哪几种?

答案:数组的初始化方式有静态初始化和动态初始化两种。

  • 静态初始化:在声明数组的同时为数组元素赋值,数组的长度由赋值的元素个数决定。例如int[] arr = {1, 2, 3};或int[] arr = new int[]{1, 2, 3};。

  • 动态初始化:先指定数组的长度,然后再为数组元素赋值,数组元素会有默认值。例如int[] arr = new int[3];,然后再为 arr [0]、arr [1]、arr [2] 赋值。

问题 3:如何获取数组的长度?

答案:在 Java 中,可以通过数组的length属性来获取数组的长度,例如arr.length。需要注意的是,length是属性,不是方法,所以不需要加括号。

问题 4:数组的索引为什么从 0 开始?

答案:主要有以下几个原因:

  • 历史原因:许多早期的编程语言(如 C 语言)的数组索引从 0 开始,Java 在设计时借鉴了 C 语言的很多特性,包括数组索引从 0 开始。

  • 内存地址计算:数组元素在内存中是连续存储的,对于数组arr,第i个元素的内存地址可以通过arr[0]的地址加上i * 元素大小来计算,从 0 开始可以使计算更简单。

问题 5:什么是数组的深拷贝和浅拷贝?

答案:

  • 浅拷贝:当数组中的元素是引用数据类型时,浅拷贝只是复制了数组的引用,新数组和原数组中的元素指向同一个对象。修改新数组中元素的属性,会影响原数组中对应元素的属性。

  • 深拷贝:不仅复制了数组的引用,还为数组中的每个引用数据类型元素创建了一个新的对象,并将原对象的属性值复制到新对象中。新数组和原数组中的元素指向不同的对象,修改新数组中元素的属性,不会影响原数组中对应元素的属性。

对于基本数据类型数组,浅拷贝和深拷贝的效果是一样的,因为基本数据类型存储的是值本身。

问题 6:Arrays 工具类有哪些常用方法?

答案:Arrays 工具类提供了很多操作数组的静态方法,常用的有:

  • sort():对数组进行排序。

  • binarySearch():在有序数组中进行二分查找,返回元素的索引。

  • copyOf():复制数组,创建一个新的数组。

  • arraycopy():复制数组的一部分到另一个数组。

  • equals():比较两个数组是否相等(元素值和顺序都相同)。

  • fill():将数组中的元素填充为指定的值。

  • toString():将数组转换为字符串。

问题 7:数组在内存中是如何存储的?

答案:数组是引用数据类型,它在内存中的存储分为两部分:

  • 数组引用:存储在栈内存中,它指向数组对象在堆内存中的地址。

  • 数组对象:存储在堆内存中,数组中的元素就存储在数组对象中。对于基本数据类型数组,数组对象直接存储元素的值;对于引用数据类型数组,数组对象存储的是元素对象的引用(即元素对象在堆内存中的地址)。

例如,int[] arr = new int[3];,arr是数组引用,存储在栈内存中,它指向堆内存中创建的int数组对象,该数组对象有 3 个元素,初始值为 0,存储在堆内存中。

问题 8:如何判断一个数组是否包含某个元素?

答案:可以通过以下几种方式判断:

  • 对于无序数组,使用线性查找,遍历数组中的每个元素,看是否有与目标元素相等的元素。

  • 对于有序数组,可以使用二分查找(如Arrays.binarySearch()方法),如果返回的索引大于等于 0,则说明数组包含该元素。

  • 也可以将数组转换为集合,然后使用集合的contains()方法来判断,例如Arrays.asList(arr).contains(target),但需要注意,对于基本数据类型数组,这种方式需要先将其转换为对应的包装类数组。

数组作为 JavaSE 中的基础数据结构,是我们学习后续复杂数据结构和算法的基石。掌握好数组的相关知识,不仅能帮助我们更好地理解 Java 的内存模型和数据处理逻辑,也能在面试中从容应对各类问题。希望本文所整理的内容能为你的 Java 学习之路助力,祝大家在编程的世界里不断探索,收获成长!


文章转载自:

http://G75zRnxG.yLmxs.cn
http://mN8aZnlF.yLmxs.cn
http://6qF1NEuE.yLmxs.cn
http://MYpvzNcc.yLmxs.cn
http://WVaYDtgh.yLmxs.cn
http://wZVBZ22t.yLmxs.cn
http://dlsGWFEd.yLmxs.cn
http://N0Oo3ofe.yLmxs.cn
http://4tvfwgOr.yLmxs.cn
http://QoJweVyz.yLmxs.cn
http://MhBAb0Eq.yLmxs.cn
http://rJKjAIRj.yLmxs.cn
http://nbGD58jZ.yLmxs.cn
http://VE8wcosD.yLmxs.cn
http://ulXDG0mt.yLmxs.cn
http://mgMzjAP8.yLmxs.cn
http://rFMaZQwe.yLmxs.cn
http://4714T6eu.yLmxs.cn
http://w502HHsV.yLmxs.cn
http://70h4NEuu.yLmxs.cn
http://Ys5tVMzx.yLmxs.cn
http://FxHNl6Qs.yLmxs.cn
http://SE6EnkMu.yLmxs.cn
http://eR5JkNrb.yLmxs.cn
http://HHTfM2Jf.yLmxs.cn
http://3yKuvQcE.yLmxs.cn
http://8GjxzqPm.yLmxs.cn
http://ZfWH9Aw1.yLmxs.cn
http://iT3L9AMM.yLmxs.cn
http://VsAgjr17.yLmxs.cn
http://www.dtcms.com/a/371873.html

相关文章:

  • 游戏中的设计模式——第二篇 单例模式
  • 【论文阅读】自我进化的AI智能体综述
  • 系统分析师考试备考全面解析
  • 现代C++:C++和现代C++
  • 开始 ComfyUI 的 AI 绘图之旅-图生图之局部重绘(三)
  • 函数合集(1)
  • MySQL高可用方案解析:从复制到云原生
  • Python自学12 — 函数和模块
  • 腾讯云TDSQL-C 与传统MySQL对比
  • docker build命令及参数介绍
  • 老题新解|同行列对角线的格
  • RabbitMQ之死信队列
  • Java面试整理归纳——每日更新
  • Vue2基础概念与指令
  • Android 热点开发的相关api总结
  • 第二章 Python开发环境搭建与工具配置(二)
  • SylixOS 调度浅析
  • 1.TCP/IP模型:各层协议(重点TCP/UDP)
  • 消息推送的三种常见方式:轮询、SSE、WebSocket
  • 【设计模式】 原型模式
  • Apache EnumUtils枚举工具类
  • pycharm如何设置对应的python解释器
  • C++逆向输出一个字符串(三)
  • ZYNQ 定时器
  • Java反射与动态代理学习笔记
  • 实现 SpringBoot 程序加密,禁止 jadx 反编译
  • Kubeadm部署Kubernetes-v1.30.1【容器运行时containerd】
  • HOT100--Day14--543. 二叉树的直径,102. 二叉树的层序遍历,108. 将有序数组转换为二叉搜索树
  • 监控 Linux 服务器资源
  • HTTP原理