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

Java---入门基础篇(下)---方法与数组

前言

本篇文章主要讲解有关方法与数组的知识点 ,是基础篇的一部分 , 而在下一篇文章我会讲解类和对象的知识点 

入门基础篇上的链接给大家放在下面啦 !

Java---入门基础篇(上)-CSDN博客

感谢大家点赞👍🏻收藏⭐评论✍🏻

欢迎各位大佬指点,相互学习,一起进步!


目录

前言

一.方法的使用

1.什么是方法?

2.方法的定义

3.方法调用的执行过程

4.实参和形参的关系 

5.没有返回值

二.方法重载

1.什么是重载?

2.方法重载的概念

三.递归

1.什么是递归?

2.执行过程分析

3.练习

四.数组的基本概念

1.数组的创建与定义

2.数组的使用

2.1.数组访问:

2.2.遍历数组:

3.数组是引用类型

3.1基本数据类型与引用数据类型的区别

3.2空引用null

3.3参数传参

3.4返回值

五.数组练习 

1.数组转字符串

2.数组拷贝 

3.查找数组中的指定元素 

4.判断一个数字是否存在于数组中 

5.冒泡排序

 6.数组逆序

六.二维数组 


一.方法的使用

1.什么是方法?

方法就是一个代码片段 , 学会C语言的伙伴们可以发现与  C 语言中的 " 函数 "类似:
比如:有三个人分别来问我相同的问题,我每次都要回答他们一遍 , 很麻烦,但如果我一次把问题整理好每当有人来问的时候我直接把文件发给他 , 就会容易很多 , 不用重复的做一样的工作了.

优点:

  • 一个代码可以在多个位置使用
  • 让代码更好理解更简单 
  • 直接调用现有的开发 , 不用重复做繁琐的工作 

2.方法的定义

修饰符 返回值类型 方法名称(参数类型 形参 ...){
方法体;
return 返回值;
}

eg:判断是否为闰年 

import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (true){System.out.println("请输入年份:  ");int year = sc.nextInt();boolean a = isLeapYear(year);//调用方法时也要定义变量,并写上类型System.out.println(year + "是闰年吗? 请回答:" + a);}}public static boolean isLeapYear(int year) {//此为方法的部分 if (year % 100 == 0) {if (year % 400 == 0) {return true;} else {return false;}} else {if (year % 4 == 0) {return true;} else {return false;}}}
}

 

上面所展示的是一个参数的写法 , 下面介绍两个参数是如何编写

public class Test {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入:");int sum1 = sc.nextInt();int sum2 = sc.nextInt();int d = add(sum1, sum2);//实际参数,需要两个System.out.println(d);}public static int add(int x, int y) {//形式参数,需要两个return x + y;}
}
注意:
1. 修饰符:现阶段先直接使用 public static 固定搭配,下一篇文章会讲解类的使用
2. 返回值类型:如果方法有返回值,返回值类型必须要与返回的实体类型一致,如果 没有返回值,必须写成 void
无返回值:  下面会讲(5.)
3. 方法名字:采用 小驼峰 命名(属于软性规则) eg: isLeapYear (只有第一个单词首字母小写)
4. 参数列表:如果方法没有参数, ()中什么都不写 ,如果有参数,需指定参数类型,多个参数之间使用逗号","隔开
5. 方法必须写在类中 ,就像上述代码一样,都写到了public class Test中
6. 方法不能嵌套定义 ,但是可以嵌套调用

3.方法调用的执行过程

调用方法 --- > 传递参数 --- > 找到方法地址 --- > 执行被调方法的方法体 --- > 被调方法结束返回 --- > 回到主调方法继续往下 执行

方法中结束的标志时遇到return,没有返回值就是执行到'' } "

下面用一个具体的例子直观的展示方法的优点:

计算1!+2!+3!+4!...+n!

不包含方法的写法:(运用了多次循环嵌套,不是很直观)

public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入");int n = sc.nextInt();int sum = 0;int m=1;for (int i = 1; i <= n; i++) {for (int j = 1; j <= 1; j++) {m = m * i;}sum=sum+m;}System.out.println(sum);}

 而运用了方法之后,避免了使用二重循环,让代码更简单清晰

public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入");int n = sc.nextInt();int sum = 0;for (int i = 1; i <= n; i++) {sum = sum + mul(i);}System.out.println(sum);
}
public static int mul(int a) {int m = 1;for (int i = 1; i <= a; i++) {m = m * i;}return m;
}

4.实参和形参的关系 

形参的名字可以随意取,对方法都没有任何影响,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值 。比如:
我们想实现两数交换的函数,但结果并没有成功是为什么呢?
可以看到,在 swap 函数交换之后,形参 x y 的值发生了改变,但是 main 方法中 a b还是交换之前的值,即没有交换成功。因为 Java 中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体.  详细来说:
  • 实参a和bmain方法中的两个变量,其空间在main方法的栈(一块特殊的内存空间)中,而形参x和yswap方法中的两个变量,xy的空间在swap方法运行时的栈中,因此:实参ab 与 形参xy是两个没有任何关联性的变量.
  • swap方法调用时,只是将实参ab中的值拷贝了一份传递给了形参x和y,因此对形参xy操作不会对实参ab 产生任何影响。即:调用

在c语言中可以用到指针来交换,那么Java中应该怎么办呢?

引用类型参数,在下面的数组会讲解.

5.没有返回值

有返回值时需要接收, 可以用变量来接收,也可以放入打印里 

注意:接收的变量的类型和方法的返回值类型要一致(也可以是能通过隐式转换或者是显式转换过去的)

System.out.println(add(a));

没有返回值时,返回值类型必须写成void 

可以不用接收直接调用 

二.方法重载

1.什么是重载?

首先看下面这张图 , 我们要实现的是两个数字相加的程序 ,由于我们只设置了int类型的两数之和的方法 , 会导致double类型的报错 

所以我们需要再加上double类型的两数之和相加 , 我们发现:虽然都是时间加和的程序 , 但是它们的命名并不相同

并且如果有很多不同的相加程序,所起的名字也会变得更加麻烦 ,比如下面的程序:

都是表示相加的程序 , 但他们可能是个数不一样 , 或者是类型不一样 , 这就导致了我们要起四个不同的名字 , 会变得更加繁琐 , 那么可不可以所有表示相加的都起一样的名字呢 ?

 .答案是可以的 这时,我们就可以使用方法重载

即全部命名为add,这个在Java中是可以实现的 ,但是要注意:相同的方法命名它们 不是类型不同 就是个数不同 ,否则就是重定义了,如下:

下图就表示重定义 , 即使他们变量名字不同,只要红色的地方一样 , 就不叫做方法重载 

返回值类型改成double了也不可以构成重载 , 只看我画红色的地方

2.方法重载的概念

1)在 Java 中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了
(也就相当于"一词多义")
2)注意:
  •  方法名必须相同
  •  参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)
  •  与返回值类型是否相同无关
  •  编译器在编译代码时,会对实参类型进行推演,根据推演的结果来确定调用哪个方法

三.递归

1.什么是递归?

从前有坐山,山上有座庙,庙里有个老和尚给小和尚将故事,讲的就是:
" 从前有座山,山上有座庙,庙里有个老和尚给小和尚讲故事,讲的就是:
" 从前有座山,山上有座庙 ..."
" 从前有座山 ……"
"
又或者,梦中梦,一环扣一环
递归也是如此,a方法中又重新调用着a方法.
eg:递归求n 的阶乘
public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入: ");int n = scanner.nextInt();int ret = fact(n);System.out.println(ret);}public static int fact(int n) {if (n == 1) {return 1;}return n * fact(n - 1);}
}

2.执行过程分析

在Java中每一次调用,都需要为本次方法调用在内存的栈区申请一块内存空间来保存方法调用期间的各种局部变量的值,这块空间被称为栈帧。

方法不返回,方法对应的栈帧空间就一直占用,所以函数调用中存在递归调用的话,每一次递归调用都会开辟属于自己的栈帧空间,直到递归不再继续,开始回归,才逐层释放栈帧空间。

所以如果采用方法递归的方式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出的问题。

3.练习

1)分析:输入一个整数,按照顺序打印一个整数的每一位

eg:

输入:1234 输出:1 2 3 4

12341234%10=41234/10=123123%10=3123/10=1212%10=212/10=11%10=11/10=0

 以上方法容易理解但是很麻烦,所有数都需要一个一个打,但是数字很大就无法做到了

public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入: ");int n = scanner.nextInt();print1(n);}public static void print1 (int n) {if(n>9){print1(n/10);//目的是将位数减一位}System.out.println(n%10);}
}

2).递归求 1 + 2 + 3 + ... + 10 

public class Test {public static void main(String[] args) {int ret = add(10);System.out.println(ret);}public static int add(int n) {if(n==1){return 1;}return n+add(n-1);}
}

注意:如果上述的方法去掉n==1就返回的程序,那么会导致程序一直循环进行 , 而递归调用方法的时候会创建栈帧 , 递归几次就会创建几层 , 每层栈帧都会消耗一定的存储空间的 , 达到一定层数后就可能把栈空间给消耗完毕了  

3).写一个递归方法,输入一个非负整数,返回组成它的数字之和 . 例如,输入 1729, 则应该返回 1+7+2+9,它的和是 19
public class Test {public static void main(String[] args) {int n = 1729;int ret = add(n);System.out.println(ret);}public static int add(int n) {if (n < 9) {return n;}return n % 10 + add(n / 10);}
}

 4)斐波那契数列

public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
}
return fib(n - 1) + fib(n - 2);
}

从这里我们也可以看到虽然才算到第6项,但是需已经调用方法很多次了,当执行fib(40)的时候,次数高达1亿多次,进行了太多的重复运算, 而每一次递归调用都会开辟属于自己的栈帧空间,所以当我们求fib(50)时,就会发现半天不出结果,结果还为负数,原因是开辟了太多的栈帧空间,导致溢出了

解决办法(针对斐波那契): 循环

public static int fib(int n) {
int last2 = 1;
int last1 = 1;
int cur = 0;
for (int i = 3; i <= n; i++) {
cur = last1 + last2;
last2 = last1;
last1 = cur;
}
return cur;
}

四.数组的基本概念

1.数组的创建与定义

如果想要打印出5个商品的价格,那么就要设立5个变量,那么要是100个商品呢,难道要设置100的变量吗?有没有一次就能打印出所有价格的方法呢?数组就可以做到

那么什么是数组?

数组就是相同类型的元素集合,且空间连在一起

下面来讲解如何创建数组?

1.数组的创建

T[] 数组名 = new T[N];
//T为数组存放的元素类型
//T[]为数组的类型
//N为数组的长度
//new为关键字

eg:创建一个可以容纳10个int类型元素的数组

int[] array = new int[10];

2.数组的初始化 

1)动态初始化:直接指定数组中的元素个数 

int[] array = new int[10];

2)静态初始化:不指定数组中的元素个数 , 而是根据后方{}里的元素个数 , 来计算数组中的长度

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

 注意1:静态初始化

  • {}内的元素类型要与[]前的类型一致
  • new int[]可以省略,为int[] array = {1,3,4,2,2,2,5,5};
  • 虽然省略了new int[] , 但是编译器编译代码时还是会还原

注意2:在c语言中,定义数组的方法为  int array[] = {1,3,4,2,2,2,5,5};

虽然java中也可以这样写,但是不建议,因为int[]在一起更能直观的表示为int类型的数组

否则可能理解为数组的类型为int .

注意3:两种初始化格式都可以分为两步

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

但如果是静态初始化中的省略格式则不能分为两步,下面所述代码就是一个错误示范. 

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

注意4:如果没有对数组进行初始化,数组中元素有默认值  

 eg:如果数组中的元素为基本数据类型 , 默认值为对应类型对应的默认值

类型默认值
byte 0
shut 0
int0
long0
float0.0f
double0
char/u0000
booleanFALSE
注意:如果数组中存储元素类型为引用数据类型 , 默认值为null 

2.数组的使用

2.1.数组访问:

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

同时,我们也可以通过赋值改变某项的值

注意1:数组的内存空间是连续的 , 因此支持随机访问

(ps:随机访问:随机访问是指可以直接访问任意存储单元中的数据,而不需要按照顺序逐个读取 , 数组的随机访问意味着可以直接、快速地访问数组中的任何元素,而无需按顺序遍历数组)

注意2:注意不要越界 , 例如上图中array数组中最大的下标为4 , 不能超过4,否则会出现以下提示 

错误提升如下

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5at Test.main(Test.java:8)
//线程 “main” java.lang 中出现异常。at Test.main(Test.java:8)数组索引越界异常:
索引 5 超出长度 5 的界外

2.2.遍历数组:

1) 第一种方法是分别访问数组中的每一个元素并进行打印 

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

但是如果数组中元素有很多长达几百个时 , 难道需要几百个打印语句吗 ?

2)循环打印数组中的每一个元素 

int[] array = {1,3,5,7,9};
for(int i=0;i<array.length;i++) {//注意:.是成员访问运算符,array.length就是求数组中的元素个数System.out.println(array[i]);
}
//打印结果:
1
3
5
7
9

3)使用for-each遍历数组 

int[] array = {1,3,5,7,9};
for(int num:array){System.out.println(num);
}
//打印结果
1
3
5
7
9

注意:   for-each方法虽然简单 , 但存在很多限制 , 只能读取数组元素  , 而不能修改 , 只能按照顺序从前往后读取 (只是将数组中的元素保存在了变量中 )

eg: 当我们想要修改数组中的元素时,for-each的改法如下,但事实上并没有改变数组的元素大小,而是改变了num这个变量的大小 .

int[] array = {1,3,5,7,9};
for(int num:array){num = num*100;System.out.println(num);
}//此代码相当于for循环中的如下写法for(int i=0;i< array.length;i++){int num = array[i];num= num*100;System.out.println(num);}

正确方法如下:

int[] array = {1,3,5,7,9};
for(int i=0;i< array.length;i++){array[i] = array[i]*100;System.out.println(array[i]);
}
//打印结果
100
200
300
400
500

 4)通过数组名来打印数组 

int[] array = {1,3,5,7,9};
System.out.println(Arrays.toString(array));
//打印结果
[1, 3, 5, 7, 9]

3.数组是引用类型

3.1基本数据类型与引用数据类型的区别

基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值
引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址

引用数据类型包括:类、 接口、 数组、 枚举、 注解等

主要区别:

基本数据类型是直接保存在栈中的

引用数据类型在栈中保存的是一个地址引用,这个地址指向的是其在堆内存中的实际位置。(栈中保存的是一个地址,而实际的内容是在堆中,通过地址去找它实际存放的位置)

引用数据类型在创建时,系统会分配两块空间,一块存放引用地址,一块存放实际的对象

引用数据类型赋值给另一个变量时,赋的是内存地址,而不是实际的数据

public static void func() {
int a = 10;
int b = 20;
int[] arr1 = new int[]{1,2,3};
int[] arr2 = arr1;//将arr1的地址赋值给arr2
}

如果两个引用数据的变量指向同一个对象时,一个变量修改值,另一个变量的值一样会受到影响。

public static void func() {
int a = 10;
int b = 20;
int[] arr1 = new int[]{1,2,3};
int[] arr2 = arr1;//将arr1的地址赋值给arr2
arr2[0]=100;
}

因为arr1和arr2的地址是一样的 , 那他们对应的堆中对应的内容就是一样的 ( 因为是根据地址来找对应的堆的内容 )

当代码添加arr2[0]=100时,也就相当于修改了堆中的内容 , 所以arr1中的内容也会被修改

举例来说:

如果引用是一把钥匙(arr1是一把钥匙 , 又配了一把一样的钥匙 , 也就是arr2) 

存在于堆中的 new 出来的数组本体,看作是一个房子 , 那么如果通过arr2钥匙修改了房子中的内容那么arr1钥匙打开看到的也是被修改的. 

从上图可以看到,引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象。有点类似C语言中的指针,但是Java中引用要比指针的操作更简单。只有以下四种: 

  • 引用像指针一样能保存内存地址 
  • 引用可以相互赋值 或 判断相等
  • 针对数组的引用 , 可以用 [] 访问元素
  • 成员访问功能 

3.2空引用null

null在Java中表示"空引用",即不指向对象的引用 

类似c中的空指针NULL ,都表示无效的内存位置

那么空引用到底有什么用处呢?

空引用主要是用来表示,一个对象还没有被初始化,当你在代码里可能需要先声明一个变量,但是呢,又不想马上给它分配内存空间,这时候就可以用空引用了。还有就是,比如说你要返回一个对象,但是呢在某些情况下又没有合适的对象可以返回,这时候也可以返回一个空引用。不过,空引用确实容易出问题,所以在Java里边,从Java七开始吧,就引入了Optional类,来处理空引用的问题,这样就更安全一些。

3.3参数传参

1)

 public static void main(String[] args) {int[] arr1 = new int[]{1,2,3};func(arr1);System.out.println(arr1[0]);}public static void func(int[] arr2) {//将arr1的地址复制给arr2arr2[0] = 10;//通过地址来找到实际的内容并修改System.out.println(arr2[0]);}
//打印结果
10
10

注意:传过去的是地址,所以arr2可以根据地址找到实际的值并修改,所以arr1与arr2都被修改

2)

public static void main(String[] args) {int[] arr1 = new int[]{1,2,3};func(arr1);System.out.println("arr1[0]为"+arr1[0]);}public static void func(int[] arr2) {//将arr1的地址复制给arr2arr2 = new int[]{3,4,5};//将此数组的首地址赋值给arr2//注意这块不要重定义// 上一行代码已经定义过它是一个int类型的数组了System.out.println("arr2[0]为"+arr2[0]);//此打印是根据arr2来找到的实际的内容}
//打印结果
arr2[0]为3
arr1[0]为1

注意:虽然传过去的也是地址但是在func方法中修改了arr2的地址  

即:1)修改了实际的内容(改了房子里的布置)

    2)修改了地址(换成了另一把钥匙打开了另一座房子)

总结:

  • 方法内部针对引用的修改 , 不总是能影响到外面的 , 关键要看对引用修改是怎样的操作 
  • 如果修改的是引用指向的对象本体(通过 [ ] . ) , 此时的修改是能够被方法外部感知到的 
  • 如果修改的是引用本身(通过=修改引用中保存的地址), 此时的修改不能被方法外部感知到

3.4返回值

(上图画红框处,左边的代码为Java,右边为c语言)

在C语言中定义的a数组是局部变量 , 当执行完函数之后 , 局部变量就释放内存 , 如果在函数外部调用 , 由于数组所在的空间已经被销毁了 , 返回了数组的首地址也根本不会找到它 , 即为访问非法的内存空间 , 因此右侧c语言的写法是错误的 .

(相当于已经把酒店的房间退了 , 但是用私自配的房卡 , 强行开这个门 , 看到的房间里的内容是随机的 )

在Java中数组的实际内容 , 是存在于中的 , 但是随着方法的结束 , 销毁的是a引用 , 并没有消除堆上数组的实际内容 , 所以a引用的地址指向的内存是仍然有效的 . 因此Java的写法是正确

那怎么释放堆上的空间呢?什么时候会被释放掉呢?---"垃圾回收机制 "

答案是:你new出来的对象或数组当你的代码中没有任何地方使用这样的对象或数组的时候就会被JVM自动释放掉 , 完全不需要自己写代码来进行干预 , JVM察觉出来你一定不会用到它时就会释放掉 , 这样的机制称为"垃圾回收机制",简称GC.

  • 缺点:
  • 消耗更多的系统资源来实现自动释放内存功能
  • 运行过程中消耗更多的时间

例如:求斐波那契数列前10项.

public class Test {public static void main(String[] args) {System.out.println("请打印斐波那契数列的前十项: ");int arr[] = func(10);System.out.println( Arrays.toString(arr));}public static int[] func(int n) {int[] arr= new int[n];if (n <= 0) {return null;}if (n > 0) {arr[0] = 1;arr[1] = 1;for (int i = 2; i < n; i++) {arr[i] = arr[i - 1] + arr[i - 2];}}return arr;}
}

五.数组练习 

1.数组转字符串

使用Java自带的方法---Arrays.toString(arr)

需要添加---import java.util.Arrays

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]

那么这个自带的方法是如何实现的呢?

在这之前大家需要知道的是字符串是可以通过加号连接在一起的 

 

所以模拟实现此方法的代码为:

public static String ArraytoString(int[] arr) {String result = "[";for (int i = 0; i < arr.length; i++) {result += arr[i];if(i<arr.length-1){result += ",";}}result += "]";return result;
}

2.数组拷贝 

第一种方法: int[] newarr = arr;//复制数组对应的地址

第二种方法: Arrays.copyOf(arr, arr.length);//复制数组的实际内容

import java.util.Arrays;
public static void func(){
// newarr和arr引用的是同一个数组
// 因此newarr修改空间中内容之后,arr也可以看到修改的结果
int[] arr = {1,2,3};
int[] newarr = arr;
newarr[0] = 100;
System.out.println("newarr: " + Arrays.toString(arr));//打印结果为{100,2,3}// 使用Arrays中copyOf方法完成数组的拷贝:
// copyOf方法在进行数组拷贝时,创建了一个新的数组,只是内容一样,但无关系
// arr和newarr引用的不是同一个数组,是两个内容相同的数组
arr[0] = 100;
newarr = Arrays.copyOf(arr, arr.length);
System.out.println("newarr: " + Arrays.toString(newarr));//打印结果为{1,2,3}
}

 

所以第二种方法在修改其中一个数组内容的时候 ,不会影响另一个,都是独立个体.

注意:也可以拷贝某一部分的范围 

同样我们来实现Arrays.copyOf此方法的编写过程

public class Test {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5};int[] arr2=copyOf(arr,7);}public static int[] copyOf(int[] arr,int newLength) {int[] result = new int[newLength];//定义数组长度为7int len = Math.min(arr.length,newLength);for(int i=0;i<len;i++){result[i]=arr[i];//只复制过去了前五项,一开始全部为0}return result;//最后返回数组的内容}
}

3.查找数组中的指定元素 

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

(顺序查找)

//顺序查找
public class Test {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5};int ret = search(arr,3);System.out.println(ret);}public static int search(int[] arr,int a) {for(int i=0;i<arr.length;i++){if(a==arr[i]){return i;}}return -1;}
}
//结果为2

(二分查找) 

public class Test {public static void main(String[] args) {int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,15,16,17,18,19,20};System.out.println(binarysearch(arr1, 8));}public static int binarysearch(int[] arr, int tofind) {int left = 0;int right = arr.length - 1;while (left <= right) {int mid = (left + right) / 2;if (tofind < arr[mid]) {right = mid - 1;} else if (tofind > arr[mid]) {left = mid + 1;} else {return mid;//找到了返回下标}}return -1;//没找到退出}
}

4.判断一个数字是否存在于数组中 

public class Test {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5};Scanner sc = new Scanner(System.in);int ret =sc.nextInt();System.out.println(search(arr,ret));}public static boolean search(int[] arr,int a) {for(int i=0;i<arr.length;i++){if(a==arr[i]){return true;}}return false;}
}

5.冒泡排序

假设排升序:
1. 将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来后最大元素
就在数组的末尾
2. 依次从上上述过程,直到数组中所有的元素都排列好
import java.util.Arrays;public class Test {public static void main(String[] args) {int[] arr1 = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 48, 19, 50};bubblesort(arr1);System.out.println(Arrays.toString(arr1));}public static void bubblesort(int[] arr2) {for (int i = 0; i < arr2.length - 1; i++) {for (int j = 1; j < arr2.length - i;j++) {if (arr2[j - 1] > arr2[j]) {int tmp = arr2[j - 1];arr2[j - 1] = arr2[j];arr2[j] = tmp;}}}}
}

 6.数组逆序

设定两个下标 , 分别指向第一个元素和最后一个元素 . 交换两个位置的元素 .
然后让前一个下标自增 , 后一个下标自减 , 循环继续即可数
public class Test {public static void main(String[] args) {int[] arr = {2,1,5,8,6,3};reserve(arr);System.out.println(Arrays.toString(arr));}public static void reserve(int[] arr) {int left=0;int right=arr.length-1;while(left<right){int tmp=arr[left];arr[left]=arr[right];arr[right]=tmp;left++;right--;}}
}

六.二维数组 

二维数组本质上也就是一维数组 , 只不过每个元素又是一个一维数组 .
数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };
注意:二维数组的用法和一维数组并没有明显差别
同理 , 还存在 " 三维数组 ", " 四维数组 " 等更复杂的数组 , 只不过出现频率都很低 .
注意:在Java中,数组的长度不要求一致,注意和C语言进行区分
本次内容就到这里啦,大家基础一定要打好,后面的学习也会上升难度了

 

相关文章:

Java---入门基础篇(下)---方法与数组

前言 本篇文章主要讲解有关方法与数组的知识点 ,是基础篇的一部分 , 而在下一篇文章我会讲解类和对象的知识点 入门基础篇上的链接给大家放在下面啦 ! Java---入门基础篇(上)-CSDN博客 感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb; 欢迎各位大佬指点…...

【分布式理论11】分布式协同之分布式事务(一个应用操作多个资源):从刚性事务到柔性事务的演进

文章目录 一. 什么是分布式事务&#xff1f;二. 分布式事务的挑战三. 事务的ACID特性四. CAP理论与BASE理论1. CAP理论1.1. 三大特性1.2. 三者不能兼得 2. BASE理论 五. 分布式事务解决方案1. 两阶段提交&#xff08;2PC&#xff09;2. TCC&#xff08;Try-Confirm-Cancel&…...

【文献阅读】Collective Decision for Open Set Recognition

基本信息 文献名称&#xff1a;Collective Decision for Open Set Recognition 出版期刊&#xff1a;IEEE TRANSACTIONS ON KNOWLEDGE AND DATA ENGINEERING 发表日期&#xff1a;04 March 2020 作者&#xff1a;Chuanxing Geng and Songcan Chen 摘要 在开集识别&#xff0…...

Gorm中的First()、Create()、Update()、Delete()的错误处理

一. First() result : tx.Model(&models.Attachment{}).Where("home ? AND home_id ?", attachment.Home, attachment.HomeID).First(&existingAttachment)如果没有查询到数据&#xff0c;result.Error的值是什么&#xff1f; 在使用 GORM&#xff08;…...

【心得】一文梳理高频面试题 HTTP 1.0/HTTP 1.1/HTTP 2.0/HTTP 3.0的区别并附加记忆方法

面试时很容易遇到的一个问题—— HTTP 1.0/HTTP 1.1/HTTP 2.0/HTTP 3.0的区别&#xff0c;其实这四个版本的发展实际上是一环扣一环的&#xff0c;是逐步完善的&#xff0c;本文希望帮助读者梳理清楚各个版本之间的区别&#xff0c;并且给出当前各个版本的应用情况&#xff0c;…...

Navicat连接虚拟机数据库详细教程

Navicat连接虚拟机数据库详细教程 以Windows主机 上的navicat 连接ubuntu虚拟机为例 确认虚拟机ip地址和主机ip地址 主机地址查询 cmd输入ipconfig 登录mysql 创建用户 CREATE USER newuserlocalhost IDENTIFIED BY password; CREATE USER newuser% IDENTIFIED BY passwor…...

委托者模式(掌握设计模式的核心之一)

目录 问题&#xff1a; 举例&#xff1a; 总结&#xff1a;核心就是利用Java中的多态来完成注入。 问题&#xff1a; 今天刷面经&#xff0c;刷到装饰者模式&#xff0c;又进阶的发现委托者模式&#xff0c;发现还是不理解&#xff0c;特此记录。 举例&#xff1a; ​老板​…...

DeepSeek-R1 论文笔记:通过强化学习提升大语言模型的推理能力

论文标题&#xff1a;DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning 作者团队&#xff1a;DeepSeek-AI 发表时间&#xff1a;2025 前置知识 & 术语 模型蒸馏 语言模型蒸馏的目标是将大型教师模型的知识&#xff08;如语义理解、上…...

实现Unity shader扭曲效果

实现思路 1、扭曲材质赋于面片 2、抓取当前一帧的图片内容 3、获取屏幕坐标 4、利用屏幕坐标对抓取的图片采样 5、再采样张扰动贴图做扭曲 Shader "Unlit/NewUnlitShader" {Properties {_DistortTex ("扰动贴图 (RGB)", 2D) "bump" {}_Di…...

七星棋牌 6 端 200 子游戏全开源修复版源码(乐豆 + 防沉迷 + 比赛场 + 控制)

七星棋牌源码 是一款运营级的棋牌产品&#xff0c;覆盖 湖南、湖北、山西、江苏、贵州 等 6 大省区&#xff0c;支持 安卓、iOS 双端&#xff0c;并且 全开源。这个版本是 修复优化后的二开版本&#xff0c;新增了 乐豆系统、比赛场模式、防沉迷机制、AI 智能控制 等功能&#…...

C++STL---<limits>

C <limits> 头文件&#xff1a; <limits> 头文件是 C 标准库中用于获取各种数据类型的数值范围、精度等信息的工具。它通过模板类 std::numeric_limits 提供了对基本数据类型&#xff08;如 int、float、double 等&#xff09;的详细属性查询功能。通过 std::nume…...

一键安装Mysql部署脚本之Linux在线安装Mysql,脚本化自动化执行服务器部署(附执行脚本下载)

相关链接 一键安装Redis部署脚本之Linux在线安装Redis一键安装Mysql部署脚本之Linux在线安装Mysql一键安装JAVA部署脚本之Linux在线安装JDK一键安装Nginx部署脚本之Linux在线安装NginxNavicat最新版(17)详细安装教程Xshell客户端免费版无需注册XFtp客户端免费版无需注册 前言…...

ES、OAS、ERP、电子政务、企业信息化(高软35)

系列文章目录 ES、OAS、ERP、电子政务、企业信息化 文章目录 系列文章目录前言一、专家系统&#xff08;ES&#xff09;二、办公自动化系统&#xff08;OAS&#xff09;三、企业资源规划&#xff08;ERP&#xff09;四、典型信息系统架构模型1.政府信息化和电子政务2.企业信息…...

文生图开源模型发展史(2014-2025年)

文生图开源模型的发展历程是一段充满技术革新、社区生态繁荣与商业化竞争的多维度演进史。 一、技术萌芽期&#xff08;2014-2020年&#xff09; 核心突破 2014年&#xff1a;GAN&#xff08;生成对抗网络&#xff09;诞生&#xff0c;首次实现数据驱动式图像生成&#xff0…...

OA办公系统自动渗透测试过程

目录 一、下载环境源码 二、部署环境 三、测试 XSS漏洞 SQL注入 文件上传漏洞 一、下载环境源码 OA源码打包地址: https://download.csdn.net/download/weixin_43650289/90434502?spm=1001.2014.3001.5503 二、部署环境...

Python标准库【os】5 文件和目录操作2

文章目录 8 文件和目录操作8.7 浏览目录下的内容8.8 查看文件或目录的信息8.9 文件状态修改文件标志位文件权限文件所属用户和组其它 8.10 浏览Windows的驱动器、卷、挂载点8.11 系统配置信息 os模块提供了各种操作系统接口。包括环境变量、进程管理、进程调度、文件操作等方面…...

[代码规范]接口设计规范

一个优雅的接口要如何设计&#xff1f;有哪些设计规范可以遵循&#xff1f; 下面抛砖引玉&#xff0c;分享一些规范。 目录 1、RESTful API 设计最佳实践 2、Shneiderman 的 8 条黄金法则 3、Nielsen 的 10 条启发式规则 1、RESTful API 设计最佳实践 一共18条&#xff0c;参考…...

什么是最终一致性,它对后端系统的意义是什么

最终一致性(Eventual Consistency)是分布式系统中的一种一致性模型。与传统的强一致性模型不同,最终一致性并不要求系统在任何时刻都保持一致,而是保证在足够的时间后,所有节点的数据最终会达到一致的状态。换句话说,系统允许短时间内出现数据的不一致性,但最终会通过某…...

Unity学习笔记之——ugui的性能优化

在Unity中UI优化的核心问题就是重绘和批处理之间的平衡 一、Canvas优化要点 1.优化原因&#xff1a; &#xff08;1&#xff09;Unity为了性能优化&#xff0c;会合并Canvas下的所有元素&#xff1b; &#xff08;2&#xff09;如果把所有面板放到一个Canvas下&#xff0c;会…...

Python接口自动化中操作Excel文件的技术方法

在Python接口自动化测试中&#xff0c;操作Excel文件是一项常见且关键的技术需求。Excel作为数据存储和数据分析的重要工具&#xff0c;在自动化测试中通常用于存储测试用例、测试数据以及测试结果。通过Python操作Excel&#xff0c;可以大大提高测试的效率和灵活性。以下是一些…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...

数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)

目录 &#x1f50d; 若用递归计算每一项&#xff0c;会发生什么&#xff1f; Horners Rule&#xff08;霍纳法则&#xff09; 第一步&#xff1a;我们从最原始的泰勒公式出发 第二步&#xff1a;从形式上重新观察展开式 &#x1f31f; 第三步&#xff1a;引出霍纳法则&…...

FOPLP vs CoWoS

以下是 FOPLP&#xff08;Fan-out panel-level packaging 扇出型面板级封装&#xff09;与 CoWoS&#xff08;Chip on Wafer on Substrate&#xff09;两种先进封装技术的详细对比分析&#xff0c;涵盖技术原理、性能、成本、应用场景及市场趋势等维度&#xff1a; 一、技术原…...

CppCon 2015 学习:REFLECTION TECHNIQUES IN C++

关于 Reflection&#xff08;反射&#xff09; 这个概念&#xff0c;总结一下&#xff1a; Reflection&#xff08;反射&#xff09;是什么&#xff1f; 反射是对类型的自我检查能力&#xff08;Introspection&#xff09; 可以查看类的成员变量、成员函数等信息。反射允许枚…...