JavaSE之数组总结

目录

一、数组基本用法

1.什么是数组

2.数组的创建

3.数组的使用

二、数组作为方法的参数

1.初识 JVM 内存区域划分

2.一道题:

 3.null

 4.数组作为方法的返回值

三、数组的一些练习

1.数组转字符串

2.数组的拷贝

3.为整型数组分配元素

4.查找整型数组中指定元素(二分查找)

 四、二维数组


一、数组基本用法

1.什么是数组

数组本质上就是让我们能 "批量" 创建相同类型的变量,在 Java , 数组中包含的变量必须是相同类型

2.数组的创建

(1)动态初始化:数据类型[] 数组名称 = new 数据类型 []{ 初始化数据 }; 
new:一个关键字,实例化一个对象,这说明数组是一个对象
如:int[] arr = new int[3];//创建了一个长度为3的数组
       int[] arr = new int[]{1,2,3};//创建了一个长度为3的数组并且初始化为1,2,3
(2)静态初始化:数据类型[] 数组名称 = { 初始化数据 };如:int[] array = {1, 2, 3};
其实数组也可以写成int arr[] = {1, 2, 3}; 这样就和 C 语言更相似了. 但是我们还是更推荐写成 int[] arr 的形式. int和 [] 是一个整体.

3.数组的使用

(1)使用 arr.length 能够获取到数组的长度。“.”这个操作是成员访问操作符

(2)使用 [ ] 按下标取数组元素. 需要注意, 下标从 0 开始计数

(3)使用 [ ] 操作既能读取数据, 也能修改数据

(4)下标访问操作不能超出有效范围 [0, length - 1] , 如果超出有效范围, 会出现下标越界异常java.lang.ArrayIndexOutOfBoundsException(IIEA中的描述)

(5)遍历数组:

import java.util.Arrays;//法三
public class Array{
    public static void main(String[] args){
        int[] arr = {1, 2, 3};
        //法一:for循环
        for(int i = 0; i < arr.length; i++){
             System.out.print(arr[i]+" ");
        }
        //法二:for-each循环(增强for循环)for-each循环拿不到下标,for循环可以拿到下标   for-each循环更多的用于集合中
       //增强for循环的语法定义为:for(ElementType element: arrayName){};
        for(int i : arr){
             System.out.print(arr[i]+" ");
        }
        //法三:借助Java的操作数组的工具类Arrays
        System.out.println(Arrays.toString(arr));//toString:将参数的数组以字符串的形式输出
}

二、数组作为方法的参数

1.初识 JVM 内存区域划分

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

2.一道题:

在这之前,我们先来看看什么是引用?

引用相当于一个 "别名", 也可以理解成一个指针. 创建一个引用只是相当于创建了一个很小的变量, 这个变量保存了一个整数, 这个整数表示内存中的一个地址。我们来看看 int[] arr = new int[]{1, 2, 3} 这样的代码的 内存布局。

 现在我们来看这条题,运行下面的代码,它输出的是什么?

public class Test{
   public static void func1(int[] array){
        array = new int[]{11, 2, 13, 4, 51, 61};
    }
    public static void func2(int[] array){
        array[0] = 899;
    }
    public static void main2(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 6};
        System.out.print(Arrays.toString(array));
        System.out.println();
        func1(array);
        System.out.print(Arrays.toString(array));
        System.out.println();
        func2(array);
        System.out.print(Arrays.toString(array));
    }
}

Tips:

(1)func1(array);此时数组名 array 是一个 "引用" . 当传参的时候, 是按照引用传参,也叫按值传递,只不过这个值是地址而已

(2)所谓的 "引用" 本质上只是存了一个地址. Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实 只是将数组的地址传入到函数形参中. 这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大)

编译运行该代码,输出如下:

1 2 3 4 5 6

1 2 3 4 5 6

899 2 3 4 5 6 

分析如下图:

 3.null

null Java 中表示 " 空引用" , 也就是一个无效的引用, 不能对这个内存进行任何读写操 Java 中并没有约定 null 和 0 号地址的内存有任何关联。
如:int[] arr = null;//这表示arr不指向任何对象,如果此时我们System.out.println(arr[0]);编译器会报一个 NullPointerException(空指针)的错
注意:C语言的空指针NULL是大写,而java是小写

 4.数组作为方法的返回值

比如:我们要写一个方法, 将数组中的每个元素都 * 2(2种方式实现代码)

法一:

public class Test { 
    public static void main(String[] args) { 
         int[] arr = {1, 2, 3}; 
         transform(arr);
         for(int i : arr){
             System.out.print(i + " ");
         } 
   }
   public static void transform(int[] arr) { 
        for (int i = 0; i < arr.length; i++) { 
            arr[i] = arr[i] * 2; 
        } 
   } 
}

这个实现方式也不是不行,只不过破坏了原数组,要不想破坏原数组,就需要在方法内部创建一个新的数组, 并由方法返回出来

法二:

public class Test { 
    public static void main(String[] args) { 
         int[] arr = {1, 2, 3}; 
         transform(arr);
         for(int i : ret){
             System.out.print(i + " ");
         } 
    }
    public static int[] transform(int[] arr) { 
        int[] ret = new int[arr.length]; 
        for (int i = 0; i < arr.length; i++) { 
            ret[i] = arr[i] * 2; 
        }
        return ret; 
    } 
}
这样的话就不会破坏原有数组了 . 另外由于数组是引用类型, 返回的时候只是将这个数组的首地址返回给函数调用者 , 没有拷贝数组内容 , 从而比较高效

三、数组的一些练习

1.数组转字符串

(1)首先,我们先认识一下“包”:

程序开发也不是从零开始, 而是要站在巨人的肩膀上. 像我们很多程序写的过程中不必把所有的细节都自己实现, 已经有大量的标准库(JDK提供好的代码)和海量的第三方库(其他机构组织提供的代码)供我们直接使用. 这些代码就放在一个一个的 "包" 之中,我们可以使用的 "包" , 有成千上万
(2) Java 中提供了 java.util.Arrays , 其中包含了一些操作数组的常用方法
toString(int[] a):将参数的整型数组以字符串的形式输出,返回值为static String
toString(float[] a):将参数的浮点型数组以字符串的形式输出,返回值为static String
......其他数据类型的数组以此类推
import java.util.Arrays
public class Test { 
    public static void main(String[] args) {
       int[] arr = {1,2,3,4,5,6}; 
       String newArr = Arrays.toString(arr); 
       System.out.println(newArr);
    }
}

编译并运行该代码,输出如下:

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

其实,我们也可以模拟实现toString(int[] a):

public class Test{
       public static String myToString(int[] array){
        if(array == null){
            return null;
        }//注意考虑如果传过来是空指针
        String str = "[";
        for(int i = 0; i < array.length; i++){
            str = str + array[i];
            if(i != array.length - 1){
                str = str +",";// 除了最后一个元素之外, 其他元素后面都要加上","
            }
        }
        str = str + "]";
        return str;
    }
    public static void main6(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 6};
        String ret = myToString(array);
        System.out.println(ret);
    }
}

2.数组的拷贝

(1)法一

Arrays类中的方法copy.Of(int[] original,int newlength),返回值为static int[],该方法针对整型数组,可以实现数组的拷贝:

(其他数据类型的数组可以在上面的基础上改一改,如:浮点型数组copy.Of(float[] original,int newlength),返回值为static float[]......)

import java.util.Arrays
public class Test{
    public static void main(String[] args){
        int[] array = {1, 2, 3, 4, 5, 6};
        int[] ret = Arrays.copyOf(array,array.length*2);
  
        System.out.println(Arrays,toString(ret));
    }
}

编译运行该程序,输出如下:

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

其实还可以限制范围的拷贝,这个需要用到方法copyOfRange(int[] original,int from,int to)

① original:源数组

②from:开始拷贝的位置

③to:结束拷贝的位置     

注意范围为[from,to),左闭右开

import java.util.Arrays
public class Test{
    public static void main(String[] args){
        int[] array = {1, 2, 3, 4, 5, 6};
        int[] ret = Arrays.copyOfRange(array,1,3);
  
        System.out.println(Arrays,toString(ret));
    }
}

编译并运行该代码,输出如下:

[2,3] 

(2)法二:

利用for循环将数组中的元素一个一个的拷贝

import java.util.Arrays;
public class Test{
    public static int[] myCopy(int[] array,int newlength){
         int[] copy = new int[newlength];
         for(int i = 0; i < newlength; i++){
             copy[i] = array[i];
         }
         return copy;
    }
    public static void main(String[] args){
        int[] array = {1, 2, 3, 4, 5};
        int newlength = 3;
        int[] ret = myCopy(array,newlength);
        System.out.println(Arrays.toString(ret));
    }
}

(3)法三:

System类里面的方法arraycopy(Object src,int srcPos,Object dest,int destPos,int length);返回值为static void

①src:源数组

②srcPos:从源数组这个位置开始拷贝(下标)

③dest:目标数组

④destPos:拷贝到目标数组的这个位置(下标)

⑤length:拷贝长度

import java.util.Arrays
public class Test{
    public static void main(String[] args){
        int[] array = {1, 2, 3, 4, 5, 6};
        int[] copy = System.arraycopy(array,0,copy,0,array.length);
  
        System.out.println(Arrays,toString(copy));
    }
}

(4)法四:

利用方法clone():

public class Test{
    public static void main(String[] args){
        int[] array = {1, 2, 3, 4, 5, 6};
        int[] copy = array.clone();//产生一个副本

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

这4种方法从代码的实现来看都是浅拷贝。

 浅拷贝:浅拷贝只复制某个对象的引用,而不复制对象本身,新旧对象还是共享同一块内存

深拷贝:深拷贝会创造一个一摸一样的对象,新对象和原对象不共享内存,修改新对象不会改变原对对象。

注意:决定深拷贝还是浅拷贝不是方法的用途,而是代码的实现

3.为整型数组分配元素

我们需要用到Arrays类中的方法fill(int[] a,int val),返回值为static void

                                                  fill(int[] a,int fromIndex,int toIndex,int val),返回值为static void

①a:要分配元素的数组

②fromIndex:开始分配的位置(下标)

③toIndex:结束分配的位置(下标)

④val:要分配的值

注意范围:[fromIndex,toIndex)

public class Test{
    public static void main10(String[] args){
        int[] array = new int[10];
        Arrays.fill(array,2,6,66);//从[2,6)下标填充66
        System.out.println(Arrays.toString(array));
    }
}

4.查找整型数组中指定元素(二分查找)

不同与C语言,java实现二分查找很简单,只需要用到Arrays类中的方法binarySearch(int[] a,int key),返回值为static int

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

编译并运行该代码,输出如下:

-7

为什么是-7呢?这时候我们就要看实现它的源码了

 四、二维数组

1.基本语法

数据类型 [][] 数组名称 = new 数据类型 [ 行数 ][ 列数 ] { 初始化数据 };
2.二维数组的遍历。(二维数组本质上是一维数组)
public class Test{
    public static void main(String[] args) {
        int[][] array = {{1, 2, 3},{4, 5, 6}};
        //法一:
        for(int i = 0; i < array.length; i++){
            for(int j = 0; j < array[i].length; j++){
                System.out.print(array[i][j]+" ");
            }
            System.out.println();
        }
        //法二:
        for(int[] ret : array){
            for(int i:ret){
                System.out.print(i+" ");
            }
            System.out.println();
        }
       //法三:
        System.out.println(Arrays.deepToString(array));//[[1, 2, 3], [4, 5, 6]]
    }
}

3.java中的二维数组不能省略行;如果省略列,会报一个空指针异常的错,但是也有解决办法

 public class Test{  
     public static void main(String[] args){
        int[][] array = new int[2][];//java中不能省略行;不能省略列(否则会报空指针异常)的错,但是可以解决这个报错
        array[0] = new int[3];
        array[1] = new int[2];//不规则的二维数组
        for(int i = 0; i < array.length; i++){
            for(int j = 0; j < array[i].length; j++){
                System.out.print(array[i][j]+" ");
            }
            System.out.println();
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值