【java】数组的定义和使用

数组的基本概念

数组创建

复制代码
   T[] 数组名 = new T[N];

T:数组中存放元素的数据类型

T \[\] :代表数组本身的类型

N:数组的长度(数组能存放多少个元素)
2.

复制代码
           int[] arr1=new int[10];
           double[] array2=new double[10];
           String[] array3=new String[20];

数组两种初始化方式

  1. 动态初始化

    创建数组时,只指定数组长度,不写元素值,元素自动赋默认值

    只规定数组大小,里面元素是对应类型的默认值

    复制代码
            //静态初始化
            int[]  array1=new int[10];
  2. 静态初始化

    创建数组时,直接写出数组里面的元素,编译器自动根据大括号里元素个数算出数组长度

    复制代码
            //动态初始化
            int[]  array2=new int[]{1,2,3,4,5,6,7,8,9};
            double[] array3=new double[]{1.0,2.0,3.0,4.0};
            String[]  array4=new String[]{"tom","Lily","java"};
  3. 数组元素默认值
    当数组只开辟空间,没有手动赋值时,元素自带默认值:
    引用类型(String、类对象等)默认值:null

    复制代码
    String[] words = new String[3]; // 三个元素默认都是null


    重点注意事项

  4. 静态初始化不用手动写长度,编译器自动数{}里元素个数。

  5. {}里的数据类型必须和数组定义的类型一致。

  6. 简写格式{...}不能拆分成两行定义


复制代码
        int[] array5;
        array5=new int[]{1,3,5,3,6,7};  //这样是可行的

        int[] array6;
        array6={1,2,34,54,65};//编译报错,简写只能在定义数组那一行初始化
        
        int[] array7={1,2,3,4,5,6};  //在定数组这一行初始化,是可行的

数组的基本使用

数组中元素访问
  1. 数组在内存是连续空间,下标从 0 开始递增,通过数组下标访问元素
复制代码
           int[] array1=new int[]{10,20,30,40,50};
           System.out.println(array1[0]);
           System.out.println(array1[2]);
           System.out.println(array1[3]);
           // 修噶下标为0 的元素、
           array1[0]=1;
           System.out.println(array1[0]);
  1. 注意事项
    连续内存 → 支持随机访问,直接用下标快速读取任意位置元素。
    下标范围:[0, 数组长度),不能越界。
    数组有N个元素,下标最大是N-1
    下标越界抛出异常
遍历数组
遍历:把数组里所有元素全部访问一遍
  1. 方式 1: for 循环(能拿到数组下标)
    利用 数组名.length 获取数组长度

    复制代码
            int[] array1=new int[]{1,2,3,4,5,6};
            for(int i=0;i<array1.length;i++)
            {
                System.out.printf("%d ",array1[i]);
            }
            System.out.println();
  2. 方式 2:for-each 增强 for 循环(只读取元素,拿不到下标)
    语法: for(元素类型 变量 : 数组名)
    特点: 不用写循环条件,简化遍历
    无法获取当前元素下标

    复制代码
            //for-each 增强for循环
            int[] array2=new int[]{1,3,4,5,6};
            for(int x:array2)
            {
                System.out.printf("%d ",x);
            }
            System.out.println();

数组是引用类型

基本类型变量与引用类型变量的区别

  1. 基本类型变量 :栈里面直接存值本身

    引用类型变量:栈里面存对象在堆中的地址,对象本体放在堆里


  2. 3. 基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值
    引用数据类型创建的变量,⼀般称为对象的引用,其空间中存储的是对象所在空间的地址
    4. 引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始
    地址, 通过该地址,引用变量便可以去操作对象

  3. Java 的引用类似 C 语言指针,但 Java 不能手动对地址做加减运算,安全性更高

复制代码
   public static void func1()
   {
       int[] array1=new int[3];
       array1[0]=10;
       array1[1]=20;
       array1[2]=30;

       int[] array2=new int[]{1,2,3,4,5};
       array2[0]=100;
       array2[1]=200;

       // 变量里存的不是变量本身,而是在堆内存的地址
       array1=array2;  //两个变量共用同一块内存地址

       array1[2]=300;
       array1[3]=400;
       array1[4]=500;

       for(int i=0;i<array2.length;i++)
       {
           System.out.println(array2[i]);
       }
   }
  1. 关键总结
    Java 数组属于引用类型:
    a)变量里存的不是数组本身,而是数组在堆内存的地址;
    b)array1 = array2 只是拷贝地址,两个变量共用同一个数组对象;
    c)无论用哪个引用修改数组内部元素,都会互相影响

NULL

  1. 什么是 null
    a)null 在 Java 中表示空引用 ,是一个不指向任何对象的引用
    b)Java 里引用类型(数组、类、String 等)的变量,可以赋值为 null,代表这个引用 变量没有指向堆里的任何对象
    c)基本数据类型(int / double / boolean)不能赋值为 null,只有引用类型可以

  2. 和 C 语言 NULL 的区别
    相似点 :都代表无效的内存位置,不能读写
    重要区别 :Java 的 null 不等价于内存 0 号地址,只是 Java 层面的 "空标记",和 C 语言空指针底层含义不一样

  3. 空指针什么时候会出现
    只要用一个值为null的引用,去调用属性 / 方法 / 访问数组元素,就会触发 NPE

  4. 总结

    复制代码
            int[] arr1=null;
            int[] arr2=new int[]{1,2,3,4,5,6,7};
            System.out.println(arr1[0]);
    //        System.out.println(arr2[0]);

    a)arr1:只是一个空引用,不存在数组,arr10 空指针
    b)arr2:数组对象存在,可以访问元素,arr20 是 1


数组的应用场景

保存数据

  1. 知识点
    a)数组:用来批量保存多个同类型数据
    b)数组下标从 0 开始,最大下标 = 数组长度 -1
    c)数组名.length:获取数组元素个数
    d)for 循环:适合知道循环次数的遍历场景
复制代码
           int[] array={1,2,3};
           for(int i=0;i<array.length;i++)
           {
               System.out.println(array[i]+" ");
           }

参数传递(值传递)

Java 中只有值传递,没有引用传递

基本类型和引用类型,本质都是拷贝一份 "值" 传给方法

基本数据类型作为参数
复制代码
   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);
   }


2. 斐波那契数列

复制代码
       //方法:返回int[]数组,存放婓波那些前n项
       public static int[]fib(int n)
       {
           if(n<=0)
           {
               return null;
           }

           int[] array=new int[n];
           array[0]=array[1]=1;
           //当前项等于前两项之和
           for(int i=2;i<n;i++)
           {
               array[i]=array[i-1]+array[i-2];
           }
           return array;
       }


Arrays 工具类 和 数组知识点

Java 数组常用操作,包含Arrays工具类、数组拷贝、查找、排序、逆序

数组转字符串 Arrays.toString()

  1. 作用:快速把数组转为字符串格式打印,不用自己循环拼接
复制代码
           int[] arr=new int[]{1,2,3,4,5,6,7};
           String newArr= Arrays.toString(arr);
           System.out.println(newArr);
  1. 注意:直接打印数组对象名,输出的是地址哈希值,不是数组内容

数组拷贝

  1. 直接赋值(浅引用,不是拷贝)

    复制代码
            int[] arr=new int[]{1,2,3,4,5};
            int[] newArr=arr;  //newArr 和 arr 指向的是同一块数组
            newArr[0]=100;
            System.out.println(Arrays.toString(arr));  // newArr 的修改 会导致 arr 也被修改
  2. Arrays.copyOf / Arrays.copyOfRange(真正拷贝,生成新数组)

    复制代码
            //Arrays.copyOf/Arrays.copyOfRange 是拷贝
            int[] arr=new int[]{1,2,3,4,5,6,7};
    
            //copyOf(原数组,新数组长度)
            int[] newArr=Arrays.copyOf(arr,arr.length);
            arr[0]=10;
            System.out.println("arr: "+Arrays.toString(arr));
            System.out.println("newArr: "+Arrays.toString(newArr));  //不受arr 的影响
    
            //copyOfRange (原数组,起始下标,结束下标)  //左闭,右开
            int[] newArr2=Arrays.copyOfRange(arr,1,5);
            System.out.println("newArr2: "+Arrays.toString(newArr2));
  3. 区分 :
    基本类型数组拷贝没问题;
    引用类型数组拷贝是浅拷贝

  4. 自己手写数组拷贝

    复制代码
        public static int[] copyOf(int[] arr)
        {
            int[] ret=new int[arr.length];
            for(int i=0;i<arr.length;i++)
            {
                ret[i]=arr[i];
            }
            return ret;
        }

    功能:

    手写版数组拷贝,深拷贝(对于 int 基本类型数组),复制完成后,修改原数组arr不会影响新数组ret,修改ret也不会影响arr

顺序查找(线性查找)

  1. 从头到尾逐个比对元素,找到返回下标,找不到返回 -1

复制代码
       //顺序查找,找到返回下标,找不到返回-1
       public static int find(int[] arr,int data)
       {
           for(int i=0;i<arr.length;i++)
           {
               if(arr[i]==data)
               {
                   return i;
               }
           }
           return -1;
       }
  1. 缺点:
    数据量大的时候效率低
    不需要数组有序

二分查找(折半查找)

  1. 思路:取中间元素,比较目标值,缩小查找区间

复制代码
       //二分查找
       public static int  binarySearch(int[] arr,int toFind)
       {
           int left=0;
           int right=arr.length-1;
           while(left<=right)
           {
               int mid=(left+right+1)/2;
               if(toFind<arr[mid])
               {
                   right=mid-1;
               }
               else if (toFind>arr[mid])
               {
                   left=mid+1;
               }
               else
               {
                   return mid;// 找到
               }
           }

           return -1; //没找到返回 -1
       }
  1. 优点:数据越多,效率优势越大

  2. Java 自带Arrays.binarySearch()方法

    复制代码
            int ret2=Arrays.binarySearch(arr,6);
            System.out.println(ret2);

数组排序:冒泡排序

  1. 升序思路:相邻两个元素比较,前大后小就交换;

    每一轮把最大元素 "冒泡" 到末尾

  2. 降序思路:相邻两个元素比较,前小后大就交换;
    每一轮把最小元素 "冒泡" 到末尾

复制代码
       public static void bubbleSort(int[] arr)
       {
           //外层控制轮数
           //内层比较,每轮末尾 i 个已经排好的不用比较
           for(int i=0;i<arr.length;i++)
           {
               for(int j=0;j<arr.length-i-1;j++)
               {
                   //如果前面的比后面的数据大,就交换
                   if(arr[j]>arr[j+1])  //要改成降序的话,把大于改成小于就行
                   {
                       int temp=arr[j];
                       arr[j]=arr[j+1];
                       arr[j+1]=temp;
                   }
               }
           }
       }
  1. Java 内置:Arrays.sort(arr),底层是优化后的排序,性能远高于手写冒泡

数组逆序

  1. 思路:双指针,left 指向头部,right 指向尾部,交换两个元素,left++,right--,直到 left >= right

复制代码
       // 数组逆序 双指针  先交换元素,在变化指针
       public static void reverse(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--;
           }
       }


二维数组

普通二维数组

  1. 二维数组本质:是一维数组,数组里每一个元素又是一个一维数组

  2. 语法格式

    复制代码
    数据类型[][] 数组名称 = new 数据类型 [行数][列数] {初始化数据};

    特点:行不能省略,列可以省略

复制代码
       // 二维数组
       public static void main(String[] args) {

           int[][] a={
                   {1,2,3,4},
                   {5,6,7,8},
                   {9,10,11,12}
           };
           //a.length 是行数
           for(int row=0;row<a.length;row++)
           {
               //a[row].length 是列数
               for(int col=0;col<a[row].length;col++)
               {
                   System.out.printf("%d\t",a[row][col]);
               }
               //换行
               System.out.println();
           }
       }

a.length:二维数组行数

arow.length:第row行一维数组的长度(当前行的列数)

不规则二维数组

  1. 定义时只确定行数,每一行的列数不固定,各行长度不一样
复制代码
   int[][] array = new int[2][]; // 定义2行,列暂时不指定
   array[0] = new int[3]; // 第0行,3个元素(3列)
   array[1] = new int[5]; // 第1行,5个元素(5列)
  1. 第 0 行:3 列
    第 1 行:5 列
    内存理解:外层数组保存两个一维数组的地址,两个一维数组长度不同
相关推荐
shuoshuohaohao3 小时前
MyBatis 小知识点
java·spring·mybatis
海上小飞龙4 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
谢亮_vipxieliang4 小时前
泛型擦除、通配符与 PECS 一次讲透
java·面试
八解毒剂5 小时前
【计组】中央处理器CPU
java·开发语言·计算机组成原理
打工仔折腾 AI5 小时前
工业场景下时序库与实时计算一体化架构选型实践对比
java·开发语言·后端·python·性能优化·架构·ai agent 实战
ZealSinger6 小时前
Java虚拟线程上线后瓶颈转移到哪看三层
java·开发语言·firefox
2601_961133286 小时前
盘立方软件指标文华期货公式下载
java
蜗牛互联网6 小时前
长任务多Agent共享文件系统的Manifest交接模式
java·人工智能·后端
Sirens.6 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
sunshine22 girl7 小时前
Java学习五 面向对象高级5 内部类1
java·学习