【Java】数组及应用

目录

一、数组的基本用法

1、创建数组

2、数组的使用

3、遍历数组

for 循环遍历数组

使用 for-each 遍历数组

二、数组作为参数

1、认识引用类型

2、认识null

3、认识JVM内存区域划分

三、认识二维数组

1、基本语法

2、循环输出二维数组的方法

(1)使用 for 循环嵌套

(2)使用 for-each 循环输出

(3)Arrays.deepToString(二维数组名);

四、部分Arrays方法

1、Arrays.toString(数组名);

2、Arrays.sort(数组名);

3、Arrays.binarySearch(数组名,值);

4、Arrays.fill(数组名,值);

5、Arrays方法之数组的拷贝

(1)Arrays.copyOf(原数组名,拷贝的长度);

(2)Arrays.copyOfRange(原数组名,起始下标,终止下标);

(3)数组名.clone();

(4)System.arraycopy(原数组名,原数组的起始下标,拷贝的数组名,拷贝数组的起始下标,需要拷贝的长度);

五、数组应用经典例题

1、冒泡排序

2、二分查找


上节我们说到方法的使用,这一节我们来说一说关于数组的使用。数组让我们能 "批量" 创建相同类型的变量,然后存放在一起。

一、数组的基本用法

1、创建数组

语法格式如下:

数据类型[] 数组名称 = { 初始化数据 };

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

数据类型[] 数组名称 = new 数据类型 [] { 初始化数据 };

例:

2、数组的使用

数组使用这块,Java提供了一个非常便捷的方法——

如果给一个数组arr[]赋了确定的初始值,则用 arr.length 即可快捷获取改数组的元素个数。

int[] arr = {1, 2, 3}; 
System.out.println("length: " + arr.length);// 执行结果 length:3

System.out.println(arr[1]); // 执行结果: 2 
System.out.println(arr[0]); // 执行结果: 1

 注:[ ]获取元素时从0开始,到  length-1 为止,超过这个范围,会出现数组越界,从而程序报错无法继续执行。

3、遍历数组

顾名思义,将数组中每个元素打印出来。

·for 循环遍历数组

int[] arr = {1, 2, 3};
 for (int i = 0; i < arr.length; i++) {
 System.out.println(arr[i]); 
}


// 执行结果
1

2

3

·使用 for-each 遍历数组

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

 for-each 相当于for循环的增强版,此时语法格式为:

for(元素类型 元素变量 : 遍历对象){ 
     引用了x的java语句; 
} 
来个实例:
int[] arr = {1, 2, 3};
 for (int x : arr) { 
System.out.println(x); 
}


// 执行结果 
1

2

3

二、数组作为参数

1、认识引用类型

我们先来对比两个例子。

public static void main(String[] args) {
     int num = 0; 
     func(num); 
     System.out.println("num = " + num); 
}

public static void func(int x) {
     x = 10; 
     System.out.println("x = " + x); 
}



// 执行结果 

x = 10
num = 0

此时,修改形参x的值,num的值却没有改变。

而如果以数组传参,

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]); 
}

// 执行结果 
a[0] = 10 
arr[0] = 10

此时,在方法内部修改了数组内容,函数外部也发生了变化。

2此时数组名 arr 是一个 "引用"

结论: 引用相当于一个 "别名", 也可以理解成一个指针。创建一个引用只是相当于创建了一个很小的变量, 这个变量保存了一个整数, 这个整数表示内存中的一个地址。

2、认识null

1、null Java 中表示 " 空引用 " , 也就是一个 无效的引用
2、null 的作用类似于 C 语言中的 NULL ( 空指针 ), 都是表示一个无效的内存位置 因此不能对这个内存进行任何读写操作。 一旦尝试读写, 就会报错——  NullPointerException。

3、认识JVM内存区域划分

JVM的内存被划分为了几个区域:

程序计数器(PC Register):保存下一条执行的指令的地址。

虚拟机栈(JVM Stack):重点是存储局部变量表,我们刚才创建的int[]arr这样的存储地址的引用就是在这里保存。

本地方法栈(Native Method Stack):本地方法栈与虚拟机栈的作用类似。只不过保存的内容是Native方法的局部变量。

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

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

运行时常量池(Runtime Constant Pool):是方法区的一部分,存放字面量(字符串常量)与符号引用。

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

 总结:1、局部变量引用保存在上,new 出的对象保存在。(如下图所示)

2、堆的空间非常大,栈的空间比较小

3、堆是整个 JVM 共享一个 ,而栈每个线程( Thread )具有一份。

三、认识二维数组

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

1、基本语法

数据类型 [][] 数组名称 = new 数据类型 [ 行数 ][ 列数 ] { 初始化数据 };
例:
注:当使用int[][] array = new int [2] [] ; 定义时,二维数组的第二维数字可以省略。
(相当于只指定了二维数组的 长度,不确定每个数组的元素个数)

2、循环输出二维数组的方法

(1)使用 for 循环嵌套

如上图所示, i 为数组一维的长度,j 为数组二维的长度。画个图,就清晰明多了:

(2)使用 for-each 循环输出

 如下图,如果array是二维数组,array中的每个元素就是一维数组。则外层 for 循环的 ret 就是拿到了 array 中的每个元素,则ret就是一维数组,内部循环是拿到 ret 一维数组中的每个元素。

 

 注:除了正常的输出,还可以用自带的Arrays方法 快捷得到二维数组的元素值——

(3)Arrays.deepToString(二维数组名);

调用该方法后打印,最后会以字符串的形式输出。

int[][] array= {{1,2,3}, {4,5,6}};
System.out.println(Arrays.deepToString(array)); 


//运行结果

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

四、部分Arrays方法

 那么问题来了,还有其他便捷的处理数组元素的方法吗? 

答案是当然有,这里列举几个常用的方法——

1、Arrays.toString(数组名);

这个与二维数组的输出有异曲同工之妙,就是将一维数组以字符串的形式输出。

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

//运行结果
[1, 2, 3, 4, 5]

2、Arrays.sort(数组名);

顾名思义,就是将数组自动按从小到大顺序排序。(向冒泡法say goodbye~)

 int[] array = {1,45,23,73,57,25,46};
 Arrays.sort(array);
 System.out.println(Arrays.toString(array));

//运行结果
[1, 23, 25, 45, 46, 57, 73]

3、Arrays.binarySearch(数组名,值);

实现二分查找功能,查找数组中有的数值,并返回其数组下标。

注:二分查找要求数组中元素必须是有序递增的,否则返回值会出问题。

int[] array = {1,3,5,7,9,13,15};
System.out.println(Arrays.binarySearch(array,3));

//运行结果
1

4、Arrays.fill(数组名,值);

【 或 Arrays.fill(数组名,数组起始下标,数组终止下标,值) 】

就是将某个值填入数组中,或者定向填入数组的某个位置中。

第一种用法:

int[] array = {1,45,23,73,57,25,46};
Arrays.fill(array,99);
System.out.println(Arrays.toString(array));

//运行结果
[99, 99, 99, 99, 99, 99, 99]

第二种:

int[] array = {1,45,23,73,57,25,46};
Arrays.fill(array,2,5,99);
System.out.println(Arrays.toString(array));

//运行结果
[1, 45, 99, 99, 99, 25, 46]

由此可见,第二个引用是左闭右开的 [2,5),并且注意输入的参数是直接从1开始的索引值,而非数组下标值!!!

5、Arrays方法之数组的拷贝

Arrays提供了不少数组拷贝的方法——

(1)Arrays.copyOf(原数组名,拷贝的长度);

int[] array = {1,45,23,73,57,25,46};
int[] array2=Arrays.copyOf(array,2);
System.out.println(Arrays.toString(array2));

//运行结果
[1, 45]

如上例子,可以只拷贝部分数组元素。

当然,也可以扩容,只需将第二个参数设置大于数组长度即可。如下例——

int[] array = {1,45,23,73,57,25,46};
int[] array2=Arrays.copyOf(array,10);
System.out.println(Arrays.toString(array2));

//运行结果
[1, 45, 23, 73, 57, 25, 46, 0, 0, 0]

(2)Arrays.copyOfRange(原数组名,起始下标,终止下标);

注:这里的起始位置指的是数组下标的起始位置,而不是数组长度的起始!并且取值范围是

[起始位置,终止位置)。如下例:

int[] array = {1,45,23,73,57,25,46};
int[] array2=Arrays.copyOfRange(array,2,5);
System.out.println(Arrays.toString(array2));

//运行结果
[23, 73, 57]

(3)数组名.clone();

这个不用传参,直接克隆,然后用新数组接收即可,比较便捷。

int[] array = {1,45,23,73,57,25,46};
int[] array2=array.clone();
System.out.println(Arrays.toString(array2));

//运行结果
[1, 45, 23, 73, 57, 25, 46]

(4)System.arraycopy(原数组名,原数组的起始下标,拷贝的数组名,拷贝数组的起始下标,需要拷贝的长度);

参数确实比较多,多用几遍就能理解了,上例子:

int[] array = {1,45,23,73,57,25,46};
int[] array2=new int[array.length];
System.arraycopy(array,2,array2,3,4);
System.out.println(Arrays.toString(array2));

//运行结果
[0, 0, 0, 23, 73, 57, 25]

五、数组应用经典例题

1、冒泡排序

将数组中的元素经过比较后,按升序的顺序输出。

import java.util.Arrays;
class testdemo {
        public static void main(String[] args) {
            int[] array = {3,26,17,38,16,42,33};
            bubbleSort(array);
        }

        public static void bubbleSort(int[] array){

            for (int i = 0; i < array.length-1; i++) {//外层循环代表要比较array.length-1趟
                boolean flag=false;
                for (int j = 0; j < array.length-1-i; j++) { //内层循环为每趟要进行比较的数                                                          
                    if (array[j]>array[j+1]){
                        int tmp =array[j];
                        array[j]=array[j+1];
                        array[j+1]=tmp;
                        flag =true;
                    }
                }
                if (flag==false)
                    break;
            }
            System.out.println(Arrays.toString(array));
        }
}



//运行结果
[3, 16, 17, 26, 33, 38, 42]

注:flag是用来优化代码的,只要有一趟中没有交换,说明数组已经有序了,即可直接退出循环,能让程序效率提高。

2、二分查找

(查找的数组必须是有序的)

class testdemo {
        public static void main(String[] args) {
            int[] array = {1,3,5,7,9,13};
            int key =13;
            System.out.println(binarySearch(array, key));
        }

        public static int binarySearch(int[] array,int key){
               int left =0;
               int right=array.length-1;
               while(left<=right) {
                   int mid=(left+right)/2;
                   if (key>array[mid]) {
                       left=mid+1;
                   } else if (key<array[mid]){
                       right=mid-1;
                   }else {
                       return mid;
                   }
               }
               return -1;
        }
}

//运行结果
5

我们下一节类与对象见!

to be continue →

欢迎大家互相探讨交流补充 欢迎捉虫!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玫瑰与鸢尾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值