06 java基础学习笔记 - 数组课时

p1、数组Array
1、java语言中的数组是一种引用数据类型,不属于基本数据类型,数组的父类是Object
2、数组实际上是一个容器,可以同时容纳多个元素,(数组是一类数据的集合)
3、数组当中可以存储基本数据类型的数据,也可以存储引用数据类型的数据
4、因为数组是引用类型,所以数组对象是在堆内存当中存储,(数组存储在堆内存当中)
5、数组的元素如果存储的是java对象的话,实际上存储的是对象的引用(即内存地址),数组中不能直接存储Java对象
6、数组一旦创建,在Java中规定,长度不可变,(数组长度不可变)
7、数组的分类:一维数组、二维数组、多维数组...
8、所有的数组对象都有 length属性,用来获取数组元素的个数,(length属性即数组的长度)
9、Java要求数组中元素的类型统一,比如int类型数组只能存储int类型的元素,Person类型数组只能存储Person类型的数据
10、数组在内存方面,数组中元素的内存地址是连续的,内存地址连续是数组存储元素的特色,数组实际上是一种简单的数据结构
11、所有的数组都是以第一个元素的内存地址作为整个数组对象的内存地址,(数组中首元素的内存地址作为整个数组对象的内存地址)
12、数组中每一个元素都有下标,下标从0开始,以1递增,最后一个元素的下标是 length-1,我们对数组的元素进行存取的时候,都需要使用下标来进行定位
13、数组这种数据结构的优点和缺点是什么?
优点:查询/查找/检索某个下标的元素时效率极高,因为
  第一:每个元素的内存地址在空间存储上是连续的
  第二:每个元素类型相同,所以占用空间大小一样
  第三:知道第一个元素的内存地址,知道每个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标的元素的内存地址,直接通过内存地址定位元素,数组的检索效率是最高的
缺点:
  第一:由于为了保证数组中每个元素的内存地址连续,所以在数组上删除或增加元素的时候,效率较低
  第二:数组不能存储大量数据,为什么?
    因为很难在内存空间上找到一块特别大的连续的内存空间
14、怎么声明/定义一个一维数组?语法格式:
    int[] array1;
    double[] array2;
    boolean[] array3;
    String[] array4;
    Object[] array5;
15、怎么初始化一个一维数组?两种方式:
  静态初始化一维数组:
    int[] array = {100,2100,300,55};
  动态初始化一维数组:
    int[] array = new int[5];  //初始化一个长度是5的int类型数组,元素默认值为0
    String names = new String[6];  //初始化长度是6的String类型数组,元素默认值是null

16、什么时候采用静态初始化方式,什么时候采用动态初始化方式呢?
  当创建数组的时候,能确定数组中存储的具体元素时,采用静态初始化的方式
  当创建数组的时候,不确定数组中要存储哪些数据时,采用动态初始化的方式,预先分配内存空间

示例1:静态初始化 下标 存取 遍历

public class Test{
    //main()方法 入口
    public static void main(String[] args){
        //声明一个int类型的数组,使用静态初始化的方式
        int[] a = {1,100,10,20,55,689};
        
        //所有的数组对象都有length属性
        System.out.println("数组中元素的个数是" + a.length);
        
        //数组中每个元素都有下标,通过下标对元素进行存取
        //取/读
        System.out.println("第一个元素 = " + a[0]);  //1
        System.out.println("最后一个元素 = " + a[5]);  //689
        System.out.println("最后一个元素 = " + a[a.length - 1]);  //689
        
        //存/改
        a[0] = 111;
        a[a.length - 1] = 0;
        
        System.out.println("第一个元素 = " + a[0]);  //111
        System.out.println("最后一个元素 = " + a[a.length - 1]);  //0
        
        //一维数组怎么遍历呢?
        for(int i = 0; i < a.length; i++){
            System.out.println(a[i]);
        }
        //从最后一个元素遍历到第一个元素
        for(int i = a.length - 1; i >= 0; i--){
            System.out.println(a[i]);
        }
        
        //数组下标越界异常:ArrayIndexOutOfBoundsException
        System.out.println(a[6]);  //ArrayIndexOutOfBoundsException 运行时异常
    }
}
View Code

示例2:动态初始化 存取

public class Test{
    //main()方法 入口
    public static void main(String[] args){
        //声明/定义一个int型数组,使用动态初始化的方式
        int[] a = new int[4];  //创建一个长度是4的int型数组,元素默认值是0
        //后期赋值
        a[0] = 1;
        a[1] = 100;
        a[2] = 111;
        a[3] = 222;
        //遍历数组
        for(int i = 0; i < a.length; i++){
            System.out.println(a[i]);
        }
        
        //初始化一个Object类型的数组,采用动态初始化方式
        Object[] objs = new Object[3];  //长度是3的Object类型的数组,元素默认值是null
        for(int i = 0; i <= objs.length-1; i++){
            System.out.println(objs[i]);
        }
        
        //静态初始化的方式
        /*
        Object o1 = new Object();
        Object o2 = new Object();
        Object o3 = new Object();
        Object[] objs2 = {o1,o2,o3};
        */
        Object[] objs2 = {new Object(),new Object(),new Object()};
        for(int i = 0; i <= objs2.length-1; i++){
            System.out.println(objs2[i]);
        }
        
        System.out.println("=============");
        
        //动态初始化的方式
        String[] strs = new String[3];  //长度是3的String类型的数组,元素默认值是null
        for(int i = 0; i <= strs.length-1; i++){
            System.out.println(strs[i]);
        }
        
        //静态初始化的方式
        String[] strs2 = {"abc","def","xyz"};
        for(int i = 0; i <= strs2.length-1; i++){
            System.out.println(strs2[i]);
        }
    }
}
View Code

 

示例3:方法的参数是数组

public class Test{
    public static void main(String[] args){
        //静态初始化一维数组
        int[] a = {1,2,3};
        printArray(a);  //1 2 3
        
        //没有这种语法
        //printArray({1,2,3});
        //如果直接传递一个静态数组的话,语法必须如下:
        printArray(new int[]{1,2,3});  //1 2 3
        
        //动态初始化一维数组
        int[] a2 = new int[4];
        printArray(a2);  //0 0 0 0
        
        printArray(new int[3]);  //0 0 0

        
    }
    
    public static void printArray(int[] array){
        for(int i = 0; i < array.length; i++){
            System.out.println(array[i]);
        }
    }
}
View Code

 


 

p2、main方法的“string[] args”
1、main方法的“string[] args”数组参数有什么用?
  分析一下谁负责调用main方法-JVM,JVM调用main方法的时候,会自动传一个String数组过来,这个数组对象的长度默认是0
2、这个数组什么时候里面会有值呢?
  其实这个数组是留给用户的,用户可以在控制台上输入参数,这个参数自动被转换为“String args”。
  例如这样运行程序: java Test abc def xyz  那么这个时候JVM会自动将字符串abc def xyz 按照空格进行分隔,然后自动放到“String args”数组里面,把字符串 abc def xyz 转换成字符串数组{"abc","def","xyz"}
  所以main方法上的“String[] args”数组主要是用来接收用户输入的参数的

示例1:main方法的“string[] args”数组参数

public class Test{
    //这个方法程序员负责写出来,JVM负责调用,JVM调用的时候一定会传一个String数组过来
    public static void main(String[] args){
        //JVM默认传递过来的这个数组对象的长度是多少?默认长度是0
        System.out.println("JVM传递过来的String数组参数,这个数组的长度是:" + args.length);
        
        //以下代码的表示的含义是:创建了数组对象,但数组中没有任何数据,数组长度是0
        /*
        String[] strs = new String[0];  //动态初始化
        String[] strs = {};  //静态初始化
        printLength(strs);  //0
        */
        
        /**
        这个数组什么时候里面会有值呢?
            其实这个数组是留给用户的,用户可以在控制台上输入参数,这个参数自动被转换为“String args”。
        例如这样运行程序: java Test abc def xyz    那么这个时候JVM会自动将字符串abc def xyz 按照空格进行分隔,然后自动放到“String args”数组里面,把abc def xyz转换成字符串数组{"abc","def","xyz"}
        所以main方法上的“String[] args”数组主要是用来接收用户输入的参数的
        */
        //java Test abc def xyz
        //遍历数组
        for(int i = 0; i < args.length; i++){
            System.out.println(args[i]);
        }  //JVM传递过来的String数组参数,这个数组的长度是:3  abc DEF xyz
    }
    
    public static void printLength(String[] args){
        System.out.println(args.length);
    }
}
View Code

 示例2:案例:模拟一个系统,假设要使用这个系统,必须输入用户名和密码

public class Test{
    //用户名和密码输入到String args数组当中
    public static void main(String[] args){
        if(args.length != 2){
            System.out.println("使用该系统时请输入程序参数,参数包括用户名和密码信息,例如:zhangsan 123");
            return;
        }
        
        //程序执行到此处说明用户提供了用户名和密码,接下来应该判断用户名和密码是否正确
        //取出用户名
        String username = args[0];
        //取出密码
        String password = args[1];
        
        //假设用户名是admin,密码是123
        //判断两个字符串是否相等,使用equals方法
        //if(username.equals("admin") && password.equals("123")){}
        //采用以下编码风格,可以避免空指针异常,即使username和password都是null,也不会出现空指针异常,这是一个编程经验
        if("admin".equals(username) && "123".equals(password)){
            System.out.println("登录成功,欢迎[" + username + "]回来");
            System.out.println("您可以继续使用该系统......");
        }else{
            System.out.println("验证失败,用户名或密码错误!");
        }
    }
}
View Code

 

 


 

p52 数组的声明与创建

1、数组:是相同类型数据的有序集合,其中每个数据称作一个数组元素
  - 数组的元素通过索引/下标访问,索引区间是 [0, length-1]
  - 下标越界则返回异常:ArrayIndexOutOfBoundsException!
  - 获取数组长度的方法是:arrayName.length
  - 定义数组以 [ ] 表示,数组元素以 { } 圈定,以 ,号间隔,拾取数组元素的格式:arrayName[index]

2、使用数组必须先声明数组变量(分配栈空间)

  dataType[ ] arrayName;   //首选
  dataType arrayRefVar[ ];

3、使用 new 操作符来创建数组(分配堆空间)

  dataType[ ] arrayName = new dataType[arraySize];

4、数组的基本特点:
  1)数组元素必须是相同类型,不允许出现混合类型
  2)其长度是确定的,数组一旦被创建,它的大小是不可以改变的
  3)数组中的元素可以是任何数据类型,包括基本类型和引用类型

  - 数组的本质也是对象,数组元素相当于对象的成员变量,因此数组无论保存原始类型还是其它对象类型,数组对象本身是在堆中的
  - 数组变量是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素即被默认初始化


 

p53 内存分析

1、java内存:堆、栈、方法区
  - 堆:存放 new 的对象和数组,可以被所有线程共享,不会存放别的对象引用
  - 栈:存放基本变量类型(会包含这个基本类型的具体数值),引用对象的变量(存放此引用/对象在堆里面的地址)
  - 方法区:可以被所有线程共享,包含了多有的class和static的变量

2、三种初始化
  //静态初始化:创建 + 赋值
  int[ ] a = {1,2,3,5,6,7,8};

  //动态初始化:包含默认初始化
  int[ ] b = new int[10];
  b[0] = 1;
  b[1] = 2;

 

  声明:生成一个整型数组类型的变量array,未初始化未分配空间无值null
  创建:开辟一个堆空间,占10个整型大小的空间 ---->初始化变量array {开辟一个整型栈空间 ---->将该空间分配给变量array ---->使array获取堆空间的引用address,完成初始化} ---->生成10个整型的数组元素变量a[0],a[1]...a[9] ---->初始化元素变量 {给每一个元素变量分配一个整型空间 ---->使元素变量获取初始化值默认为0,初始化完成}
  赋值:修改数组元素的值

 


p55 数组的使用

1)普通 For循环

2)For - each 循环

public class D01{
    public static void main(String[] args){
        int[] arrays = {1,2,4,3,5};
        
        //遍历输出数组
        for(int i = 0; i < arrays.length; i++){
            System.out.println(arrays[i]);
        }
        
        //使用增强for遍历输出
        for(int array : arrays){
            System.out.println(array);
        }
        
        //计算元素之和
        int sum = 0;
        for(int i = 0; i < arrays.length; i++){
            sum += arrays[i];
        }
        System.out.println(sum);
        
        //查找最大元素
        int max = arrays[0];
        for(int i = 1; i < arrays.length; i++){
            if(arrays[i] > max){
                max = arrays[i];
            }
        }
        System.out.println(max);
    }
}
View Code

 

3)数组入参,实际传递的是引用关系/地址值 

4)数组作返回值

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

        //数组入参
        printArray(arrays);                         //传递数组实参
    }

    //遍历输出数组
    public static void printArray(int[] arrays){    //数组形参作接收
        //普通for的用法
        for(int i = 0; i < arrays.length; i++){
            System.out.println(arrays[i]);
        }
        
        //增强for的用法
        for(int array : arrays){
            System.out.println(array);
        }
    }
}
View Code

 

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

        int[] revs = reverse(arrays);            //传递数组参数,获取反转结果
        printArray(revs);                        //传递数组参数,完成打印动作
    }

    //反转数组    数组作返回值
    public static int[] reverse(int[] arrays){
        int[] result = new int[arrays.length];
        //反转操作
        for(int i = 0, j = result.length-1; i < arrays.length; i++, j--){
            result[j] = arrays[i];
        }
        return result;                                //返回值是数组
    }

    //遍历输出数组
    public static void printArray(int[] arrays){    //数组类型的形参
        for(int array : arrays){
            System.out.print(array + " ");
        }
    }
}
View Code

 


 

p56 二维数组

1、二维数组,用两个 [ ][ ] 定义

  int[ ][ ] arr = new int[4][2];  //相当于一个4行2列的数组
  int arr[ ][ ] = new int[4][2];

public class D03{
	public static void main(String[] args){
		int[][] array = {{1,2},{2,3},{3,4},{4,5}};	//定义了一个二维数组
		
		//遍历二维数组
		for(int i = 0; i < array.length; i++){
			for(int j = 0; j < array[i].length; j++){
				System.out.println(array[i][j]);
			}
		}
	}
}

  

2、二维数组的内存分析

int[][] arr = new int[3][2];  //3行2列的数组

 

  生成一个整型数组类型的变量arr ---->开辟一个整型的堆空间(address0),占3个整型大小 ---->初始化数组变量arr {开辟一个整型栈空间 ---->分配该空间给变量arr ---->使arr获取堆地址引用address0,完成初始化}
---->生成3个整型的元素变量arr[0],arr[1],arr[2] ----> * 开辟一个二维的堆空间(address1),占2个整型大小 ---->初始化一维的元素变量arr[0] {分配一维的堆空间给元素变量arr[0] ---->使arr[0]获取二维的堆地址引用address1,完成一维元素变量的初始化}
---->生成2个整型的二维的元素变量a[0][0],a[0][1] ---->初始化二维元素变量 {分配二维的堆空间分别给2个二维元素变量 ---->使二维元素变量获取初始化值0,完成二维元素变量的初始化} *
---->重复 * * 中的流程完成所有一维元素变量与所有二维元素变量的初始化
  赋值:修改二维元素变量的值

 


 

p57 Arrays类 

1、Arrays类中的方法都是 static 修饰的静态方法,在使用的时候可以直接使用类名进行调用,而不用使用对象来调用

2、常用功能
1)输出数组元素:toString()方法,返回数组元素,Arrays.toString(arrayName)
2)对数组排序: sort()方法,    按升序排序,   Arrays.sort(arrayName);
3)填充数组:  fill()方法,    给数组赋值为value,或者给其中一段元素赋值 [from,to), Arrays.fill(arrayName, value); Arrays.fill(arrayName, fromIndex, toIndex, value);
4)比较数组:  equals()方法,  比较数组中元素值是否相等
5)查找数组元素:binarySearch()方法,对排序好的数组进行二分查找法操作

 

import java.util.Arrays;

public class D05{
    public static void main(String[] args){
        int[] a = {3,5,7,8,65,123,8,9,5,4,2};

        //数组排序
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));

        //填充数组
        Arrays.fill(a, 10);
        System.out.println(Arrays.toString(a));

        //给一段元素赋值[from,to)
        Arrays.fill(a, 2, 5, 20);
        System.out.println(Arrays.toString(a));

    }
}
View Code

 

package com.study.part10;

import java.util.Arrays;

public class D04{
    public static void main(String[] args){
        int[] a = {3,54,7,8,65,123,48,9,5,4,2,685,89,213,45,3,5,85};
        System.out.println(a);      //[I@1b6d3586

        //打印数组元素
        System.out.println(Arrays.toString(a));
        printArray(a);
    }

    //重复造轮子
    public static void printArray(int[] arr){
        for(int i = 0; i < arr.length; i++){
            if(i == 0){
                System.out.print("[" + arr[i]);
            }else if(i == arr.length - 1){
                System.out.print(", " + arr[i] + "]");
            }else{
                System.out.print(", " + arr[i]);
            }
        }
    }
//    public static void printArray(int[] arr){
//        for(int i = 0; i < arr.length; i++){
//            if(i == 0){
//                System.out.print("[");
//            }
//            if(i == arr.length - 1){          //以下继续对 i=0的条件作判断,容易被忽视
//                System.out.print(arr[i]+"]");
//            }else{
//                System.out.print(arr[i]+", ");
//            }
//        }
//    }
}
View Code

  

p58 冒泡排序:两层循环,外层冒泡轮数,里层依次比较,江湖中人尽皆知

 

import java.util.Arrays;
public class D06{
    public static void main(String[] args){
        int[] a = {1,0,5,87,63,12,54,3,8,9,14,345,32,385,8,5,64,3,43};
    
        int[] result = sort(a);
        System.out.println(Arrays.toString(result));
        
    }
    
    public static int[] sort(int[] array){
        
        //临时整数
        int temp = 0;
        
        //外层循环,判断要走多少次
        for(int i = array.length-1; i > 0; i--){
            //内层循环,两两比较,交换位置
            for(int j = 0; j < i; j++){
                if(array[j+1] < array[j]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
        }
        return array;
    }
}
View Code

 


 

p59 稀疏数组 

1、当一个数组中大部分元素为0,或者为同一值时,可以使用稀疏数组来保存它
2、稀疏数组的处理方式是:
  - 记录数组一共有几行几列,有多少个有效值
  - 把有效值的 行号、列号及值 记录在一个小规模的数组中,从而缩小程序的规模
  - 稀疏数组行数为 有效值个数n+1,列数为固定值3,固定存放行、列、值三个元素
  - [0]行记录原始数组的 总行数、列数、有效值个数
  - [1]-[n]行记录原始数组中每一个有效值的 行号、列号、值

 //使用二维数组记录棋盘

  

public class D07{
    public static void main(String[] args){
        //使用二维数组记录棋盘
        //创建一个二维数组 11*11 0:没有棋子 1:黑棋 2:白棋
        int[][] array1 = new int[11][11];
        array1[1][2] = 1;
        array1[2][3] = 2;

        //输出原始数组
        for(int[] ints : array1){
            for(int anint : ints){
                System.out.print(anint + "\t");
            }
            System.out.println();
        }


        //转换为稀疏数组保存
        //1、棋盘的行列数已知,遍历二维数组,获取有效值的个数
        int sum = 0;
        for(int i = 0; i < 11; i++){
            for(int j = 0; j < 11; j++){
                if(array1[i][j] != 0){
                    sum++;
                }
            }
        }
        System.out.println("有效值的个数是:" + sum);

        //2、创建稀疏数组 行数为sum+1 列数为固定值3
        int[][] array2 = new int[sum+1][3];
        array2[0][0] = 11;
        array2[0][1] = 11;
        array2[0][2] = sum;

        //3、遍历二维数组,获取有效值的坐标,将有效值放在稀疏数组里
        int count = 0;//有效值序号
        for(int i = 0; i < 11; i++){
            for(int j = 0; j < 11; j++){
                if(array1[i][j] != 0){
                    count++;
                    array2[count][0] = i;
                    array2[count][1] = j;
                    array2[count][2] = array1[i][j];
                }
            }
        }

        //4、打印稀疏数组
        for(int[] ints : array2){
            System.out.println(ints[0] + "\t" + ints[1] + "\t" + ints[2]);
        }


        //还原稀疏数组
        //1、读取稀疏数组,创建新数组
        int[][] array3 = new int[array2[0][0]][array2[0][1]];

        //2、按照稀疏数组的数据还原
        for (int i = 1; i < array2.length; i++) {
           array3[array2[i][0]][array2[i][1]] = array2[i][2];
        }
        //打印还原的数组
        for(int[] ints : array3){
            for(int anint : ints){
                System.out.print(anint + "\t");
            }
            System.out.println();
        }

    }
}
View Code

 

 

 

 

 

//即使再小的帆也能远航2021-10-27

posted @ 2021-10-27 13:23  冬雪雪冬小大寒  阅读(128)  评论(0)    收藏  举报