【Java 基础语法】深度剖析 Java 中的数组,java面试宝典pdf

在这里插入图片描述

二、剖析 String[] args


你有没有想过每次我们用到的

public static void main(String[] args)

其中的 String[] args 是啥吗?我们可以知道它是一个字符串数组,那其中存放着什么呢?我们可以打印一下看看

public static void main(String[] args){

System.out.println(Arrays.toString(args));

}

// 结果为:[]

结果啥都没有,哦豁!上述是我在 IDEA 中尝试的,现在我再在命令行中试试

  1. 新建一个 Java 文件的代码,将上述代码输入,并保存(注意别忘了导包)

  2. 在该文件目录下通过 Shift+鼠标右键 ,就可以找到 PowerShell,将其打开

  3. 通过 Javac 编译,java 运行该程序,结果为在这里插入图片描述

人傻了,还是啥都没有

通过学习,如果我在运行时 java TestDemo 后面加上内容,如 Hello World! 就会有以下的结果在这里插入图片描述

因为 main 函数里的 args 叫运行时命令行参数,如果运行java程序时,后面放了内容,就会将其存到该数组里面

在这里插入图片描述

三、数组练习


在训练今天的习题前,我们要理解什么是包。而在之前我们就已经用到过 java.util.Arrays

import java.util.Arrays;

public class TestDemo{

public static void main(String[] args){

int[] array = {1, 2, 3};

String ret = Arrays.toString(array);

System.out.println(ret);

}

}

// 打印结果为:[1, 2, 3]

这其中使用到的 toString 就是上述包中的一个方法,它可以让数组变成字符串并返回一个字符串。

因此学会该包中和数组相关的常用方法,那数组的使用就可以更加舒服了!那么什么是包呢?

例如你吃的一碗热干面,如果一碗面从头到尾要你自己做的话,你需要先和面、擀面、扯面、再烧水、煮面、放调料等等。而大多数店铺其实它们做面只要煮面放调料就行了,因为制作面的这个繁琐的过程可以直接通过去超市买面来省去。

一个程序的开发也不一定要我们从头到尾去完成,我们实际上可以站在巨人的肩膀上。就比如 Java 中有大量的标准库和海量的第三方库提供我们使用,这里面的代码就放在一个个的

除此之外我们要知道

  1. 上述包中的 Arrays 意思是操作数组的工具类
  1. java.util 是 Arrays 所在的那个包的名字。大家可以去自己的 JDK\jre\lib\rt.jar 中找到 util 这个包,里面包含了很多该包中已经封装好的字节码文件,要使用就导入对应的类就行在这里插入图片描述
  1. 我们也可以直接使用 import java.util.*; ,它可以导入该包中全部的类。(**注意:**其实在使用它时并不会将该包中的全部类导入,而是你使用到了哪个类,它才会加载哪个类)

那么接下来我们将开始数组的练习,想要玩数组必须要掌握的基础的方法!

在这里插入图片描述

1. 数组转字符串

我们知道 toString 方法可以直接将数组变成字符串,那么我们怎么自己实现一个方法模拟 toString 呢?

public static String myToString(int[] array){

if(array == null){

return null;

}

if(array.length == 0){

return “”;

}

String str = “[”;

for(int i = 0; i < array.length; i++){

if(i == 0){

str +=array[i];

}else{

str +=", " + array[i];

}

}

str += “]”;

return str;

}

其中我们要注意数组长度为0或者数组为 null 的情况

2. 数组拷贝(4种)

首先我们自己可以尝试写一个方法来拷贝数组

public static int[] copyArray(int[] array){

int[] newArray = new int[array.length];

for(int i = 0; i < array.length; i++){

newArray[i] = array[i];

}

return newArray;

}

上述其实就是使用了 for 循环语句来进行遍历的拷贝,那么 Arrays 工具类中有没有更舒服的方式呢?

int[] array = {1, 2, 3};

int[] ret1 = Arrays.copyOf(array ,array.length);

System.out.println(Arrays.toString(ret1));

// 打印结果为:[1, 2, 3];

可以直接通过 copyOf(原数组,要返回的副本的长度) 方法来拷贝数组

如果副本长度大于原数组,相当于扩容,扩容的值默认为0

int[] array = {1, 2, 3};

int[] ret2 = Arrays.copyOf(array , 2 * array.length);

int[] ret3 = Arrays.copyOf(array , 2);

System.out.println(Arrays.toString(ret2));

System.out.println(Arrays.toString(ret3));

// 打印结果为:

// [1, 2 , 3, 0, 0, 0]

// [1, 2]

我们还可以通过 copyOfRange(原数组,起始索引值,终点索引值的后一个值) 方法来拷贝数组区间

int[] ar

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

ray = {1, 2, 3};

int[] ret4 = Arrays.copyOfRange(array ,1, 3);

System.out.println(Arrays.toString(ret4));

// 打印结果为:[2, 3]

除了上面所说的拷贝方式,我们还有其他方法。我们在 IDEA 上按住 Ctrl 键后点击 copyOf,跳转到它的源码,我们可以看到在这里插入图片描述

通过比较我们自己创建的拷贝方法可以知道,中间这段代码(如下)就是拷贝的过程

System.arraycopy(original, 0, copy, 0,

Math.min(original.length, newLength));

我们再按住 Ctrl 键后点击 arraycopy,跳转到它的源码,我们可以看到在这里插入图片描述

其中有一个 native,所以我们知道它是一个本地方法

而本地方法(native)具有以下特点

  • 本地方法由 C/C++ 代码实现
  • 运行速度快
  • 运行时是在本地方法栈上

通过它的参数我们可以猜测,它是从原数组(src)的起始位置(srcPos)开始,拷贝到目的数组(dest)的起始位置(destPos)开始且长度为(length)

我们可以敲个代码验证

int[] array = {1, 2, 3};

int[] ret5 = new int[array.length];

System.arraycopy(array, 0, ret5, 0, array.length);

System.out.println(Arrays.toString(ret5));

// 打印结果为:[1, 2, 3];

不过要注意这里的 length 不能超过原数组的长度,不然就会出现数组越界的异常

那么拷贝的方式就这样就结束了吗?NO!

在这里插入图片描述

我们还可以调用对象的 clone() 方法进行拷贝

int[] array = {1, 2, 3};

int[] ret6 = array.clone();

System.out.println(Arrays.toString(ret6));

// 打印结果为:[1, 2, 3];

至于克隆的过程其实可以用一张图描绘在这里插入图片描述

以上总结了数组的四种拷贝方法。但是我们要注意一种代码

int[] array = {1, 2, 3};

int[] ret7 = array;

这个根本就不是拷贝,因为 ret7 这个引用是指向 array 这个引用所指向的对象,如果 ret7 被改变, array 也会被改变

小结

上述介绍了拷贝的几种方法,但是拷贝其实还可以被分为深拷贝和浅拷贝。这里我简单的介绍一下

  • 深拷贝:(数组里面存的一般是基本数据类型)在这里插入图片描述

如果将 array2[0] 改成 99,array1[0] 不会被影响,这种拷贝就是深拷贝

  • 浅拷贝:(数组里面存的是引用数据类型)在这里插入图片描述

如图,加入原数组 array1[0] 存的是一个引用类型,它指向120这个对象。当数组拷贝后,array2[0] 这个引用也会指向120这个对象。如果将 array2[0] 所指向的对象改变,那么 array1[0] 所指向的对象也就改变了,这种就叫浅拷贝

  • 那如何对上述这种例子的浅拷贝怎么改成深拷贝呢?我们可以先将对象拷贝一份,然后再将拷贝后对象的地址拷贝到新数组中
  • 那么如何判断上述四种方法是深拷贝还是浅拷贝呢?一图让你理解明白在这里插入图片描述

3. 找数组中的最大元素

这题就很简单啊,一首 for 循环送给你

public static void main(String[] args){

int[] array = {1,6,2,0,8};

System.out.println(maxNum(array));

}

public static int maxNum(int[] array){

int max = array[0];

for(int i = 1; i < array.length; i++){

if(array[i] > max){

max = array[i];

}

}

return max;

}

4. 求数组中元素的平均值

这题也很简单,直接上代码

public static double avg(int[] array){

int sum = 0;

for(int x: array){

sum += x;

}

return (double)sum/(double)array.length;

}

不够要注意返回的可能时浮点数

5. 查找数组中指定元素(顺序查找)

直接上代码

public static int findNum(int[] array, int x){

for(int i = 0; i < array.length; i++){

if(array[i] == x){

return i;

}

}

return -1;

}

最后返回-1,是因为数组索引不可能为-1,其他非索引值也行,只是一个判断不存在的值

6. 查找数组中指定元素(二分查找)

这也直接上代码啦!不过使用二分的前提是该数组为有序的

public static int binarySearch(int[] array, int x){

int left = 0;

int right = array.length - 1;

while(left <= right){

int mid = (left + right) >> 1;

if(array[mid] > x){

right = mid -1;

}else if(array[mid] < x){

left = mid + 1;

}else{

return mid;

}

}

return -1;

}

除了自己定义的方法,Arrays 类中也有一个 binarySearch 方法可以进行二分查找

public static void main(String[] args){

int[] array = {1, 3, 7 ,9 ,10};

System.out.println(Arrays.binarySearch(array, 9));

}

7. 检查数组的有序性

直接上自己写的方法

public static boolean isSorted(int[] array){

for(int i = 0; i < array.length - 1; i++){

if(array[i] > array[i+1]){

return false;

}

}

return true;

}

注意,遍历时 i 不能等于array.length,因为如果数组本身有界,则最后 array[i+1] 就会越界

8. 数组排序(冒泡排序)

这个题学 C 语言时也写烂了,直接上代码

public static void dubbleSort(int[] array){

for(int i = 0; i < array.length - 1; i++){

boolean flg = false;

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;

flg = true;

}

}

if(flg == true){

break;

}

}

}

9. 数组逆序

Java 中没有逆序的方法,下面我们手撸一个吧!

public static void reverse(int[] array){

int left = 0;

int right = array.length - 1;

while(left < right){

int tmp = array[left];

array[left] = array[right];

array[right] = tmp;

left++;

right–;

}

}

10. 数组数字排序

给定一个整形数组,将所有的偶数放在数组前半部分,将所有的奇数放在后半部分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值