JavaSE——中——数组

目录

三.数组  

数组的基本概念  

数组的定义  

数组的使用  

数组的遍历及排序  

数组是引用数据类型  

初始JVM的内存分布  

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

认识null  

数组的应用场景  

数组练习  

  数组转字符串  

  数组拷贝 

  这里给了另一种方法(也可以当成扩容)  

  JVM其实就是C/C++写的,所以究其底层,我们还可以这么做:(支持部分拷贝)  

查找数组中指定元素  

二维数组  


三.数组  

数组中存放的元素其数据类型相同。数组的空间是连在一起的,每个空间都有自己的编号。编号又叫下标或索引,起始编号为0。

数组的基本概念  

数组的定义  

数组是引用数据类型,所以创建时得加new,可以简写

public class HelloWorld {
    public static void main(String[] args) {
        int[] arr0 = {1,2,3,4};
        int[] arr1 = new int[]{1,2,3,4,5};   //静态初始化
        int[] arr2 = new int[10];      //只是分配了内存,没有初始化,默认是0
//      int[] arr3 = new int[2]{1,2};  //这种也是错误的,在等号后面,要么中括号里有数字,要么花括号里有数字
        //一般通过new关键字 实例化对象。Java中的数组其实就是一个对象,Java中一切皆对象
        double[] score = new double[5];
        String[] name = new String[]{"I","love","study","!"};
    }
}

数组的使用  

JavaSE——中——数组_第1张图片

可以通过System.out.println(arr0.length);来实现求数组长度

数组的遍历及排序  

import java.util.Arrays;

public class HelloWorld {
    public static void main(String[] args) {
        int[] arr0 = {1,21,3,14};
        for (int i = 0; i < arr0.length; i++)
            System.out.print(arr0[i]);
        System.out.println();

        for (int x : arr0)
            System.out.print(x);           //依次输出1 21 3 14
        System.out.println();

        String str = Arrays.toString(arr0);
        System.out.println(str);  //以字符串形式输出[1, 21, 3, 14]
        Arrays.sort(arr0);
        System.out.println(str);  //以字符串形式输出[1, 21, 3, 14]
    }
}

数组是引用数据类型  

初始JVM的内存分布  

JVM对所使用的内存按功能的不同进行了划分

JavaSE——中——数组_第2张图片JavaSE——中——数组_第3张图片

 关于这段代码,输出arr0的地址

public class HelloWorld {
    public static void main(String[] args) {
        int[] arr0 = {1,21,3,14};
        System.out.println(arr0);
    }
}

输出结果为:[I@1b6d3586

[ 代表这是一个数组,I 表示数组类型是整形,@作为分割,后面是16进制的数字,这个16进制数字暂且可以看成数组

  • 程序计数器(Program Counter Register):只是一个很小的空间,保存下一条执行的指令的地址
  • Java虚拟机栈(VM Stack):与方法调用相关的一些信息,每个方法在执行时,都会先创建一个栈帧,栈帧中包含有:局部变量表、操作数栈、动态链接、返回地址以及其他的一些信息,保存的都是与方法执行时相关的一些信息。比如:局部变量。当方法运行结束后,栈帧就被销毁了,即栈帧中保存的数据也被销毁了。
  • 本地方法栈(Native Method Stack):本地方法栈与虚拟机栈的作用类似,只不过保存的内容是Native方法的局部变量。在有些版本(HotSpot)的JVM实现中,本地方法栈和虚拟机栈是一起的。
  • 堆(Heap):JVM管理的最大内存区域。使用new创建的对象都是在堆上保存的,堆是随着程序开始运行时而创建,随着程序的退出而销毁的,堆中的数据只要还有在使用,就不会被销毁。
  • 方法区(Method Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法编译出来的字节码就是保存在这个区域中的。方法区就是方法区,没有所谓的静态区

方法区和堆属于线程共享的区域,其他的是线程隔离的区域。

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

JavaSE——中——数组_第4张图片

 引用变量,其实就是一个变量来存地址。(没有首地址的概念)。空间中存的是对象所在的空间

 局部变量的内存在栈上开辟的,对象在堆上。                                                                               局部变量就是在方法内部定义的变量,不要和引用变量混到一起。这是两个不一样的变量

JavaSE——中——数组_第5张图片

public class HelloWorld {
    public static void main(String[] args) {
        int[] array = null;
        System.out.println(array[0]);
    }
}

在运行此代码时,出现空指针报错xception in thread "main" java.lang.NullPointerException,简称NPE(空指针异常)。

原因只有一个:使用了值为null的引用。

import java.util.Arrays;

public class HelloWorld {
    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        array[0]=99;
        int[] array1 = array;
        array1[0]=100;
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(array1));
    }
}

两个System的输出都是[100, 2, 3, 4]

JavaSE——中——数组_第6张图片

另外:

JavaSE——中——数组_第7张图片

认识null  

Java中没有约定null和0号地址的内存有任何关联

数组的应用场景  

JavaSE——中——数组_第8张图片

总结:当数组作为参数进行传递时,其实还是按值传递,不过此时的值是一个地址。                    那么就会出现两种情况:                                                                                                                。1.形参修改指向:array new int[ ];只会影响形参的指向                                                                      2.形参修改实参所指向对象的值:array[ 0 ] =9;此时才会影响到实参

数组练习  

  数组转字符串  

public class HelloWorld {
    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        int[] array1 = null;
        String ans = myToString(array);
        String ans1 = myToString(array1);
        System.out.println(ans);    //输出[1,2,3,4]
        System.out.println(ans1);   //输出null
    }
    public static String myToString(int[] array) {
        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;
    }
}

  数组拷贝 

public class HelloWorld {
    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        int[] array1 = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            array1[i] = array[i];
        }
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(array1));
    }
}

  这里给了另一种方法(也可以当成扩容)  

public class HelloWorld {
    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        //第一个参数是被copy的数组,第二个参数是新数组的长度
        int[] array1 = Arrays.copyOf(array,array.length);
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(array1));
    }
}

  JVM其实就是C/C++写的,所以究其底层,我们还可以这么做:(支持部分拷贝)  

public static native void arraycopy(

                Object src, int src srcPos, Object dest, int destPos, int length        )

native表示是本地方法

public class HelloWorld {
    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        int[] array1 = new int[array.length*2];
//被拷贝的数组,从被拷贝的数组的哪个位置开始,拷贝到哪个数组,存放的第一个数的位置
        System.arraycopy(array,0,array1,1,array.length-1);
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(array1));
    }
}

输出为:       [1, 2, 3, 4]
                   [0, 1, 2, 3, 4, 0, 0, 0]

注意越界问题,若越界则会出现ArrayIndexOutOfBoundsExcepyion数组越界问题

另外的另外,还有一种比较奇特的方法(克隆clone:产生一个副本)也能实现同样的效果

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

另外的另外的另外的另外:拷贝分为引用拷贝、浅拷贝、深拷贝

JavaSE——中——数组_第9张图片JavaSE——中——数组_第10张图片

深浅拷贝和实现的方式,和代码写的有关,和是不是for循环无关。                                               n具体内容可以查看引用拷贝、深浅拷贝(侵权必删)

查找数组中指定元素  

顺序查找方便实现,但是查找的效率过于慢,故我们可以尝试一下二分查找(折半查找):

二分查找的前提是有序数组

public class a {
    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 (key1;
            else return mid;
        }
        return -1;
    }

    public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6,7,8,9,10};
        Arrays.sort(array);//从小到大排序
        System.out.println(binarySearch(array,8));//自己写的
        System.out.println(Arrays.binarySearch(array,8));
//自带的,没找到返回负数,不一定是-1
    }
}

关于获取时间

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        long end = System.currentTimeMillis();
        System.out.println(end-start);//答案为0;差值为毫秒
    }

二维数组  

class a {
    public static void main(String[] args) {
        int[][] array1 = {{1,2,3},{4,5,6}};
        int[][] array2 = new int[2][3];
        int[][] array3 = new int[][]{{1,2,3},{4,5,6}};
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(array1[i][j]);
            }
            System.out.println();
        }//遍历
        System.out.println("========");
        System.out.println(Arrays.toString(array3[0]));//[1,2,3]遍历
        System.out.println(Arrays.toString(array3[1]));//[4,5,6]遍历
        System.out.println("==========");
        for (int[] ret : array1) {
            for (int x : ret) {
                System.out.print(x+" ");
            }
        }//遍历二维数组
        System.out.println("=========");
        System.out.println(Arrays.deepToString(array1));//[[1,2,3],[]4,5,6]
    }
}

JavaSE——中——数组_第11张图片JavaSE——中——数组_第12张图片

引用不一定在栈上,在不在栈上只和是否是局部变量有关。

你可能感兴趣的:(Java,java)