jjzjj

二维数组的定义方式有几种

qian-fen 2023-04-19 原文

前言

在前几篇文章中,壹哥给大家介绍了Java里的一维数组,涉及到了数组的创建初始化、数组遍历、拷贝、扩容、排序、查找等核心内容,这些内容都是数组中的重点,希望大家要在这些知识点上多付出点时间和精力。但是我们知道,除了有一维数组之外,还有二维数组和多维数组,这些内容同样很重要。所以今天壹哥就在一维数组的基础上,继续给大家讲解多维数组的内容。

-------------------------------------前戏已做完,精彩即开始------------------------------------

全文大约【3000】字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富案例及配图,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

一. 多维数组

1. 概念

多维数组可以看成是数组的数组。比如二维数组就是一个特殊的一维数组,它的每个元素都是一个一维数组。其他多维数组的概念,大家可以参照二维数组以此类推。

2. 分类

多维数组可以分为:

● 二维数组;

● 三维数组;

● 其他数组;

其实我们在开发时,真正常用的数组也就是一维数组和二维数组,更多维度的数组很少使用。所以接下来在本篇文章中,主要是给大家讲解二维数组相关的内容。

二. 二维数组

1. 概念

二维数组就是一种数组的数组,其本质上还是一个一维数组,只是它的数据元素又是一个一维数组。如果你对这个概念想象不出来,给大家举个栗子,相信吸烟的同学一下子就会明白。

一根烟 = 一个变量

一包烟 = 20根烟 = 一维数组

一条烟 = 10包烟 = 二维数组

也就是说,我们买的”一条烟“,就是一种”二维数组“,明白了吧?

2. 定义

定义二维数组的基本语法如下:

定义方式一:

元素类型[][] 数组名称;

定义方式二:

元素类型 数组名称[][];

在开发时,第一种定义方式更常用一些。这是数组的定义,我们还要对数组进行初始化。二维数组在初始化时,也分为动态初始化和静态初始化两种情况。我们可以把数组的定义和初始化在多条语句中分开完成,也可以直接放在一个语句中完成。

3. 初始化

3.1 动态初始化

二维数组进行动态初始化时,语法格式如下:

元素类型[][] 数组名称 = new 元素类型[二维数组的长度][一维数组的长度];

例如:

int[][] arr = new int[3][4];

在上述示例中,表示我们定义了一个整型的二维数组arr。3表示在二维数组中有3个一维数组,每个一维数组就是一行;4表示每个一维数组中有4个数据元素,这样就形成了二维数组的4列。这样我们就可以把这个二维数组arr看成是一个3行4列的数组或矩阵,访问二维数组中的某个元素时,需要使用arr[row][col]的形式。所以二维数组中,总的元素个数最多有3*4=12个。

以下是动态初始化的案例代码。

public class Demo15 {

	public static void main(String[] args) {
		// 二维数组--动态初始化

		//二维数组在动态初始化时,必须指定二维数组的长度。
        //创建一个包含了3个一维数组的二维数组,每个一维数组的长度是2。
        int[][] arr2 = new int[3][2];

        //给二维数组赋值
        //给二维数组中的第一个一维数组赋值
        arr2[0][0] = 111;
        arr2[0][1] = 222;

        //给二维数组中的第二个一维数组赋值
        arr2[1][0] = 333;
        arr2[1][1] = 444;

        //给二维数组中的第三个一维数组赋值
        arr2[2][0] = 555;
        arr2[2][1] = 666;

        //二维数组取值
        System.out.println( "二维数组中第一个元素里的第一个元素"+arr2[0][0]);
        System.out.println( "二维数组中第一个元素里的第二个元素"+arr2[0][1]);
        System.out.println( "二维数组中第二个元素里的第一个元素"+arr2[1][0]);
        System.out.println( "二维数组中第二个元素里的第二个元素"+arr2[1][1]);

        //获取二维数组的长度
        System.out.println("二维数组的长度"+arr2.length);
        System.out.println("二维数组中第一个一维数组的长度"+arr2[0].length);
        System.out.println("二维数组中第二个一维数组的长度"+arr2[1].length);
        System.out.println("二维数组中第三个一维数组的长度"+arr2[2].length);
	}
	
}

注意:我们在对二维数组进行动态初始化时,必须先指定出二维数组的长度,但一维数组的长度可以后续使用前再单独指定。

3.2 静态初始化

二维数组中,每个一维数组的长度并不要求相同,可以各不相同。二维数组进行静态初始化时,语法格式如下:

元素类型[][] 数组名称 = new 元素类型[][]{{一维数组1,一维数组2,一维数组3....};

例如:

int[][] arr = new int[][]{{2,3},{5,2,1},{10,45,22,54}};

但是这种方式的语法显得有些啰嗦,所以在实际开发时,我们一般是采用简化的静态初始化方式,如下所示:

元素类型[][] 数组名称 =m{{一维数组1,一维数组2,一维数组3....};

例如:

int[][] arr = {{2,3},{5,2,1},{10,45,22,54}};

以下是静态初始化的案例代码。

public class Demo16 {

	public static void main(String[] args) {
		// 二维数组--静态初始化

		//静态初始化一个二维数组。静态初始化时可以很灵活
		int[][] arr = {{11,22,33},{66,88}};
		
        //给二维数组赋值。
		//重新给二维数组中第一个一维数组里的第3个数据元素(即33)赋值,用99替换原来的33.
        arr[0][2] = 99;
        //重新给二维数组中第二个一维数组里的第1个数据元素(即66)赋值,用77替换原来的66.
        arr[1][0] = 77;
        
        //二维数组取值
        System.out.println( "二维数组中第一个一维数组里的第一个元素"+arr[0][0]);
        System.out.println( "二维数组中第一个一维数组里的第二个元素"+arr[0][1]);
        System.out.println( "二维数组中第二个一维数组里的第三个元素"+arr[0][2]);
        System.out.println( "二维数组中第二个一维数组里的第一个元素"+arr[1][0]);
        System.out.println( "二维数组中第二个一维数组里的第二个元素"+arr[1][1]);
        
        //获取二维数组的长度
        System.out.println("二维数组中的长度"+arr.length);
        System.out.println("二维数组中第一个一维数组的长度"+arr[0].length);
        System.out.println("二维数组中第二个一维数组的长度"+arr[1].length);
	}
	
}

以上是定义和初始化二维数组的基本案例,为了加深大家对二维数组的理解,接下来再设计几个代码案例,巩固二维数组的用法。

4. 扩展案例

4.1 动态初始化的变形写法

如果我们在定义二维数组时,没有给定一维数组的长度,那么在使用数组之前,一定要先对一维数组进行初始化。否则,此时如果直接使用一维数组,就会产生空指针异常java.lang.NullPointerException。

public class Demo17 {

	public static void main(String[] args) {
		//动态初始化时未限定一维数组的长度
		int[][] arr = new int[3][];
		
		//如果我们在定义二维数组时,没有给定一维数组的长度,那么在使用数组之前,一定要初始化里面的一维数组。
		//否则,如果直接使用一维数组,就会产生空指针异常java.lang.NullPointerException
		// arr3[0][0] = 100;
		//初始化一维数组
		arr[0] = new int[2];
		arr[1] = new int[1];
		arr[2] = new int[4];

		//给数组赋值
		arr[0][0] = 1;
		arr[0][1] = 2;
		arr[1][0] = 10;
		arr[2][0] = 100;
		arr[2][1] = 200;
		arr[2][2] = 300;
		arr[2][3] = 400;

		// 二维数组取值
		System.out.println("二维数组中的第一个元素中的第一个元素" + arr[0][0]);
		System.out.println("二维数组中的第一个元素中的第二个元素" + arr[0][1]);
		System.out.println("二维数组中的第二个元素中的第一个元素" + arr[1][0]);
	}
	
}

arr[0]=new int[2] 和 arr[1]=new int[1]是在为最高维分配引用空间,也就是限制了最高维能保存数据的最大长度。

4.2 遍历二维数组

因为二维数组中包含若干个一维数组,我们之前遍历一维数组时要使用一个循环,所以我们对二维数组进行遍历时就要使用嵌套的双重循环。当然,for/while/foreach等循环都可以使用。

public class Demo18 {

	public static void main(String[] args) {
		// 二维数组--遍历

		//定义一个二维数组
		int[][] arr = {{11,22,33},{55,66},{77,88,99}};
		
        //使用双重for循环,遍历二维数组
        //第一层循环:遍历二维数组中有几个一维数组
        for (int i = 0; i < arr.length; i++) {
            //arr[i]是一维数组
            //第二层循环:遍历每个一维数组
            for(int j = 0 ; j < arr[i].length ; j++) {
                System.out.println("二维数组中第"+(i+1)+"个一维数组里的元素"+arr[i][j]);
            }
        }
	}
	
}

5. 内存分析

对于一个二维数组来说,比如int[][] array={{10,0,0,20,0},{0,30,40,0,0},{0,0,0,0,0}};这个二维数组的结构如下图所示:

 

array[0]会获取array数组的第1个元素,因为array数组的每个元素都是一个一维数组,因此array[0]指向的数组就是{ 10, 0, 0, 20, 0 },其他的以此类推。

高维数组中的每个数据元素,保存的是低位数组的首地址。所以我们访问array[0]就相当于是在访问二维数组中的第一个一维数组的首地址,这样就可以得到第一个一维数组。

三. 多维数组

理论上,在Java中我们可以定义出任意维度的数组。但高于二维的多维数组,在实际开发中很少使用,大家知道Java中支持这种数据结构即可。如果你感兴趣,可以尝试着自己构造一个三维数组出来,壹哥就不在这里过多讲解啦,可以参考如下:

//动态初始化
int[][][] arr= new int[3][3][2];

//静态初始化
int[][][] arr2= {
    {
    	{1,2,3},{4,5,6},{7,8,9}
    },
    {
    	{1,2},{3,4}
    },
    {
    	{1,2},{3,4,5}
    }
};

 

-----------------------------------------正片已结束,来根事后烟---------------------------------------

四. 结语

至此,壹哥就把二维数组的内容给大家介绍完了,现在你知道如何使用二维数组了吗?二维数组的定义、动态和静态初始化、内存分析都是今天的重点,大家要牢牢掌握哦。

在下一篇文章中,会给大家讲解Java里的可变参数,敬请期待哦。另外如果你独自学习觉得有很多困难,可以加入的学习互助群,我们一起交流学习。

六. 今日作业

1. 第一题

利用二维数组,打印出一个杨辉三角形来。

有关二维数组的定义方式有几种的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  6. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  9. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  10. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

随机推荐