【Java宝典】——探索数组的奥秘之旅

🌈个人主页: Aileen_0v0
🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法

💫个人格言:"没有罗马,那就自己创造罗马~"

文章目录

Java数组常见报错

①:ArrayIndexOutOfBoundsException(数组索引超出范围)

java 复制代码
    public static void main(String[] args) {

    //java常见报错1:
        boolean[] array2 = new boolean[10];
        System.out.println(array2[10]);
    }

②:NullPointerException(空指针异常)

java 复制代码
    public static void main(String[] args) {
    //java常见报错2:
        int[] array = null;
        System.out.println("数组的长度是: " +array.length);
    }

数组的三种遍历方式

java 复制代码
    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        //Java循环遍历方式1:访问下标形式
        for (int i = 0 ; i < array.length; i++){
            System.out.print(array[i]+" ");
        }
        System.out.println();

        //Java循环遍历方式2:for-each 只是遍历程序,不能通过下标访问
        for (int Aileen : array){
            System.out.print(Aileen + " ");
        }
        System.out.println();

        //Java遍历循环方式3:toString将数组转换为字符串
        String ret= Arrays.toString(array);
        System.out.println(ret);


    }

java 复制代码
public class X {


    public static void main(String[] args) {
        int[] array1 = new int[3];
        array1[0] = 10;
        array1[1] = 20;
        array1[2] = 30;
        System.out.println(array1);

        int[] array2 = new int[]{1,2,3,4,5};
        array2[0] = 100;
        array2[1] = 200;
        System.out.println(array2);

        array1 = array2;
        array1[2] = 300;
        array1[3] = 400;
        array2[4] = 500;
        System.out.println(array1);
        System.out.println(array2);
    }
}

|--------------------------------|
| array1这个引用 指向 array2这个引用所指向的对象 |



|---------------------------------------------|
| array1 和 array2这两个引用 指向 的都是array2这个引用所指向的对象 |

|----------------------------------|
| 0x87这个对象 当没有引用 再指向这个对象,就被JVM回收了. |

|---------------------------------------------------------------|
| int[] array = null; 代表array这个引用 不指向任何对象. 这就意味着0不能调用它的下标,长度等 |


Java中栈和堆的关系

|---------------------------------------------------------------------------------------------------------------------------------------------|
| 栈(Stack)是一种后进先出(LIFO)的数据结构,用于存储方法调用和局部变量。 每当一个方法被调用时,Java虚拟机会为该方法创建一个栈帧,并将其推入栈中。 栈帧包含了方法的参数、局部变量以及方法返回时需要的信息。 当方法执行完毕后,对应的栈帧会被弹出,释放相应的内存空间。 |

|-----------------------------------------------------------------------------------------------------------------|
| 堆(Heap)是用于动态分配对象的内存区域。 在Java中,所有通过new关键字创建的对象都存储在堆中。 堆是一种可扩展的内存区域,它的大小可以根据需要进行调整。 堆中的对象可以被多个线程共享,因此需要进行线程安全的管理。 |

|-------------------------------------------------------------------------------------------------|
| 栈和堆之间的关系是:栈中存储了对堆中对象的引用。 当我们在栈中声明一个对象引用变量时,实际上只是在栈中创建了一个引用,而对象本身仍然存储在堆中。 通过引用变量,我们可以访问和操作堆中的对象。 |


Java中の数据类型

在Java中,数据类型可以分为基本数据类型和引用数据类型。

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 基本数据类型是Java语言中预定义的数据类型,它们包括整数类型(byte、short、int、long)、浮点数类型(float、double)、字符类型(char)和布尔类型(boolean)。 基本数据类型的值直接存储在变量中,它们占用固定的内存空间,并且在内存中分配的位置是连续的。 基本数据类型的赋值是将值直接复制给变量。 |

|-------------------------------------------------------------------------------------------------------------------------------------------------|
| 引用数据类型是由程序员定义的类、接口、数组等类型。 引用数据类型的变量存储的是对象的引用(内存地址),而不是对象本身。 引用数据类型的变量在内存中占用的空间大小是固定的,但它们指向的对象可以动态地分配和释放内存。 引用数据类型的赋值是将对象的引用复制给变量,多个变量可以指向同一个对象。 |

基本数据类型和引用数据类型的区别总结如下:

  1. 存储方式:基本数据类型的值直接存储在变量中,而引用数据类型的变量存储的是对象的引用。
  2. 内存分配:基本数据类型在内存中分配的位置是连续的,而引用数据类型的对象可以动态地分配和释放内存。
  3. 大小固定性:基本数据类型占用固定的内存空间,而引用数据类型的变量在内存中占用的空间大小是固定的。
  4. 赋值方式:基本数据类型的赋值是将值直接复制给变量,而引用数据类型的赋值是将对象的引用复制给变量。

java 复制代码
public class X {


    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        
        fun1(array);
        //打印第一个函数的值
        System.out.println(Arrays.toString(array));
        System.out.println(array);
    }
    public  static void fun1(int[] array22){
        array22 = new int[]{11,22,33,44,55};
    }
}

|------------------------------------------------------------------------------------------|
| 因为引用只是修改了形参(局部变量)的指向,当程序执行完以后,形参和其对应的堆上的地址就会自动销毁. 程序最后的打印结果是1,2,3,4所以说不是传了引用,就一定能够修改实参的值 |


①形参不能改变实参的值的情况(只修改指向)

|------------------------------------------------------------------------------------------------------------------------|
| 因为引用只是修改了形参(局部变量-红色框框内)的指向[这两个引用分别指的是不同的对象.],当程序执行完以后,形参和其对应的堆上的地址(对象)就会自动销毁. 程序最后的打印结果是1,2,3,4所以说不是传了引用,就一定能够修改实参的值 |

|------------------|
| 引用变量当中存地址 引用指向对象 |


②形参可以改变实参的值的情况(修改同一个指向所指向的对象)

java 复制代码
public class X {

    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        fun2(array);
        for (int i = 0 ; i < array.length; i++){
            System.out.print(array[i]+" ");
        }
        System.out.println();
        System.out.println(array);
    }
    
    public  static  void fun2(int[] array11){
        array11[0] = 99;
    }
}

|------------------------------------------------|
| 两个引用(array和array11)同时指向同一个对象,所以通过形参修改,实参也会跟着改变 |

|---------------------------------|
| 从上面的例子也可以看出,形参和实参的名字可以一样也可以不一样. |


java 复制代码
public class X {

    public static void main(String[] args) {
        int x = 10;
        func4(x);
        System.out.println(x);
    }

    public static void func4(int a){
        a = 20;
    }

}

|-------------------------------------|
| 从上面的例子可以看出, 传入基本数据类型,不能通过形参修改实参的数值. |


数组作为返回值进行进行返回

java 复制代码
public class X {

    public static void main(String[] args) {

        int[] ret = func5();
        System.out.println(
                Arrays.toString(ret)
        );
    }

    public static int[] func5(){
        int[] array = {1,2,3,4};
        return array;
    }
}

|-------------------------------------------------------------------------------------------------------------------|
| 首先创建的ret数组先访问函数func5, 其次为创建的array(引用)这个数组开辟一块空间然后指向堆上的地址0x99. 然后将array的值返回出来赋值给ret,并且指向array的对象, 最后打印并返回出array的值. |


数组练习

数组转字符串

java 复制代码
public class X {


    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        //创建方法的对象
        String ret = myToString(arr);
        System.out.println(ret);
    }

    //自己创造的转为字符串的方法
    public static String myToString(int[] arr) {
        String ret = "[";
        for (int i = 0; i < arr.length; i++) {
            ret += arr[i];
            if(i != arr.length-1 ){
            ret += ",";}
        }
        ret += "]";
        return ret;
    }
}
java 复制代码
public class X {

//但是下面这种写法漏了判断array是否为null的情况.
    public static void main(String[] args) {
        int[] array = null;
        String ret = myToString(array);
        System.out.println(array);
    }

    public static String myToString(int[] array){
        //判断数组array为null的情况
        if (array == null){
            return "null";
    }

        String ret = "[";
        for (int i=0;i < array.length;i++){
            ret += array[i];
            if (i != array.length- 1){
                ret += ",";
            }
        }
    ret += "]";
    return ret;
    }
}

数组的copy

java 复制代码
public class X {

    //但是下面这种写法漏了判断array是否为null的情况.
    public static void main(String[] args) {
    //先定义一个数组
    int[] array = {1,2,4,5,8};
    //开始复制:首先复制他原来的数组空间大小
    int[] copy = new int [array.length];
    //通过循环遍历,将原数组的值传入到新创建的数组
    for (int i = 0; i < copy.length; i++) {
        copy[i] = array[i];
    }
    //打印新创建数组的值
        System.out.print(Arrays.toString(copy));
    }
}




✨️ 数组的复制

方法1:使用copyof进行复制

java 复制代码
import java.util.Arrays;

public class x {

    public static void main(String[] args) {
        int[] array ={1,2,3,4};

        //拷贝  array 这个数组 ,长度为 array.length
        int[] copy = Arrays.copyOf(array,array.length);

        System.out.println(Arrays.toString(copy));
    }

}

方法2:使用copyofRange进行部分复制

在JAVA中数组的复制from...to范围一般是左闭右开的,如下所示:

java 复制代码
import java.util.Arrays;

public class x {
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};
        int[] copy = Arrays.copyOfRange(array,1,3);
        System.out.println(Arrays.toString(copy));
    }
}

方法3:使用arraycopy进行复制

所有被native修饰的是由C/C++进行实现的,所有我们不能看到这个方法的源码,但是它的优点是运行速度比较快

java 复制代码
import java.util.Arrays;

public class x {

    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};
        int[] dest = new int[array.length];
        System.arraycopy(array,0,dest,0,array.length);
        System.out.println(Arrays.toString(dest));
    }
   }

arraycopy方法括号里面参数的含义用通俗的话讲就是从array这个书架的0位置开始拿书把它放到dest这个书架的0位置,这些书的长度是array.length。

方法4:使用clone进行复制

java 复制代码
import java.util.Arrays;

public class x {

    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};

        int[] copy = array.clone();

        System.out.println(Arrays.toString(copy));
}
}

数组的扩容

将数组扩大2倍

java 复制代码
public class X {
    public static void main(String[] args) {
        //数组扩容
        int[] array = {1,2,3,4};
        //拷贝array 这个数组 ,新的长度为 array.length * 2
        array = Arrays.copyOf(array,array.length*2);
        //array 指向了 新的数组空间
        System.out.println(Arrays.toString(array));
    }
}

顺序查找数组中的指定元素

法1:循环查找-有序无序都适用

java 复制代码
public class FindElement {
    // 主方法,程序的入口点
    public static void main(String[] args) {
        // 定义并初始化一个整型数组 array
        int[] array = {1,2,5,4,5};
        // 定义并初始化另一个整型数组 myarray
        int[] myarray = {9,8,7,6,5};
        // 调用 search 方法搜索数组 array 中的元素 556,并打印返回值
        System.out.println(search(array, 556));
        // 调用 search2 方法搜索数组 myarray 中的元素 8,并打印返回值
        System.out.println(search2(myarray, 8));
    }

    // 定义一个静态方法 search,用于在整型数组中搜索给定的 key 值
    public static int search(int[] array, int key) {
        // 遍历数组
        for (int i = 0; i < array.length; i++) {
            // 如果找到 key 值,返回当前索引
            if (array[i] == key) {
                return i;
            }
        }
        // 如果没有找到 key 值,返回 -1
        return -1;
    }

    // 定义另一个静态方法 search2,与 search 方法功能相同,用于在整型数组中搜索给定的 key 值
    public static int search2(int[] array, int key) {
        // 遍历数组
        for (int i = 0; i < array.length; i++) {
            // 如果找到 key 值,返回当前索引
            if (array[i] == key) {
                return i;
            }
        }
        // 如果没有找到 key 值,返回 -1
        return -1;
    }
}

法2:二分查找-使用前提:元素必须按照从小到大排序

java 复制代码
import java.util.Arrays; // 导入 Arrays 类,用于数组操作

public class BinarySearch {
    public static void main(String[] args) {
        int[] array = {5, 3, 6, 8, 7}; // 定义并初始化一个整型数组
        Arrays.sort(array); // 使用 Arrays 类的 sort 方法对数组进行排序
        System.out.println(Arrays.toString(array)); // 打印排序后的数组,输出格式为 [3, 5, 6, 7, 8]

        // 调用 binarySearch 方法在数组中搜索键值 111,并打印返回结果
        System.out.println(binarySearch(array, 111));
    }

    // 定义一个静态方法 binarySearch,用于在排序后的数组中进行二分查找
    public static int binarySearch(int[] array, int key) {
        int i = 0; // 初始化左边界索引为 0
        int j = array.length - 1; // 初始化右边界索引为数组长度减 1
        while (i <= j) { // 当左边界索引小于等于右边界索引时,继续循环
            int mid = (i + j) / 2; // 计算中间索引
            if (array[mid] < key) { // 如果中间索引处的值小于键值,说明键值在右半部分
                i = mid + 1; // 将左边界索引移动到中间索引的下一个位置
            } else if (array[mid] == key) { // 如果中间索引处的值等于键值,返回中间索引
                return mid; // 找到键值,返回其索引
            } else { // 如果中间索引处的值大于键值,说明键值在左半部分
                j = mid - 1; // 将右边界索引移动到中间索引的前一个位置
            }
        }
        // 如果没有找到键值,返回 -1
        return -1;
    }
}

除了通过自己写二分查找以外,Java还可以直接调用Arrays库里面的binarySearch直接进行二分查找。

java 复制代码
import java.util.Arrays; // 导入 Arrays 类,用于数组操作

public class BinarySearch {
    public static void main(String[] args) {
        int[] array = {5, 3, 6, 8, 7}; // 定义并初始化一个整型数组
        Arrays.sort(array); // 使用 Arrays 类的 sort 方法对数组进行排序
        System.out.println(Arrays.toString(array)); // 打印排序后的数组,输出格式为 [3, 5, 6, 7, 8]

        // 调用 binarySearch 方法在数组中搜索键值 111,并打印返回结果
        System.out.println(Arrays.binarySearch(array, 7));
    }
}

我们除了通过使用Arrays类里面的sort进行从小到大排序以外,还可以利用reverse进行逆向排序。

java 复制代码
import java.util.Arrays; // 导入Arrays类,用于调用数组相关的工具方法,如toString()

public class ReverseSorted {
    public static void main(String[] args) {
        int[] array = {1,2,3,31,14,5}; // 定义并初始化一个整型数组

        reverse(array); // 调用reverse方法,传入数组作为参数
        System.out.println(Arrays.toString(array)); // 打印数组的字符串表示,查看反转后的结果
    }

    public static void reverse(int[] array){ // 定义一个名为reverse的方法,用于反转数组
        int i = 0; // 初始化索引i为0,指向数组的起始位置
        int j = array.length-1; // 初始化索引j为数组长度减1,指向数组的末尾位置
        while (i < j){ // 当索引i小于索引j时,继续循环
            int temp = array[i]; // 将索引i处的元素暂存到临时变量temp
            array[i] = array[j]; // 将索引j处的元素赋值给索引i处
            array[j] = temp; // 将临时变量temp的值(原索引i处的元素)赋值给索引j处
            i++; // 索引i向后移动一位
            j--; // 索引j向前移动一位
        }
    }
}

通过Arrays中的equals关键字判断数组是否相等

java 复制代码
import java.util.Arrays;

public class Equals {
    public static void main(String[] args) {
        int [] array1 = {1,8,4,5};
        int [] array2 = {1,8,4,5};
        int [] array3 = {1,2,3,3};

        System.out.println(Arrays.equals(array1,array2));
        System.out.println(Arrays.equals(array1,array3));
    }
}

Arrays局部填充用fill关键字

java 复制代码
import java.util.Arrays;

public class PartFill
{
    public static void main(String[] args) {
        int [] array = new int[10];
        Arrays.fill(array,1,3,99);//下标1-2处填充为99
        System.out.println(Arrays.toString(array));
    }
}

冒泡排序

冒泡排序流程图
java 复制代码
import java.util.Arrays;

public class BubbleSort {
    public static void main(String[] args) {
        int[] array = {1,5,3,2,9};
        System.out.println(Arrays.toString(array));
        bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }


    public  static void bubbleSort(int[] array){
        //循环要比较的趟数  ,  5个数据比较4趟
         for(int i = 0 ; i < array.length-1;i++ ){

             //---优化:假设本来就有序,进入下面的循环则变为无序。
             boolean order = false;//假设有序

             //循环控制每趟比较次数 ,  因为每一次比上一次少比较一趟
             for (int j = 0; j < array.length - 1 - i;j++){
                 if (array[j] > array[j+1]) {
                     int temp = array[j];
                     array [j] = array[j+1];
                     array[j+1] = temp;
                     order = true;
                 }
             }

             //如果为false则有序,直接返回
             if (order == false) {
                 return;
             }
         }
    }
}

相关推荐
向阳12187 分钟前
Dubbo负载均衡
java·运维·负载均衡·dubbo
DARLING Zero two♡14 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
Gu Gu Study17 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
芊寻(嵌入式)39 分钟前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
WaaTong40 分钟前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
m0_7430484440 分钟前
初识Java EE和Spring Boot
java·java-ee
AskHarries42 分钟前
Java字节码增强库ByteBuddy
java·后端
荒Huang44 分钟前
Linux挖矿病毒(kswapd0进程使cpu爆满)
linux·运维·服务器
一颗松鼠1 小时前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
有梦想的咸鱼_1 小时前
go实现并发安全hashtable 拉链法
开发语言·golang·哈希算法