夯实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));
    }
}
原文地址:https://www.cnblogs.com/tanghaorong/p/11204340.html