初识Java(数组)

目录

认识数组

数组的定义

第一种定义方法且初始化

 第二种定义方法但不初始化

 第三种定义数组的且初始化的方式

 数组的基本用法

1.访问数组内容

 2.在数组上写入数据

 3.数组的遍历

①for循环遍历数组

 ②for-each遍历数组

③利用Java中操作数组的工具类 Arrays(数组内容以字符串的形式打印)

数组作为方法的参数

基本用法

JVM

数组在内存中的存储

null

数组作为方法的返回值

方法实现数组元素交换

数组作为方法的返回值

写一个方法以数组为形参,返回值为原数组

以方法为参数,返回值为新数组

模拟实现Arrays.toString()

在数组中查找元素

遍历查找

二分查找法(只适用与有序数组)

数组练习

判断数组是否有序

思路:

代码:

注意:

冒泡排序

思路:

代码:

注意

数组排序(奇数后,偶数前)

思路

代码

注意

数组逆序

思路

代码

数组拷贝

思路

代码

注意

二维数组

二位数组的定义

第一种定义

第二种定义

第三种定义

二维数组在内存的存储

二维数组的打印

第一种打印方式(遍历)

 第二种打印方式(for-each打印)

第三种打印方式(利用Arrays数组操作工具类)

例子



认识数组

数组是存储一组相同数据类型的数据的集合。

数组的定义

第一种定义方法且初始化

 第二种定义方法但不初始化

 第三种定义数组的且初始化的方式

 数组的基本用法

1.访问数组内容

数组的长度无需通过计算求得,可以通过arr.length直接求得。当数组下标为负数或者超出数组大小范围,会发生数组越界,编译器会报错,如:

 2.在数组上写入数据

 3.数组的遍历

①for循环遍历数组

        for (int i = 0;i < arr.length;i++){
            System.out.print(arr[i] + " ");
        }

 ②for-each遍历数组

for(数组中的数据类型定义一个整型变量用于接受整型变量 : 数组名)
例如:
for (int x : arr){
            System.out.print(x + " ");
        }

注意:for和for-each的区别:

for:可以拿到数组的下标。

for-each:不可以拿到数组的下标,一般运用与集合中。

③利用Java中操作数组的工具类 Arrays(数组内容以字符串的形式打印)

先导入数据包,用toString形式打印

import java.util.Arrays;
System.out.println(Arrays.toString(arr));

数组作为方法的参数

基本用法

JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

1.程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址.
2.虚拟机栈(JVM Stack): 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int[] arr 这样     的存储地址的引用就是在这里保存.
3.本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是        Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.
堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2,3} )
4.方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域.
5.运行时常量池(Runtime Constant Pool): 是方法区的一部分, 存放字面量(字符串常量)与符号引用. (注意 从 JDK
1.7 开始, 运行时常量池在堆上). 

数组在内存中的存储

1.数组内容是对象,数组名相当于引用变量。引用变量指向个对象,引用变量存放对象的地址存储在栈区,对象存储在堆区,可以解释为引用指向对象。

 2.当引用变量不指向任何一个对象时,进行计算会报错

        int[] Arrays2 = null;//代表Arrays引用不指向任何一个对象,一下操作会报错
        System.out.print(Arrays2.length);
        System.out.print(Arrays2[2]);

3.数组作为参数打印传递到方法打印数组内容

    public static void print(int[] Arrays){
        for (int i = 0; i < Arrays.length;i++) {
            System.out.print(Arrays[i] + " ");
        }
    }
    public static void main(String[] args) {
        int[] Arrays = {1,2,3,4,5,6};
        printArray(Arrays);
    }

其在内存的操作过程:

 4.引用指向对象

    public static void func1(int[] array){
        array= new int[]{11,22,33,44,55,66};
    }
    public static void func2(int[] array) {
        array[1] = 22;
    }
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6};
        System.out.println(Arrays.toString(array));
        //func1(array);
        func2(array);
        System.out.println(Arrays.toString(array));
    }

func1分析

打印的结果为[1,2,3,4,5,6],[1,2,3,4,5,6]

 func2分析

打印结果为[1,2,3,4,5,6],[1,22,3,4,5,6]

注意:1.一个引用只能保存一个对象的地址

2.引用变量不一定在栈上,是由变量的性质决定的,如果是局部变量就保存在栈上;如实例成员变量就不一定在栈上

null

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

数组作为方法的返回值

方法实现数组元素交换

    //交换数组元素
    public static void exchange(int[] array){
         int tmp = array[0];
         array[0] = array[1];
         array[1] = tmp;
    }
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6};
        System.out.println("交换前:" + array[0] + "," + array[1]);
        exchange(array);
        System.out.println("交换后:" + array[0] + "," + array[1]);
    }

数组作为方法的返回值

写一个方法以数组为形参,返回值为原数组

public static int[] Double2(int[] Array){
        for (int i = 0;i <Array.length;i++){
            Array[i] = 2 * Array[i];
        }
        return Array;
    }
    public static void main(String[] args) {
        //int[] Array = {1,2,3,4,5,6,7};
        int[] Array = new int[]{1,2,3,4,5,6};
        Double2(Array);
        System.out.print(Arrays.toString(Array));

    }

分析

以方法为参数,返回值为新数组

对比下列代码和结果

 

 可以得出,新开辟数组ret只将Array的值复制处理后存储,直接打印Array其值不变。方法结束,存储在栈上的变量会销毁,堆上的数组内容保存,地址传到主函数进行计算。

模拟实现Arrays.toString()

int[] array = {1,2,3,4,5,6};
System.out.print(Arrays.toString(array));
//打印结果为[1,2,3,4,5,6]

思路:1.[1,2,3,4,5,6]为"["和"]"将数字和逗号括起来。2.除了数组的最后一个元素外,其余的元素都是一个数字加",".

实现代码:

public static String my_toString(int[] array){
        String str = "[";
        for (int i = 0;i < array.length;i++){
            if (i == array.length-1){
                str += array[i];
            }else {
                str += array[i] + ",";
            }
        }
        str += "]";
        return str;
    }
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6};
        System.out.print(myToString(array));
    }

在数组中查找元素

遍历查找

 public static int findNumber1(int[] array,int key){
        if (array == null){
            return -1;
        }
        if (array.length == 0){
            return -1;
        }
        int ret = -1;
        for (int i = 0;i < array.length;i++){
            if(array[i] == key){
                ret = i;
            }
        }
        return ret;
    }
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6};
        System.out.println("请输入要查找的数字");
        Scanner scanner = new Scanner(System.in);
        int key = scanner.nextInt();
        System.out.println("找到了,坐标为");
        System.out.print(findNumber1(array, key));
    }

二分查找法(只适用与有序数组)

思路:

 代码:

public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6};
        System.out.println("请输入要查找的数字");
        Scanner scanner = new Scanner(System.in);
        int key = scanner.nextInt();
        System.out.println("找到了,坐标为");
        System.out.print(findNumber2(array, key));

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

可直接通过操作数组工具类Arrays直接实现二分查找

Arrays.binarySearch(int[] array,int key)

数组练习

判断数组是否有序

思路:

遍历数组,数组前一项和后一项大小比较。循环过程中,如遇到无序返回flase,结束循环。

代码:

   public static void isOrderly(int[] array){
        int flag = 1;
        for (int i = 0;i < array.length-1;i++){
            if (array[i] < array[i + 1]){
                ;
            }else {
                flag = -1;
                break;
            }
        }
        if (flag == 1){
            System.out.println("该数组有序");
        }else {
            System.out.println("该数组无序");
        }
    }
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6,7};
        isOrderly(array);
    }

注意:

遍历数组过程的for循环判断条件防止数组越界,如:for (int i = 0;i < array.length;i++)后
            if (array[i] < array[i + 1]);此时为array[array.length - 1] < array[array.length],而array[arry.length]数组越界,正确做法应该将for(int i = 0;i < array.length - 1;i++).

冒泡排序

思路:

冒泡排序是数组数据从左到右比较来交换后确定顺序的方法。

代码:

   public static void Bubble(int[] array){
        //i表示趟数
        for (int i = 0;i < array.length-1;i++){
            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;
            }
        }
    }
    public static void main(String[] args) {
        int[] array = {11,2,5,66,7,1,0};
        for (int x : array){
            System.out.print(x + " ");
        }
        Bubble(array);
        System.out.println("冒泡排序后为");
        for (int x : array){
            System.out.print(x + " ");
        }
    }

注意

1.for循环判断条件可以优化,判断趟数和次数可以优化。

2.通过操作数组工具类Arrays直接实现排序,Arrays.sort(array).

数组排序(奇数后,偶数前)

思路

定义左右下标,通过while循环逐渐向中移动,左下标遇奇数停下,右下标遇到偶数停下;停下后,两数组元素交换。

代码

public static void oddAfter(int[] array){
        int left = 0;
        int right = array.length-1;
        while (left < right){
            while (left < right && array[left] % 2 != 0){
                left++;
            }
            while (left < right && array[right] % 2 == 0){
                right--;
            }
            int tmp = array[left];
            array[left] = array[right];
            array[right] = tmp;
        }
    }
    public static void main(String[] args) {
        int[] array = {1,2,4,6,8,7,9,11,12};
        System.out.print("排序前");
        System.out.println(Arrays.toString(array));
        oddAfter(array);
        System.out.print("排序后");
        System.out.println(Arrays.toString(array));
    }

注意

左右下标移动的循环应该逻辑与(&&)上条件:左下标始终小于右下标

数组逆序

思路

定义左右下标,通过while循环逐渐向中移动,逐个移动交换。

代码

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--;
        }
    }
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6,7};
        System.out.print("逆序前");
        System.out.println(Arrays.toString(array));
        Reverse(array);
        System.out.print("逆序后");
        System.out.println(Arrays.toString(array));
    }

数组拷贝

思路

将遍历源数组将数组元素逐个赋值到目标数组。

代码

public static int[] Copy(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,7};
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(Copy(array)));
    }

注意

1.可利用Arrays数组操作工具类实现

        //利用Arrays数组工具类实现
        int[] ret = Arrays.copyOf(array,array.length);//(源数组,需要拷贝的长度)
        System.out.println(Arrays.toString(ret));

2.可利用Arrays数组操作工具类实现

        //拷贝局部
        int[] ret2 = Arrays.copyOfRange(array,2,7);//(源数组,起始坐标,结束坐标)
        System.out.println(Arrays.toString(ret2));

3.利用array调用克隆产生副本

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

4.拷贝分为深拷贝和浅拷贝

深拷贝:拷贝完成之后,通过一个引用修改目标数组的值时,不会影响源数组的值

浅拷贝:拷贝完成之后,通过一个引用修改目标数组的值时,会影响源数组的值

二维数组

二位数组的定义

第一种定义

int[][] array1 = {{1,2,3},{4,5,6}};
//编译器会默认数组为两行三列,int[][]的括号中不能加数字,否则会报错

第二种定义

int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
//同样在括号中也不能加数字,否则会报错

第三种定义

int[][] array3 = new int[2][3];
//定义一个两行三列的的二位数组

二维数组在内存的存储

二维数组是特殊的一维数组,在内存的存储方式为:

打印其长度:

二维数组的打印

第一种打印方式(遍历)

        int[][] array1 = {{1,2,3},{4,5,6}};
        for (int i = 0;i < array1.length;i++){
            for (int j = 0;j < array1[i].length;j++){
                System.out.print(array1[i][j] + " ");
            }
            System.out.println();
        }

 第二种打印方式(for-each打印)

        //for-each语句打印
        for (int[] ret : array1){
            for (int x : ret){
                System.out.print(x + " ");
            }
            System.out.println();
        }

第三种打印方式(利用Arrays数组操作工具类)

//利用Arrays数组操作工具类打印
System.out.print(Arrays.deepToString(array1));

例子

1、代码:

        int[][] array4 = {{1,2},{3,4,5}};
        for (int i = 0;i < array4.length;i++){
            for (int j = 0;j < array4[i].length;j++){
                System.out.print(array4[i][j] + " ");
            }
            System.out.println();
        }

代码运行结果:

1 2 
3 4 5

注意:数组正常打印不会在补充元素.

2、代码:

        //二维数组省略列打印会报错
        int[][] array5 = new int[2][];
        for (int i = 0;i < array5.length;i++){
            for (int j = 0;j < array5[i].length;j++){
                System.out.print(array5[i][j] + " ");
            }
            System.out.println();
        }

代码运行结果:

 会报错,以为此时二位数组的行为null,此时会报空引用错误:

注意:省略列不会报错,因此可以利用这一特性定义不规则二维数组

代码:

       int[][] array6 = new int[2][];
        array6[0] = new int[3];
        array6[1] = new int[2];

此时定义是不规则二维数组,第一行长度为3,第二行长度为2,不赋初值打印为:

0 0 0 
0 0

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爆裂突破手

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

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

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

打赏作者

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

抵扣说明:

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

余额充值