最新java之数组的定义和使用(附加练习题),埃森哲java技术面试题

总结

就写到这了,也算是给这段时间的面试做一个总结,查漏补缺,祝自己好运吧,也希望正在求职或者打算跳槽的 程序员看到这个文章能有一点点帮助或收获,我就心满意足了。多思考,多问为什么。希望小伙伴们早点收到满意的offer! 越努力越幸运!

金九银十已经过了,就目前国内的面试模式来讲,在面试前积极的准备面试,复习整个 Java 知识体系将变得非常重要,可以很负责任的说一句,复习准备的是否充分,将直接影响你入职的成功率。但很多小伙伴却苦于没有合适的资料来回顾整个 Java 知识体系,或者有的小伙伴可能都不知道该从哪里开始复习。我偶然得到一份整理的资料,不论是从整个 Java 知识体系,还是从面试的角度来看,都是一份含技术量很高的资料。

三面蚂蚁核心金融部,Java开发岗(缓存+一致性哈希+分布式)

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

//输出结果为[1, 2, 3, 4, 5, 6],此输出结果的格式是toString方法所固有的格式


2. 数组作为方法的参数

=============

2.1 基本用法


代码示例: 打印数组内容

public static void main (String[]args){

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

printArray(arr);

}

public static void printArray ( int[] a){

for (int x : a) {

System.out.println(x);

}

}

// 执行结果

1

2

3

2.2 理解引用类型(重点/难点)


2.2.1

下面先来看一个图:

其中我们可以清楚的看到等号左边首先是数组类型,然后是引用,等号右边为数组对象,在JAVA数组中,引用所存放的是其所指向的数组对象在堆中的地址。例如下图所示,arr2这个引用存储的就是所指对象在堆中的地址。

下面我们再用另外一张图来具体解析下其在内存中的存储:

首先我们在main方法中定义了三个数组,则这三个局部变量全部存储于栈上的main方法的栈帧中,此时对arr进行初始化,初始化的值我们称之为数组对象,则arr中此时存储的便是arr所指向的数组对象在堆中的地址,假设其为0x999,在逻辑上来说此时引用指向了对象,同理arr2这个引用也是相同的逻辑,只是arr2为动态初始化,而arr1为静态初始化。此时我们会发现arr1并没有进行初始化,不同于c语言的是,java中没有初始化的数组的值默认为0,并不是随机值,此处虽然没有存储地址,但是arr1这个引用同样指向了自己的数组对象。

此处要注意一个问题:引用是不是一定都在栈上呢?

答:引用不一定都在栈上的,之所以在栈上是因为其是一个局部变量若是一个全局变量的话则未必在栈上但是对象一定在堆上。

2.2.2一个引用只能指向一个对象

例如下面的代码此时arr这个引用表面上看起来指向了三个数组对象,实际上只能指向一个对象为{11,12,3,4,5},其余的两个对象被垃圾回收器回收掉了。

int[] arr= {1, 2, 3, 4, 5, 6, 7};

arr= new int[]{3, 4, 5, 6};

arr= new int[]{11, 12, 3, 4, 5};

String str3 = Arrays.toString(arr);

System.out.println(str3);

//输出结果为[11, 12, 3, 4, 5]

2.2.3 代码示例:如何正确理解下面的代码:

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

int[] arr8 = arr7;

String str2 = Arrays.toString(arr8);

System.out.println(str2);

//输出结果为[1, 2, 3, 4]

此处不能理解成为arr8引用指向arr7引用,因为引用是不能指向引用的,正确理解为arr8这个引用指向了arr7这个引用所指向的数组对象。

此时arr7中存储的是其数组对象在堆中的地址,现在通过int[] arr8 = arr7语句将其地址赋给了arr8这个引用,那么此时arr8这个引用指向了arr7这个引用所指向的数组对象,最终两个引用同时指向了{1,2,3,4}这个对象。

注意:当两个引用同时指向了一个对象,最终当一个引用修改了对象中的某个值,那么当另一个引用去访问这个对象的时候,也是会收到牵连的,举例:

public class suanshu {

public static void func(int[] array2) {
    array2[2] = 6;
}
public static void main(String[] args) {
    int[] array={1,2,3,4,5,6};
    func(array);
    System.out.println(array[2]);
}

}

此时输出的结果为6,原因是我们的array和array2这两个引用同时指向了{1,2,3,4,5,6}这个对象,当array2这个引用修改了对象中的2下标所对应的值后,array这个引用再次访问2这个下标对应的值便成了修改过后的值。

2.3 认识 null


null 在 Java 中表示 “空引用” , 也就是一个无效的引用,此时这个引用不指向任何一个对象

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

arr = null;

System.out.println(arr[0]);

System.out.println(arr.length);

// 执行结果

Exception in thread “main” java.lang.NullPointerException at Test.main(Test.java:6)

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

所以说如果发生了空指针异常,首先检查我们的引用是否为null.

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

思考一个问题:当arr不指向任何对象时,原来的数组对象去了哪里?

答:当arr等于null时,此时原来的数组对象被jvm中的垃圾回收器回收了

总结:当一个对象不再被任何引用所引用的时候,此时会被垃圾回收器回收掉

例如  int arr={1,2,3,4,5,6};

arr=null;

那么{1,2,3,4,5,6}这个对象如果没有被任何一个引用所指向的话,在不久后会被垃圾回收器回收掉。

同时当我们的引用不知道指向谁的时候,可以赋值为null.但是不能赋值为0.

2.4 初识 JVM 内存区域划分****(重点)****


JVM 的内存被划分成了几个区域, 如图所示:

1.程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址.

2.虚拟机栈(JVM Stack): 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int[] arr 这样的存储地址的引用就是在这里保存.

3.本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.

在这里简单介绍下native方法:JVM 是一个基于 C++ 实现的程序. 在 Java 程序执行过程中, 本质上也需要调用 C++ 提供的一些函数进行和操作系统底层进行一些交互. 因此在 Java 开发中也会调用到一些 C++ 实现的函数.这里的 Native 方法就是指这些 C++ 实现的, 再由 Java 来调用的函数.

4.堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} )

5.方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域.

6.运行时常量池(Runtime Constant Pool): 是方法区的一部分, 存放字面量(字符串常量)与符号引用. (注意 从 JDK 1.7 开始, 运行时常量池在堆上).

我们发现, 在上面的图中, 程序计数器, 虚拟机栈, 本地方法栈被很多个原谅色的, 名叫 Thread(线程) 的方框圈起来了,并且存在很多份. 而 堆, 方法区, 运行时常量池, 只有一份. (关于线程, 这是我们后面重点讲解的内容).

关于上面的划分方式, 我们随着后面的学习慢慢理解. 此处我们重点理解 虚拟机栈 和 堆


  1. 数组作为方法的返回值

==============

代码示例: 写一个方法, 将数组中的每个元素都 * 2

public class ShuZu {

//写一个方法,将数组中的每一个元素扩大2倍(不改变原数组)

public static int[] print2(int[] arr) {

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

arr[i] = arr[i] * 2;

}

//注意返回的是一个数组名

return arr;

}

public static void main(String[] args) {

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

int[] arr1 = print2(arr);

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

//输出结果为[2, 4, 6, 8, 10, 12]

}

}

这个代码固然可行, 但是破坏了原有数组. 有时候我们不希望破坏原数组, 就需要在方法内部创建一个新的数组, 并由方法返回出来.,上述代码示意图如下所示:

public class ShuZu {

//写一个方法,将数组中的每一个元素扩大2倍(改变原数组)

public static int[] print3(int[] arr) {

int[] ret = new int[arr.length];

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

ret[i] = arr[i] * 2;

}

return ret;

}

public static void main(String[] args) {

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

int[] arr1 = print3(arr);

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

//输出结果为[2, 4, 6, 8, 10, 12]

}

}

这样的话就不会破坏原有数组了.

另外由于数组是引用类型, 返回的时候只是将这个数组的首地址返回给函数调用者, 没有拷贝数组内容, 从而比较高效.上述代码示意图如下所示:

此时我们并没有改变原有数组,如图所示,最终我们所输出的arr1指向的是新的对象{2,4,6,8,10,12},并不是原有对象{1,2,3,4,5,6}。

代码示例:匿名数组作为返回值


public static int[] func(int[] arr) {

return new int[]{1, 2};

}

此时的new int[]{1,2}就是匿名数组。


  1. 数组练习

========

4.1 数组转字符串


代码示例:

import java.util.Arrays

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

String newArr = Arrays.toString(arr);

System.out.println(newArr);

// 执行结果

[1, 2, 3, 4, 5, 6]

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

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

在这里科普下什么是包?

例如做一碗油泼面, 需要先和面, 擀面, 扯出面条, 再烧水, 下锅煮熟, 放调料, 泼油. 但是其中的 “和面, 擀面, 扯出面条” 环节难度比较大, 不是所有人都能很容易做好. 于是超市就提供了一些直接已经扯好的面条, 可以直接买回来下锅煮. 从而降低了做油泼面的难度, 也提高了制作效率. 程序开发也不是从零开始, 而是要站在巨人的肩膀上. 像我们很多程序写的过程中不必把所有的细节都自己实现, 已经有大量的标准库(JDK提供好的代码)和海量的 第三方库(其他机构组织提供的代码)供我们直接使用. 这些代码就放在一个一个的 “包” 之中. 所谓的包就相于卖面条的超市. 只不过, 超市的面条只有寥寥几种, 而我们可以使用的 “包” , 有成千上万.

我们实现一个自己版本的数组转字符串:即重写我们的toString方法

public class suanshu {

public static String myToString(int[] array) {

//要考虑到我们这个数组假如为空的情况

if(array==null){

return “[]”;

}

String ret = “[”;

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

ret += array[i];

//如果没到最后一个,则一个数字后面跟一个逗号

if (i != array.length - 1) {

ret += “,”;

}

}

ret += “]”;

return ret;

}

public static void main(String[] args) {

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

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

}

}

//输出结果为【1,2,3,4,5】

4.2 数组拷贝(重要)


下面一共介绍四种数组拷贝的方法:

方法1:利用for循环来进行拷贝

代码示例:

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

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

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

array2[i] = array[i];

}

//输出结果为[1, 2, 3, 4, 5, 6]

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

//输出结果为[1, 2, 3, 4, 5, 6]

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

此方法为最简单的数组拷贝方法,利用for循环来进行拷贝

方法2:利用copyof方法进行拷贝

代码示例:

//定义一个数组array3

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

//copyOf方法是用来拷贝数组的一种方法,括号中放入的分别为引用和想要拷贝多长的数组的长度值

int[] array2 = Arrays.copyOf(array, 10);

//输出结果为[1, 2, 3, 4, 5, 6]

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

//输出结果为[1, 2, 3, 4, 5, 6, 0, 0, 0, 0]

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

此处我们利用copyof方法来进行数组的拷贝,此处我们可以看下copyof方法的源码实现

Arrays的copyOf()方法传回的数组是新的数组对象改变传回数组中的元素值,不会影响原来的数组。(在下面的图中将做具体解释)

copyOf()方法中有两个形参,第一个形参是代表被拷贝的数组,第二个形参newLength指定要建立的新的数组的长度如果新数组的长度超过原数组的长度,则新数组剩余坑位保留数组的默认值(默认值为0)

下面对此段代码在内存中的存储做一个图示:

首先我们在main方法中定义了一个数组array并进行了初始化,那么首先在栈上开辟main方法的栈帧,并为引用array开辟内存,此时引用array的数组对象的地址存储在其内存中,逻辑上引用array指向了其数组对象,此时我们定义了一个新的数组array2,并且调用了copyof方法,那么在栈上为copyof开辟一个新的栈帧并在main方法的栈帧中再为array2开辟一个新的内存,然后再为copyof方法内部的局部变量copy在copyof方法的栈帧上分配内存,此时通过copeof方法的调用后我们的引用copy有了一个新的数组对象,此时同样copy引用指向了这个新的数组对象,并且当我们将copyof方法的返回值(即copy数组)赋给我们所定义的新的数组array2后,同样array2这个引用此时也指向了这个新的数组对象(原因是地址传递).

同时在这里介绍下copefOf方法的变形也就是copeOfRange方法,首先我们来看下代码示例:

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

int[] ret=Arrays.copyOfRange(array,1,5);

int[] ret1=Arrays.copyOfRange(array,1,7);

//输出结果为[2, 3, 4, 5]

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

//输出结果为[2, 3, 4, 5, 6, 0]

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

首先我们来看下copyOfRange方法的声明:

将一个原始的数组original,从下标from开始复制,复制到下标to,生成一个新的数组。

新拷贝的数组的长度为to-from,并且我们可以看到copyOfRange方法的底层代码实现本质上还是arraycopy方法

注意复制的时候包括下标from,但不包括上标to。

例如在上面的代码中,我们从array数组中下标为1的地方开始复制,复制到下标为5的地方,但并不复制下标为5处的本身的数字(左闭右开),那么此时复制的数字有2,3,4,5

而当to处的的下标值超过了被复制数组array下标的最大值时,例如上面的代码中,array的下标值最大到5,而此时from下标值为1,to的下标值为7,7>5,相当于当我们复制完array[5]处的数字后,此时array不能再提供数字让我们复制了,则此时ret1[6]的值为0,即为默认值,所以总结结论得当**to处的的下标值超过了被复制数组array下标的最大值时,其后面所放的数字统一为0.**例如执行int[] ret1=Arrays.copyOfRange(array,1,7);语句后,最终的ret1实际值为[2, 3, 4, 5, 6, 0].

方法3:利用arraycopy方法进行拷贝(注意与copyOf方法的对比)

代码示例:

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

int[] array6 = new int[array5.length];

/*表示从array5数组的0下标开始复制6个数字到array6数组当中,并且在放入arrray6数组当中时

也是从0下标开始放入*/

System.arraycopy(array5, 0, array6, 0, 6);

//输出结果为[1, 2, 3, 4, 5, 6]

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

//输出结果为[1, 2, 3, 4, 5, 6]

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

首先观察先System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)的声明:

public static native void arraycopy(Object src, int srcPos,

                                    Object dest, int destPos,
                                    int length);

src - 源数组(即被复制的数组)。

srcPos - 源数组中的起始位置(表示可以从源数组的任意一个下标处开始复制)。

dest - 目标数组(即复制后的数组)。

destPos - 目标数组中的起始位置(表示可以让复制过来的数字按照下标顺序从其要在新的目标数组中所放入的位置开始有序插入)。

同时还需注意:arraycopy方法使用了native关键字,说明这个方法是c/c++代码实现的,我们是看不到具体实现的。同时被native关键字所修饰的方法具有速度快这一特性。

并且在jvm内存的划分中,有一部分为本地方法栈,其存储的就是被native所修饰的方法.

下面再来看两种需要注意的情况:

情况一:此时我们修改下代码:当我们要复制的数组长度大于原数组长度时,例如我们设为10

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

int[] array6 = new int[10];

/*表示从array5数组的1下标开始复制5个数字到array6数组当中,并且在放入arrray6数组当中时,是从2下标开始放入的,那么此时array6[0],array6[1]的默认值变为0,并且此时已经占用两个位置后,array6中能放入的数字变为了8个,所以 此时我们复制过来的数字能放入array6这个数组当中的有2,3,4,5,6.接着array6[6]=array6[7]=array6[8]=array6[9]=0.

此处一定要注意如果srcPos+length>src.length,那么此时便会发生数组下标越界异常,例如此时length值若变为6,1+6>6,那么运行代码时便会出现数组下标越界异常,原因是从原数组下标为1处开始往后复制6个时,当我们复制到下标为5处的地方,此时已经没有数组再让我们复制了。

System.arraycopy(array5, 1, array6, 2, 5);

//输出结果为[1, 2, 3, 4, 5, 6]

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

//输出结果为[0, 0, 2, 3, 4, 5,0,0,0,0]

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

情况二:此时我们修改下代码:当我们要复制的数组长度等于原数组长度时

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

int[] array6 = new int[array5.length];

/*表示从array5数组的1下标开始复制4个数字到array6数组当中,并且在放入arrray6数组当中时,是从2下标开始放入的,那么此时array6[0],array6[1]的默认值变为0,并且此时已经占用两个位置后,array6中能放入的数字变为了4个,所以 此时我们复制过来的数字能放入array6这个数组当中的只有2,3,4,5.

此处一定要注意length的取值最多(<=)为array5.length-destPos,如果超过此时便会发生数组下标越界异常,例如此时length值若变为5,那么运行代码时便会出现数组下标越界异常,原因是array[6]数组中只能再放入4个了,而length的值是小于等于能插入的个数的.

System.arraycopy(array5, 1, array6, 2, 4);

//输出结果为[1, 2, 3, 4, 5, 6]

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

//输出结果为[0, 0, 2, 3, 4, 5]

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

length - 要复制的数组元素的数量。(容易出错,需要注意)

面试题目:System.arraycopy方法和copyOf方法哪个拷贝速度更快呢?

答:arraycopy方法会比较快,原因是当我们浏览arraycopy方法源码时会发现其被native所修饰,我们都知道native方法是由C/C++代码来实现的,我们是看不到具体实现的,而且被native所修饰的方法一般有个特点就是速度块

所以arraycopy方法会速度更快些

方法4:利用clone方法进行拷贝

代码示例:

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

int[] array1=array.clone();

//输出结果为[1, 2, 3, 4, 5, 6]

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

//输出结果为[1, 2, 3, 4, 5, 6]

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

此时运用clone方法相当于在堆中对数组对象进行拷贝,如下图所示:

自主实现数组拷贝的方法:

import java.util.Arrays;

/**

  • 自主实现数组的拷贝方法

  • @author SongBiao

  • @Date 2021/1/06

*/

public class ShuZu3 {

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

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

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

ret[i]=array[i];

}

return ret;

}

public static void main(String[] args) {

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

int[] ret=KaoBei(array);

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

}

}

面试题:这四种拷贝方法是深拷贝还是浅拷贝?

答:这四种方法若是**针对基本类型或者是简单类型为深拷贝,对于引用类型来说就是浅拷贝了** **深拷贝**:当拷贝结束后,通过一个新的引用修改所拷贝的新的对象的其中的某个类型(此类型为简单类型或者基本类型,引用类型的分情况,后续会详细介绍)的值时,并不影响原来引用所对应的相同对象中的相同类型的值,那么此时便为深拷贝。

例如假设此时我们拷贝array1数组后生成了array2数组,当修改了array2[0]处的值后,array1[0]处的值会发生改变吗,答案当然是不,原因是array1和array2这两个数组存储的都是基本数据类型,array2拷贝一份array1后修改自己的值,并不影响array1中的值.

**浅拷贝**:**当拷贝结束后,此时两个引用指向了同一个数组对象,当通过其中一个引用去改变数组对象的某个值后,另一个引用在访问完数组对象后得到了另一个引用修改后的值,并非原来的值时,则此时便为浅拷贝**

例如此时我们有一个array1数组存储的是引用数组类型,即每个对象在堆中的地址,并且每个对象中都存储了对应的整数值,如下所示:

当我们拷贝一份array1后得到了一个新的数组array2,但是我们此时的拷贝只是拷贝了引用,并没有拷贝对象,所以新拷贝的array2数组还是指向了之前array1所指向的对象。

所以当我们修改array1[0]所对应的对象中的值后,array2再度访问array2[0]下标的值时,便会得到修改后的值.

当然上述情况的浅拷贝要是变为深拷贝的话,也是可以实现的,只需要我们拷贝对象就好了

后续当我们学完接口后,便可以实现我们的深拷贝了

4.3找出数组中最大的元素


代码示例:

public class suanshu {

public static int findMax(int[] array){

//假定此时数组第一个值为最大值

int max=array[0];

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

if(array[i]>max){

max=array[i];

}

}

return max;

}

public static void main(String[] args) {

int[] arr={1,4,7,9,4,8};

int maxNum=findMax(arr);

System.out.println(maxNum);

}

}

注意:题目思路为假设数组下标为0的元素为最大值,然后从下标为1的元素开始进行比较,假如比下标为0的元素大,那么当前最大值就进行替换,依次往复.

4.4求数组中元素的平均值


代码示例:

public class suanshu {

public static double findAverge(int[] array) {

//求数组中元素的平均值

double sum=0.0;

double averge=0.0;

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

sum+=array[i];

averge=1.0*sum/array.length;

}

return averge;

}

public static void main(String[] args) {

int[] arr={1,4,7,9,4,8};

double averge=findAverge(arr);

System.out.println(averge);

}

}

注意给整形数组求平均值的时候要进行数组元素和或者数组个数的强转

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


给定一个数组,给定一个元素,找出该元素在数组中的位置

代码示例:

public class suanshu {

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

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

if (array[i] == num) {

return i;

}

}

return -1;

}

public static void main(String[] args) {

int[] arr = {1, 3, 5, 10, 9, 8};

int num = findNum(arr, 9);

System.out.println(num);

}

}

注意: 顺序查找数组中的某个数的下标是最低效的方法,并且不要漏掉查不到下标返回-1这种情况.

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


注意:数组的二分查找建立在这个数组是一个有序数组的前提下

代码示例:

public class suanshu {

public static int binarySerach(int[] array, int num) {

int left = 0;

int right = array.length - 1;

while (left <= right) {

int mid = (left + right) / 2;

if (array[mid] == num) {

return mid;

} else if (num > array[mid]) {

left = mid + 1;

} else {

right = mid - 1;

}

}

//没有找到的话返回-1

return -1;

}

public static void main(String[] args) {

int[] arr = {1, 4, 7, 9, 4, 8};

//因为二分法建立在有序数组上,所以要先进行排序

Arrays.sort(arr);

int num = binarySerach(arr, 8);

System.out.println(num);

}

}

使用二分法查找数组中的某个数字的时候,要注意首先这个数组必须是有序数组,其次需要考虑三种情况:

1.如果直接查询到的话,返回下标即可。

2.经过几轮查询后查询到,返回下标。

3.如果查询不到,就返回-1.

当然上述是我们自己实现了我们二分查找的方法,我们的Arrays工具类也为我们提供了二分查找的方法,也就是我们的Arrays.binarySearch方法,代码如下:

public class suanshu {

public static void main(String[] args) {

int[] arr = {1, 3, 5, 10, 9, 8};

int num= Arrays.binarySearch(arr,9);

System.out.println(num);

}

}

输出结果为4,结果无误。

4.7检查数组的有序性


给定一个数组,判断这个数组是否是升序还是降序

代码示例:

public class suanshu {

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;

}

public static void main(String[] args) {

int[] arr = {1, 3, 5, 10, 9, 8};

System.out.println(isSorted(arr));

}

}

上述代码判断的是一个数组是否为升序,是的话返回true,不是true返回false

注意:i此时小于的是array.length-1,原因是假如i小于的是array.length的话,当i=array.length-1,那么i+1=array.length,便会发生越界冲突异常。

4.8数组排序(冒泡排序)


分享

首先分享一份学习大纲,内容较多,涵盖了互联网行业所有的流行以及核心技术,以截图形式分享:

(亿级流量性能调优实战+一线大厂分布式实战+架构师筑基必备技能+设计思想开源框架解读+性能直线提升架构技术+高效存储让项目性能起飞+分布式扩展到微服务架构…实在是太多了)

其次分享一些技术知识,以截图形式分享一部分:

Tomcat架构解析:

算法训练+高分宝典:

Spring Cloud+Docker微服务实战:

最后分享一波面试资料:

切莫死记硬背,小心面试官直接让你出门右拐

1000道互联网Java面试题:

Java高级架构面试知识整理:

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取


给定一个数组,判断这个数组是否是升序还是降序

代码示例:

public class suanshu {

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;

}

public static void main(String[] args) {

int[] arr = {1, 3, 5, 10, 9, 8};

System.out.println(isSorted(arr));

}

}

上述代码判断的是一个数组是否为升序,是的话返回true,不是true返回false

注意:i此时小于的是array.length-1,原因是假如i小于的是array.length的话,当i=array.length-1,那么i+1=array.length,便会发生越界冲突异常。

4.8数组排序(冒泡排序)


分享

首先分享一份学习大纲,内容较多,涵盖了互联网行业所有的流行以及核心技术,以截图形式分享:

(亿级流量性能调优实战+一线大厂分布式实战+架构师筑基必备技能+设计思想开源框架解读+性能直线提升架构技术+高效存储让项目性能起飞+分布式扩展到微服务架构…实在是太多了)

其次分享一些技术知识,以截图形式分享一部分:

Tomcat架构解析:

[外链图片转存中…(img-GBR4V1qG-1715632938691)]

算法训练+高分宝典:

[外链图片转存中…(img-ZIXNXm2g-1715632938692)]

Spring Cloud+Docker微服务实战:

[外链图片转存中…(img-Yv2gJiv0-1715632938692)]

最后分享一波面试资料:

切莫死记硬背,小心面试官直接让你出门右拐

1000道互联网Java面试题:

[外链图片转存中…(img-IgSV5coO-1715632938692)]

Java高级架构面试知识整理:

[外链图片转存中…(img-nqHA8nGg-1715632938693)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 24
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值