JAVA数组

数组

day6

数组概述

  1. 数组Array,是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理
  2. 数组相关的概念:
    • 数组名
    • 元素
    • 角标、下标、索引
    • 数组的长度
  3. 数组的特点:
    1. 数组是有序排列的
    2. 数组属于引用数据类型的变量,数组的元素,既可以是基本数据类型,也可以是引用数据类型
    3. 创建数组对象会在内存中开辟一整块连续的空间,而数组中引用的是这块连续空间的首地址
    4. 数组的长度一旦确定,就不能修改
  4. 数组的分类
    1. 按照维度:一维数组、二维数组、三维数组
    2. 按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)
  • 在这里涉及到地址值的数值,与c语言中的指针不太一样的地方是java中的地址不是内存中的地址,而是jvm虚拟算出来的哈希值,相当于屏蔽了底层真实的地址

一维数组的使用

  1. 一维数组的声明和初始化

    1. 静态初始化: 数组的初始化和数组的元素的赋值操作同时进行
    2. 动态初始化:数组的初始化和数组的元素的赋值操作分开进行
    • 总结:数组一旦初始化完成,其长度就确定了

      
      int num;//声明
      num = 10;//初始化
      int id = 1001;//声明+初始化
      
      int[] ids;//声明
      //1.1 静态初始化: 数组的初始化和数组的元素的赋值操作同时进行
      ids = new int[]{1001,1002,1003,1004};
      //1.2 动态初始化:数组的初始化和数组的元素的赋值操作分开进行
      String[] names = new String[5];
      //总结:数组一旦初始化完成,其长度就确定了
      
  2. 如何调用数组的指定位置的元素

    • 通过角标的方式调用

    • 数组的角标(索引)从0开始,到数组的长度-1结束

      names[0] = "Qiang";
      names[1] = "Ming";
      names[2] = "Hong";
      names[3] = "Long";
      names[4] = "Wang";//charAt(0);需要找字符串也是从0开始
      //		names[5] = "Out"//注意这里会有超出数组的范围的错误
      
  3. 如何获取数组的长度

    • array.length

      System.out.println(names.length);//5
      System.out.println(ids.length);
      
  4. 如何遍历数组

    for(int i = 0;i < names.length;i++) {
        System.out.println(names[i]);
    }
    
  5. 数组元素的默认初始化值

    • 数组元素是整型:0

    • 数组元素是浮点型:0.0

    • 数组元素是char型:0或'\u0000'(不是'0')

    • 数组元素是boolean型:false (0)

    • 数组元素是引用数据类型(String):null

      //5. 数组元素的默认初始化值
      int[] arr = new int[4];
      for(int i = 0;i < arr.length;i++) {
          System.out.println(arr[i]);
      }
      
      System.out.println("------------");
      
      short[] arr1 = new short[4];
      for(int i = 0;i < arr1.length;i++) {
          System.out.println(arr1[i]);
      }
      
      System.out.println("------------");
      
      float[] arr2 = new float[5];
      for(int i = 0;i < arr2.length;i++) {
          System.out.println(arr2[i]);
      }
      
      System.out.println("------------");
      
      char[] arr3 = new char[5];
      for(int i = 0;i < arr3.length;i++) {
          System.out.println("--" + arr3[i] + "--");
      }
      System.out.println(0==arr3[0]);
      System.out.println('0'==arr3[0]);
      
      System.out.println("------------");
      //不能使用静态初始化
      boolean[] arr4 = new boolean[5];
      for(int i = 0;i < arr4.length;i++) {
          System.out.println(arr4[i]);
      }
      
      
      System.out.println("------------");
      //不能使用静态初始化
      String[] arr5 = new String[5];
      for(int i = 0;i < arr5.length;i++) {
          System.out.println(arr5[i]);
      }
      System.out.println(arr5[0] == null);
      System.out.println(arr5[0] == "null");
      
  6. 数组的内存解析

    • 栈(stack):局部变量

    • 堆(heap):new出来的结构:对象、数组

    • 内存简化结构

      image-20211026155814594

      image-20211026164035596

      当arr1不再指向0x12ab时,这里0x12ab这个数组会在不定的时间内给jvm的垃圾回收机制清除。从广义的角度来看数据的结构是这样存放,但具体的内存结构会有所不同

      左边为栈,右边为堆,当程序允许完毕,就会出栈,出栈后,右边堆的元素就会给jvm的内存回收机制清楚

一维数组练习

  • 练习1,判断输出

    public class ArrayDemo1 {
    	public static void main(String[] args) {
    		int[] arr = new int[] { 8, 2, 1, 0, 3 };
    		int[] index = new int[] { 2, 0, 3, 2, 4, 0, 1, 3, 2, 3, 3 };
    		String tel = "";
    		for (int i = 0; i < index.length; i++) {
    			tel += arr[index[i]];
    		}
    		System.out.println("联系方式:" + tel);
    	}
    }
    
  • 练习2

    • 从键盘读入学生成绩,找出最高分,并输出学生成绩等级,成绩>=最高分-10, A,成绩>=最高分-20, B,成绩>=最高分-30, C,其余,D
    import java.util.Scanner;
    
    public class ArrayDemo2 {
        public static void main(String[] args) {
            // 1. 使用Scanner,读取学生个数
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入学生人数:");
    
            // 2. 创建数组,存储学生成绩,动态初始化
            int num = scanner.nextInt();
            int[] scores = new int[num];
    
            // 3. 给数组中的元素赋值
            int max = 0;
            System.out.println("请输入" + num + "个学生成绩");
            for (int i = 0; i < scores.length; i++) {
                scores[i] = scanner.nextInt();
                // 4. 获取数组中元素的最大值:最高分
                if (scores[i] > max)
                    max = scores[i];
    
            }
            System.out.println("最高分是:" + max);
    
            // 5. 根据每个学生成绩与最高分的差值,得到每个学生的等级,并输出等级和成绩
            char level;
            for (int i = 0; i < scores.length; i++) {
                if (scores[i] >= max - 10) {
                    level = 'A';
                } else if (scores[i] >= max - 20) {
                    level = 'B';
                } else if (scores[i] >= max - 30) {
                    level = 'C';
                } else {
                    level = 'D';
                }
                System.out.println("student " + i + " score is " + scores[i] + ",grade is " + level);
            }
        }
    }
    

二维数组的使用

  • java语言里提供支持多维数组的语法
  • 二维数组相当于是一个表格,他有行与列
  1. 理解
    • 对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素二存在。
      其实从数组底层的运行机制来看,其实没有多维数组
  2. 二维数组的使用
    1. 二维数组的声明和初始化

      //一维数组的静态初始化
      int[] arr = new int[] {1,2,3};
      //二维数组的静态初始化
      int[][] arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}};
      int[][] arr4 = new int[][]{{1,2,3},{4,5,9,10},{6,7,8}};
      
      //也是正确的写法
      int[][] arr11 = {{1,2,3},{4,5},{6,7,8}};
      //二维数组的动态初始化1
      String[][] arr2 = new String[3][2];//3行2列
      //二维数组的动态初始化2
      String[][] arr3 = new String[3][];//3行n列
      String[] arr31[] = new String[3][];//3行n列
      String arr32[][] = new String[3][];//3行n列
      
    2. 如何调用数组的指定位置的元素

      System.out.println(arr1[0][1]);//2
      System.out.println(arr2[1][1]);//null,第二行的第二个元素
      //System.out.println(arr3[1][1]);//直接输出是空指针异常报错,因为arr3指向的数组[1]内没有指向的数组
      arr3[1] = new String[4];
      System.out.println(arr3[1][0]);//null
      
    3. 如何获取数组的长度

      System.out.println(arr4.length);//3,因为内存指向的是三个长度的数组
      System.out.println(arr4[0].length);//3
      System.out.println(arr4[1].length);//4,这里指向的是arr4[1]指向的数组长度
      
      
    4. 如何遍历二维数组

      for(int i = 0;i < arr4.length;i++) {
          for(int j = 0;j < arr4[i].length;j++) {
              System.out.print(arr4[i][j] + " ");
          }
          System.out.println();
      }
      
    5. 数组元素的默认初始化值

      • 规定:二维数组分为外层数组的元素,内层数组的元素
      • int[][] arr = new int[4][3];
        • 外层元素:arr[0],arr[1]
        • 内层元素:arr[0][0],arr[1][2]
      • [I@75a1cd57
        • [一维的数组
        • Iint型的
        • @75a1cd57地址在@后面的数
      • [[I@515f550a
        • [[二维数组
        • Iint型
        • @515f550a地址在@后面的数
      int[][] arr = new int[4][3];
      System.out.println(arr[0]);//地址值 [I@75a1cd57 `[`一维的 `I`int型的 `@75a1cd57`在@后面的地址
      System.out.println(arr[0][0]);//0
      // System.out.println(arr);//[[I@515f550a
      
      System.out.println("-------------");
      
      float[][] arr1 = new float[4][3];
      System.out.println(arr1[0]);//地址值 [F@515f550a
      System.out.println(arr1[0][0]);//0.0
      
      System.out.println("-------------");
      
      String[][] arr2 = new String[4][3];
      System.out.println(arr2[0]);//地址值 [Ljava.lang.String;@123a439b
      System.out.println(arr2[0][0]);//null
      
      System.out.println("-------------");
      
      double[][] arr3 = new double[4][];
      System.out.println(arr3[1]);//null
      // System.out.println(arr3[1][0]);//报错-空指针异常
      
      
    6. 二维数组的内存解析

      int[][] arr1 = new int[4][];
      arr1[1] = new int[]{1,2,3};
      arr1[2] = new int[4];
      arr1[2][1] = 30;
      

      image-20211026211042714

数组的练习

数组的复制

  • 在下面代码中,其实就array2=array1这个操作就相当于将array1的地址复制到array2,这里只new了一次,所以在内存中就只有一个数组,所以对array2修改其实就是对array1修改
  • array1和array2地址值相同,都指向了堆空间的唯一的一个数组实体

image-20211029213909316

/*
创建两个int数组,存入8个素数
输出array,将array2=array1,修改array2中的偶数的值让其等于索引值,并打印array1
 */
class cvArrayExr {
    public static void main(String[] args) {
        int[] array1, array2;
        array1 = new int[]{2,3,5,7,11,13,17,19};
        for(int i = 0;i < array1.length;i++){
            System.out.print(array1[i] + "\t");
        }
        System.out.println();
        //这个操作不能称作数组的复制,他只是将array1的值复制给array2
        //这里自始自终就只有一个数组,因为上面就new了一次
        array2 = array1;

        for (int i = 0;i < array2.length;i++){
            if(i % 2 == 0){
                array2[i] = i;
            }
        }
        for(int i = 0;i < array1.length;i++){
            System.out.print(array1[i] + "\t");
        }
    }
}

真正意义上的复制

  • 这里是new了两个数组,真正意义上的复制

image-20211029213105574

/*
数组的复制
 */
class cvArrayExr1 {
    public static void main(String[] args) {
        int[] array1, array2;
        array1 = new int[]{2,3,5,7,11,13,17,19};
        for(int i = 0;i < array1.length;i++){
            System.out.print(array1[i] + "\t");
        }
        System.out.println();
        //这个操作不能称作数组的复制,他只是将array1的值复制给array2
        //这里自始自终就只有一个数组,因为上面就new了一次
        //array1和array2地址值相同,都指向了堆空间的唯一的一个数组实体
        array2 = new int[array1.length];

        for (int i = 0;i < array2.length;i++){
            if(i % 2 == 0){
                array2[i] = i;
            }
            else{
                array2[i] = array1[i] + 1;
            }
        }
        for(int i = 0;i < array1.length;i++){
            System.out.print(array1[i] + "\t");
        }
        System.out.println();
        for(int i = 0;i < array2.length;i++){
            System.out.print(array2[i] + "\t");
        }
    }
}

考察

  1. 写出一维数组初始化的两种方式

    int[] arr = new int[5];//动态初始化
    String[] arr1 = new int[]{'ming','qiang','mi'};//静态初始化
    
    • 数组一旦初始化,其长度就是确定的,且数组长度一旦确定就不可修改
    • 获取数组长度:arr.length
  2. 写出二维数组初始化的两种方式

    int[][] arr2 = new int[4][3];//动态初始化1
    int[][] arr3 = new int[4][3];//动态初始化2
    int[][] arr3 = new int[][]{{1,2,3},{4,5,6},{7,8}};//静态初始化
    
  3. 如何遍历如下的二维数组

    int[] arr = new int[][]{{123},{4,5},{6,7,9}}
    for(int i = 9;i < arr.length;i++){
        for(int j = 0;j < arr[i].length;j++){
            System.out.print(arr[i][j] + "\t");
        }
        System.out.println();
    }
    
  4. 不同类型的一维数组元素的默认初始化值各是多少

    整形: 0
    浮点型: 0.0
    char: 0
    boolean: false
    引用类型: null
    
  5. 一维数组的内存解析

    String[] strs = new String[5];
    strs[2] = "Tom";
    strs = new String[3];
    

    引用类型的遍历,要么是null,要么是地址值(存放于常量池里面)

    image-20211026213544987

关于数组的拓展

day7

数组的排序算法

十大内部排序算法

  • 选择排序

    • 直接选择排序、堆排序
  • 交换排序

    • 冒泡排序、快速排序
  • 插入排序

    • 直接插入排序、折半插入排序、shell排序
  • 归并算法

  • 桶式算法

  • 基数算法

  • 满足确定性的算法也称为:确定性算法。选择人们也关注更广泛的概念,例如考虑葛洪非确定性的算法,如并行算法、概率算法等。另外,人们也关注并不要求终止的计算描述,这种描述有时候被称为过程(procedure)

理解

  1. 衡量排序算法的优劣

    • 时间复杂度、空间复杂度、稳定性
  2. 排序的分类

    • 内部排序与外部排序(需要借助于磁盘)
  3. 不同排序算法的时间复杂度

    image-20211030152232128

    • 从平均时间而言:
    • 快速排序最佳,但再最坏情况下时间性能不如堆排序和归并排序
    • 从算法简单性看:
      • 由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,将其认为是简单算法。
      • 对于shell排序、堆排序、快速排序和归并排序算法,其算法比较复杂,认为是复杂排序
    • 从稳定性看:
      • 直接插入排序、冒泡排序和归并排序是稳定的;
      • 而直接选择排序、快速排序、shell排序和堆排序是不稳定排序
    • 从待排序的记录数n的大小看:
      • n较小时,宜采用简单排序;
      • 而n较大时宜采用改进排序
    • 排序算法的选择
      • 若n较小(n<=50),可采用直接插入或直接选择排序
        • 当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插入,应选直接选择排序为宜
      • 若文件初始状态基本有序(指正序),则一ing有直接插入、冒泡或随机的快速排序为宜
      • 若n较大,则应才有时间复杂度为O(nlogn)的排序方法:快速排序、堆排序或归并排序
  4. 冒泡排序

    int[] arr = new int[]{43,32,76,-98,0,64,33,-21,32,99};
    
    //冒泡排序
    for(int i = 0;i < arr.length - 1;i++){
    
        for(int j = 0;j < arr.length - 1 - i;j++){
    
            if(arr[j] > arr[j + 1]){
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
    
        }
    
    }		
    

Arrays工具类的使用

  • java.uril.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜素哦)的各种方法
    • boolean equals(int[] a,int[] b),判断两个数组是否相等
    • String toString(int[] a),输出数组信息
    • void fill(int[] a,int val),将指定值填充到数组之中
    • void sort(int[] a),对数组进行排序
    • int binarySearch(int[] a,int key),对排序后的数组进行二分法检索指定的值

Eclipse的使用

此部分为day6的部分

关于Eclipse建议的设置

  • 窗口,其他的根据具体需求使用
    • navigator
    • package explorer
    • outline
    • console
  • 设置(window->Proferences
    • 编码设置
      • General->Wrokspace: 最下面找到Text file encoding 将default改为other(UTF-8)
      • 如果不改就会出现乱码问题
    • 字体放大
      • General->Appearance->Colors and Fonts: Basic->Text Fone
      • 然后点击右边的Edit将字体大小改为12-16
  • 设置新建的文件
  • 如果你要将上面描述的保存
    • window->perspective->save perspective as
      • 你可以将默认的给替换掉
  • 如果后续编辑界面乱了,你可以在window->perspective->reset perspective中恢复

Hello实例

  • 新建project,new->java project
  • 添加名字,版本自选,后面默认下一步即可
  • src中新建包package
    • 包里面放源文件,包的概念是将代码变成一个一个的包
    • 格式:com.[域名].[功能]
  • 在包package中创建class
    • 增加名字即可

关于使用

  • 在eclipse中也有快捷键
    • main + alt+/:自动写public static void main(String[] args)
    • syso + alt+/:自动写System.out.println();
  • 运行:右键找到run as->java application
    • 如果你没写main,eclipse就会找不到入口

常见问题

  • 双击eclipse不能正常启动:
    • 启动失败有很多种原因
      1. 查看环境变量是否正确,cmd输入javac.exe或java.exe进行检查
      2. 是否正确的安装了jdk和jre
      3. 安装的jdk版本(32位或64位),必须与eclipse一致
      4. 修改eclipse安装目录下的eclipse.ini配置文件

考察

  1. 使用冒泡排序

    int[] arr = new int[]{34,5,22,-98,6,-76,0,-3}
    for(int i = 0;i < arr.length-1;i++){
        for(int j = 0;j < arr.length - 1 - i;j++){
            if (arr[j] > arr[j + 1]){
                arr[j] += arr[j + 1];
                arr[j + 1] = arr[j] - arr[j + 1];
                arr[j] = arr[j] - arr[j + 1];
            }
        }
    }
    
    • String按照ascii的大小排序
    • 冒泡排序的时间复杂度:O(N^2)
    • 快速排序时间复杂度:O(nlogn)
    • 堆排序、归并排序
  2. 如何反转数组

    int[] arr1 = {-24,-4,4,4,6,23,39,41,95,98};
    for(int i = 0,j = arr1.length - 1;i < j;i++;j--){
        arr[j] += arr[i];
        arr[i] = arr[j] - arr[i];
        arr[j] = arr[j] - arr[i];
    }
    
  3. 复制数组

    //复制地址
    arr2 = arr1;
    //复制内容
    int[] arr2 = new int[arr1.length];
    for(int i = 0;i < arr1.length;i++){
        arr2[i] = arr1[i];
    }
    
  4. 线性查找

    int dest = 23;
    //boolean isFlag = true;
    for(int i = 0;i < arr2.length;i++){
        if(dest == arr2[i]){
            System.out.println("地址值为" + i);
            //isFlag = false;
            break;
        }
    }
    //if (isFlag)
    //    System.out.println("未找到");
    //第二种方法
    if (i == arr2.length)
        System.out.println("未找到");
    
  5. 说出数组的常见异常

    • ArrayIndexOutOfBoundsException: 数组角标越界异常

      • 合理范围:[0, arr.length - 1]
      • 越界:arr[-1], arr[arr.length]
    • NullPointerException: 空指针异常

      int[] arr = null;
      arr[0];
      
posted @ 2021-11-24 15:09  bitrabbit  阅读(60)  评论(0编辑  收藏  举报