zoukankan      html  css  js  c++  java
  • 夯实Java基础(一)数组

    1、数组的介绍

    数组(Array):就是多个相同类型的数据按照一定的顺序排列的集合。简单理解数组就是一个数据容器。

    数组是编程中最常见的一种数据结构,可用于存储多个数据,每个数组元素存放一个数据,通常我们可以通过数组元素的索引来访问数组元素。包括为数组元素赋值和取出数组元素的值。

    数组的相关概念:数组名,下标(或脚标、索引)(index),元素(element),数组的长度(length)

    image

    数组的基本特性:

    • ①、数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
    • ②、创建数组对象会在内存中开辟一整块连续的空间,而数组的引用是这块连续空间的首地址。
    • ③、数组一旦初始化完成,数组在内存所占用的空间将被固定下来,因此数组的长度不可变。
    • ④、数组可以直接通过下标的方式来调用,下标从0开始。

    2、数组的声明与初始化

    ①、数组的声明

    注:数组在使用之前需要先进行声明并初始化

    2.1、数组的声明

    数组的声明比较简单,和变量基本一样,只是多了个括号[]。数组的声明如下:

    //推荐
    元素的数据类型[] 数组的名称;
    int[] age;
    //不推荐
    元素的数据类型  数组名[];
    int age[];
    

    2.2、数组的初始化

    数组使用之前需要先初始化,什么是数组初始化?就是给数组分配内存空间,并给元素赋值。数组的初始化有两种:静态初始化动态初始化

    ①、静态初始化:定义数组的同时为数组分配内存空间,并赋值。程序员只给定数组元素的初始值,不指定数组长度,由系统决定数组的长度。

    数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...};
    或
    数据类型[] 数组名;
    数组名 = new 数据类型[]{元素1,元素2,元素3...};
    
    简化方式:
    数据类型[] 数组名 = {元素1,元素2,元素3...};//必须在一个语句中完成,不能分开两个语句写
    

    ②、动态初始化:初始化时候程序员只指定数组长度,由系统元素分配初始值(为对应类型的默认值,比如int默认赋值为0)。

    数据类型 [ ]  数组名称 = new 数据类型 [数组长度]
    或
    数据类型  数组名称[ ] = new 数据类型 [数组长度]
    

    ③、简单举例代码如下:

    //声明一个元素为1,2,3的int型数组
    int[] arr=new int[]{1,2,3};
    int[] arr1={1,2,3};
    //声明一个长度为3的数组
    int[] arr2=new int[3];
    

    ④、错误写法:

    //未指定数组长度
    int [] arr1=new int[];
    //数组前面[]不能写长度
    int [5] arr2=new int[5];
    //静态初始化不能写长度
    int [] arr3=new int[3]{1,2,3};
    

    上面的代码写法都是错误的,在编译时会报错。

    3、数组元素的访问与遍历

    ①、访问数组元素以及给数组元素赋值

    数组是存在下标索引的,索引的范围为[0,数组的length-1],通过下标可以获取指定位置的元素,数组下标是从0开始的,也就是说下标0对应的就是数组中第1个元素,可以很方便的对数组中的元素进行存取操作。格式为:数组名[索引]

    //声明一个长度为3的数组
    int[] arr=new int[3];
    //给arr第1个元素赋值1
    arr[0]=1;
    //给arr第2个元素赋值2
    arr[1]=2;
    //输出
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    

    上面的arr数组,我们只能赋值三个元素,也就是下标从0到2,如果你访问 arr[3] ,那么会报数组下标越界异常。

    ②、数组的遍历

    数组遍历: 就是将数组中的每个元素分别获取出来,这就是遍历。遍历也是数组操作中的基石,数组有个 length 属性,是记录数组的长度的,我们可以利用length属性来遍历数组。语句为:数组名.length,返回int类型结果。由次可以推断出,数组的最大索引值为数组名.length-1

    //声明一个元素为1,2,3的int型数组
    int[] arr=new int[]{1,2,3};
    //遍历arr数组
    for (int i = 0; i < arr.length; i++) {
         System.out.println(arr[i]);
    }
    // 使用增强for循环foreach进行遍历
    for (int i : arr) {
          System.out.println(i);
    }
    //使用Arrays.toSting(数组名)进行遍历
    System.out.println(Arrays.toString(arr));
    

    4、数组的内存图

    众所周知,程序是运行在内存中的,而Java程序是运行在Java虚拟机(JVM)上的,那么JVM要运行程序,必须要对内存进行空间的分配和管理。JVM的内存是怎么划分的呢?为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

    image

    image

    数组内存图分析:

    public static void main(String[] args) {
        int[] arr = new int[3];
        int[] arr2 = new int[2];
        System.out.println(arr);
        System.out.println(arr2);
    }
    

    image

    5、数组的使用举例

    ①、将数组元素反转:

    public class ArrayTest {
        public static void main(String[] args) {
            String[] str=new String[]{"AA","BB","CC","DD","EE","FF","GG"};
            System.out.println("反转前:");
            for (int i = 0; i < str.length; i++) {
                System.out.print(str[i]+"\t");
            }
            for(int i=0;i<str.length/2;i++){
                String temp=str[i];
                str[i]=str[str.length-i-1];
                str[str.length-i-1]=temp;
            }
            System.out.println();
            System.out.println("反转后:");
            for (int i = 0; i < str.length; i++) {
                System.out.print(str[i]+"\t");
            }
        }
    }
    

    ②、线性查找:

    public class ArrayTest1 {
        public static void main(String[] args) {
            String[] str=new String[]{"AA","BB","CC","DD","EE","FF","GG"};
            String dest="BB";
            boolean isFlag=true;
            for (int i = 0; i < str.length; i++) {
                if (dest.equals(str[i])){
                    System.out.println("找到了元素,位置在"+(i+1));
                    isFlag=false;
                    break;
                }
            }
            if (isFlag) {
                System.out.println("对不起,没有找到");
            }
        }
    }
    

    ③、提到数组都离不开一个经典的排序——冒泡排序

    public class ArrayTest2 {
        public static void main(String[] args) {
            int[] arr=new int[]{56,12,32,98,78,45,-45,3,55,-16};
            for (int i = 0; i < arr.length; 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;
                    }
                }
            }
            for (int i = 0; i < arr.length; i++) {
                System.out.print(arr[i]+"\t");
            }
        }
    }
    

    数组无论在Java,C,C++,PHP等语言中都有着非常重要的地位,所以学号数组基础非常有必要。

    6、二维数组(理解)

    二维数组:本质上就是数组的元素为一维数组的一个数组。意思就是一个一维数组存储的是另一个数组的地址值,而另一个数组才是真正用来存储值的

    6.1、二维数组的声明

    声明语法格式为:

    //推荐
    元素的数据类型[][] 二维数组的名称;
    
    //不推荐
    元素的数据类型  二维数组名[][];
    //不推荐
    元素的数据类型[]  二维数组名[];
    
    //声明一个二维数组
    int[][] arr;
    

    6.2、二维数组的初始化

    ①、静态初始化,程序员给定元素初始值,由系统决定数组长度。

    //1.先声明,再静态初始化
    元素的数据类型[][] 二维数组名;
    二维数组名 = new 元素的数据类型[][]{
    		{元素1,元素2,元素3 。。。},
    		{第二行的值列表},
    		...
    		{第n行的值列表}
    	};
    //2.声明并同时静态初始化
    元素的数据类型[][] 二维数组名 = new 元素的数据类型[][]{
    		{元素1,元素2,元素3 。。。},
    		{第二行的值列表},
    		...
    		{第n行的值列表}
    	};
    //3.声明并同时静态初始化的简化写法
    元素的数据类型[][] 二维数组名 = {
    		{元素1,元素2,元素3 。。。},
    		{第二行的值列表},
    		...
    		{第n行的值列表}
    	};
    

    如果是静态初始化,右边new 数据类型[][]中不能写数字,因为行数和列数,由{}的元素个数决定

    简单的示例:

    //声明二维数组
    int[][] arr;
    //静态初始化
    arr = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
    //arr = new int[3][3]{{1,2,3},{4,5,6},{7,8,9}};//错误,静态初始化,右边new 数据类型[]中不能指定长度
    
    //声明并同时初始化
    int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
    
    //声明并同时初始化的简化写法
    int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};//声明与初始化必须在一句完成
    
    public static void main(String[] args) {
    	//定义数组
    	int[][] arr = {{1,2,3},{4,5},{6}};
    	
    	System.out.println(arr);
    	System.out.println(arr[0]);
    	System.out.println(arr[1]);
    	System.out.println(arr[2]);
    	
    	System.out.println(arr[0][0]); //1
    	System.out.println(arr[1][0]); //4
    	System.out.println(arr[2][0]); //6
    	
    	System.out.println(arr[0][1]); //2
    	System.out.println(arr[1][1]); //5
    	//越界
    	System.out.println(arr[2][1]); //错误
    }
    

    ②、动态初始化(规则二维表)程序员指定数组的长度,后期再赋值(系统会先给定元素默认初始值)。

    什么是规则二维表?规则二维表的每一行的列数是相同的。

    //(1)确定行数和列数
    元素的数据类型[][] 二维数组名 = new 元素的数据类型[m][n];
    	m:表示这个二维数组有多少个一维数组。或者说一共二维表有几行
    	n:表示每一个一维数组的元素有多少个。或者说每一行共有一个单元格
    //此时创建完数组,行数、列数确定,而且元素也都有默认值
    
    //(2)再为元素赋新值
    二维数组名[行下标][列下标] = 值;
    
    public static void main(String[] args) {
        //定义一个二维数组
        int[][] arr = new int[3][2];
    
        //定义了一个二维数组arr
        //这个二维数组有3个一维数组的元素
        //每一个一维数组有2个元素
        //输出二维数组名称
        System.out.println(arr); //地址值	[[I@175078b
    
        //输出二维数组的第一个元素一维数组的名称
        System.out.println(arr[0]); //地址值	[I@42552c
        System.out.println(arr[1]); //地址值	[I@e5bbd6
        System.out.println(arr[2]); //地址值	[I@8ee016
    
        //输出二维数组的元素
        System.out.println(arr[0][0]); //0
        System.out.println(arr[0][1]); //0
    }
    

    ③、动态初始化(不规则二维表);不规则二维表:每一行的列数可能不一样。

    //(1)先确定总行数
    元素的数据类型[][] 二维数组名 = new 元素的数据类型[总行数][];
    
    //此时只是确定了总行数,每一行里面现在是null
    
    //(2)再确定每一行的列数,创建每一行的一维数组
    二维数组名[行下标] = new 元素的数据类型[该行的总列数];
    
    //此时已经new完的行的元素就有默认值了,没有new的行还是null
    
    //(3)再为元素赋值
    二维数组名[行下标][列下标] = 值;
    
    public static void main(String[] args) {
        //定义数组
        int[][] arr = new int[3][];
    
        System.out.println(arr);	//[[I@175078b
    
        System.out.println(arr[1][0]);//NullPointerException
        System.out.println(arr[0]); //null
        System.out.println(arr[1]); //null
        System.out.println(arr[2]); //null
    
        //动态的为每一个一维数组分配空间
        arr[0] = new int[2];
        arr[1] = new int[3];
        arr[2] = new int[1];
    
        System.out.println(arr[0]); //[I@42552c
        System.out.println(arr[1]); //[I@e5bbd6
        System.out.println(arr[2]); //[I@8ee016
    
        System.out.println(arr[0][0]); //0
        System.out.println(arr[0][1]); //0
        //ArrayIndexOutOfBoundsException
        //System.out.println(arr[0][2]); //错误
    
        arr[1][0] = 100;
        arr[1][2] = 200;
    }
    

    6.3、二维数组的遍历(两个for循环)

    for(int i=0; i<二维数组名.length; i++){
        for(int j=0; j<二维数组名[i].length; j++){
            System.out.print(二维数组名[i][j]);
        }
        System.out.println();
    }
    

    6.4、二维数组的内存图分析

    int[][] arr = {{1},{2,2},{3,3,3},{4,4,4,4},{5,5,5,5,5}};
    

    image

    7、数组的工具类

    在java.util包下提供了一个叫Arrays的工具类,里面提供了很多静态方法来对数组进行操作,而且如下每一个方法都有各种重载形式,以下只列出int[]类型的,其他类型的数组类推:

    • static int binarySearch(int[] a, int key) :要求数组有序,在数组中查找key是否存在,如果存在返回第一次找到的下标,不存在返回负数
    • static int[] copyOf(int[] original, int newLength) :根据original原数组复制一个长度为newLength的新数组,并返回新数组
    • static int[] copyOfRange(int[] original, int from, int to) :复制original原数组的[from,to)构成新数组,并返回新数组
    • static boolean equals(int[] a, int[] a2) :比较两个数组的长度、元素是否完全相同
    • static void fill(int[] a, int val) :用val填充整个a数组
    • static void fill(int[] a, int fromIndex, int toIndex, int val):将a数组[fromIndex,toIndex)部分填充为val
    • static void sort(int[] a) :将a数组按照从小到大进行排序
    • static void sort(int[] a, int fromIndex, int toIndex) :将a数组的[fromIndex, toIndex)部分按照升序排列
    • static String toString(int[] a) :把a数组的元素,拼接为一个字符串,形式为:[元素1,元素2,元素3。。。]

    示例代码:

    import java.util.Arrays;
    import java.util.Random;
    
    public class Test {
        public static void main(String[] args) {
            int[] arr = new int[5];
            //1、打印数组,输出地址值
            System.out.println(arr); // [I@2ac1fdc4
            //2、toString;数组内容转为字符串
            System.out.println("arr数组初始状态:" + Arrays.toString(arr));
            //3、fill
            Arrays.fill(arr, 3);
            System.out.println("arr数组现在状态:" + Arrays.toString(arr));
            //赋值操作
            Random rand = new Random();
            for (int i = 0; i < arr.length; i++) {
                arr[i] = rand.nextInt(100);//赋值为100以内的随机整数
            }
            System.out.println("arr数组现在状态:" + Arrays.toString(arr));
            //4、copyOf
            int[] arr2 = Arrays.copyOf(arr, 10);
            System.out.println("新数组:" + Arrays.toString(arr2));
            //5、equals
            System.out.println("两个数组的比较结果:" + Arrays.equals(arr, arr2));
            //6、sort
            Arrays.sort(arr);
            System.out.println("arr数组现在状态:" + Arrays.toString(arr));
        }
    }
    
  • 相关阅读:
    MySQL分库分表环境下全局ID生成方案
    机器码和字节码
    Java程序编译和运行的过程
    hive大数据倾斜总结
    图解MapReduceMapReduce整体流程图
    Java中的5种同步辅助类
    Tomcat 的三种(bio,nio.apr) 高级 Connector 运行模式
    RocketMQ与Kafka对比(18项差异)评价版
    ENode 2.0
    SecureCrt的操持连接办法
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/11204340.html
Copyright © 2011-2022 走看看