数组与大数
大数
数组
声明数组
访问数组元素
for each循环
数组拷贝
命令行参数
数组排序
多维数组
数组与大数
好了,上次我们主要讲述了Java
中的输入与输出及流程控制等相关操作,这次我们主要介绍两个与数有关的内容:「大数与数组」。话不多说,开始正题叭!
大数
记得我们之前在说到变量与运算时提到,在Java
中一共有8种基本的数据类型。
复习一下,分别是:byte、short、int、long、double、float、char、boolean。
今天我们要说的「大数」就和这八种数据类型中的整数与浮点数有关。
相信很多同学会问,int、long、double、float都有着自己的取值范围,但如果某一天我们要处理的范围远比这些范围要大,此时应该怎么办呢?
如果真的发生这种情况,那么我们就可以使用「大数」来表示了
来看一下定义;
❝大数,有交易员术语,指汇率的头几位数字;数学用语,指两个数中较大的数;命运注定的寿限,如大数已尽等意思。还是印度佛教的数量单位。
❞
但这很明显不是我们Java
中的意思。
值得一提的是大数主要有两个类:BigInteger
和BigDecimal
,并且他们主要保存在Java.math
包中。
前者主要负责任意精度的整数运算,后者主要负责任意精度的浮点数运算。
那么如何将普通的数转成大数呢?就像float类型转换成double类型,不同的是前者需要调用方法实现,后者一般自动转换。
int a=100;
//使用大数来表示a
BigInteger big=BigInteger.valueof(a);
//对于更大的数,可以使用一个带字符串参数的构造器;
BigInteger big2=new BigInteger("41654612123334465468479465465465");
以上展示了一般的int和比较大的数怎么用大数来表示的方式,总的来说,至少有两种方法转换成大数:
通过``valueof(number)`来将数转换成大数 通过new操作符来构造一个String对象(这种情况只适用于数特别大的时候)。
此外还有一些常量:BigInteger.ZERO
、BigInteger.ONE
、BigInteger.TEN
、BigInteger.TWO
等
说到这里也许有小伙伴会问了,既然大数也可以表示数,那么它能用算数运算符计算叭。
很不幸,目前大数不能够用人们所熟悉的算数运算符来计算处理大数,主要使用大数类的两个方法;
分别是add
和multiply
方法
来看个综合的栗子;
int a=10; int b=5;
BigInteger c=BigInteger.valueof(a).add(BigInteger.valueof(b))
//c=a+b
BigInteger d=c.multiply(BigInteger.valueof(b).add(BigInteger.valueof(2)))
//d=c*(b+2)
当然肯定还有其他的方式,比如divide
我这么说肯定有点晕,来看看API
(这里主要介绍BigInteger
类的)
其他的方法参考BigDecimal API
。
好了以上就是大数的有关内容,内容不多,下面我们进入数组的学习!
数组
我们来看看数组的官方解释叭!
❝数组:「数组」(Array)是有序的元素序列,若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。
❞
简单点来说就是:数组内存储的是相同类型的序列。
下面我们来仔细看看。
声明数组
简答来说,数组是一种数据结构,用来存储同一类型值的集合。通过一个整型下标(index,或称索引)可以访问数组中的每个值。
同时在声明数组变量时需要指出数组类型(数据元素类型紧跟[])和数组变量的名字。
一共有两种声明方式:
int[] a int a[]
这两种声明方式都是正确的,看个人喜好,但更加建议采用第一种,因为它将类型与变量名很好地分开了。
不过值得注意的是这种声明方式只是声明了数组变量,并没有初始化,也就是没有赋予它一个「初始的值」。
应当使用「new操作符」创建数组(即数组的初始化)
int []a=new int[100];
其实数组有两种方式初始化:「动态初始化和静态初始化」
动态初始化:在初始化之时只指示数组的大小,不指定具体所含有的元素。如: int[]a=new int[5]
静态初始化:在初始化的时候直接列出数组内所含有的有穷元素个数。如: int[]a =new int[]{1,2,3,4,5}
「但在日常的使用中,动态初始化使用的更加广泛也更加方便。」
有以下几点需要注意一下:
数组长度不要求必须是常量,可以是n,则创建了一个长度为n的数组 一旦创建了数组就不能够再改变它的长度了,不过可以改变它的单个数组元素。 数组内元素之间用逗号分隔开,并且最后一个元素允许有逗号 并且你甚至可以声明一个匿名数组, new int[]{1,2,3,4,}
数组元素的下标从0开始,则最大下标即为length-1;
「在Java
中允许有长度为0的数组」,这在编写一个结果为数组的方法时,如果碰巧结果为空,长度为0的数组就很有用。
需要注意的是数组为空与null并不相同
访问数组元素
前面我们了解到怎么创建一个数组,一旦创建了一个数组就可以向数组容器当中添加元素。来看个栗子:
int[]a=new int[100];
for(int i=0;i<a.length;i++){
a[i]=i
}
//此时将元素挨个存入a数组当中。
其实Java
为了我们在使用数组时的安全问题,特意为每个不同类型的数组默认指定了***初始值***。
当创建一个int类型的数组时,所有的元素都被初始化为0 当创建一个float类型的数组时,所有元素都被初始化为0.0 当创建一个boolean类型的数组时,所有元素都被初始化为false 当创建一个对象类型的数组时,所有元素都被初始化为null
需要特别指出的是对象类型的数组指除了基本数据类型以外的引用数据类型。
相信很多人对对象类型的数组不是很了解,下面来看个栗子:(以String为栗子)
String[] names=new String[10];
//为这个数组初始化值。假设我们希望这个数组将元素初始化为空字符
for(int i=0;i<names.length;i++){
names[i]=" ";
}
这里需要注意的是如果我们创建了10个长度的数组,并且尝试去访问a[10]元素时,就会引发“array index out of bounds”
异常(数组下标越界)
如果想看看数组内元素究竟包括哪些及怎样获取数组的长度,可以进行如下操作:
String[] s=new String[5];
for(int i=0;i<s.length;i++){
System.out.println(s[i]);
}
其中s.length
即为数组的长度
for each循环
Java
有一种功能很强的循环,可以用来依次处理数组(或其他元素集合)中的每个元素,而不必考虑其下标值。
这种「增强型for循环」的语句格式如下:
for(variable:collection) statement
它定义一个变量用于「暂存」集合中的每一个元素。并执行相应的语句,当然也可以是语句块。
看个栗子:
int [] array=new int[5];
for(int element:array){
System.out.println(element);
}
上面的栗子将打印array数组的元素,每个元素占一行。
当然使用传统的for循环也是能够达到这样的效果的。
但是个人觉得增强型for循环更好,因为它不用为下标的起始值和终止值操心,因为下标值很容易出错,并且容易导致数组索引越界异常的出现。
这里需要注意的是:for each语句循环变量会遍历数组中的每个元素,而不是下标值
「如果需要处理一个集合中的所有元素,for each语句会很方便,但是在很多情况下我们还是会使用传统的for循环。」
其实还有一个更简便的方法:采用Arrays类的toString
方法,可以返回包含数组元素的字符串,这些元素包括在括号中,用逗号分隔。要想打印数组,只需要调用System.out.println(Arrays.toString(a));
来看个栗子:
好了,for each循环介绍到这里,下面来说说数组的拷贝。
数组拷贝
说到拷贝,相信我们大多数的人都很清楚,那么什么是数组拷贝呢?
❝数组拷贝:将一个数组变量拷贝到另一个数组变量,这时两个数组变量引用同一个数组。
❞
来看个栗子:
int[] smallprimes=new int[]{1,2,3,4,5,6,};
int[]luckynumbers=smallprimes;
//此时两个数组变量引用了同一个数组。
samllprimes[1]==2;
lucknumbers[1]==2;
其实这种拷贝是将某个数组的内存地址复制给了另一个数组变量,两个数组变量拥有相同的内存地址。即按地址传递
下面用图来表示一下:
如果是希望将一个数组的所有值拷贝到一个新数组中去的话,就要使用Arrays类的copyOf
方法:
int[] copieslucknumbers=Arrays.copyOf(lucknumbers,lucknumbers.length)
第2个参数表示的是新数组的长度,这个方法常用来增加数组的长度。(本质上还是复制了引用)
前面说到了初始化,那么经过拷贝后新数组的初始化是什么样的呢?
如果数组元素是数值型的,那么额外的元素则是0 如果数组元素是布尔类型,那么额外元素都是false
「相反,如果新数组的长度小于原始数组的长度,则只拷贝前面的值。」
值得注意的是;
Java
中的[]运算会被预定义为会完成的越界检查,而且没有指针运算,即:不能通过a+1得到数组中的下一个元素
命令行参数
相信在前面的很多Java
应用程序中都见过一个Java
数组,每一个应用程序都有一个带String []args
参数的main方法,这个参数表明main方法将接受一个字符串数组,也就是命令行上指定的参数。
来看个栗子:
public class Messages{
public static void main(String[]args){
if(args.length==0 || args[0].equals("-h"))
System.out.println("Hello,");
else if(args[0].equals("-g"))
System.out.println("Goodbye,");
for(int i=1;i<args.lenth;i++){
System.out.println(" "+args[i]);
}
System.out.println("!");
}
}
如果使用下列形式调用java Message -g cruel world
args
数组将包括以下内容:
args[0]:"-g"
args[1]:"cruel"
args[2]:"world"
最终会显示如下消息:
Goodbye ,cruel world!
同时需要注意的是在Java
应用程序中,程序名并没有存储在args
数组中。
数组排序
如果想要对数组的元素按照一定的规则进行排序的话,可以使用Arrays类的sort方法
int []a=new int[1000];
`````
Arrays.sort(a);
//调用方法对a数组进行排序。
下面看看Arrays类的常用方法
好了,了解了排序,下面来看看多维数组。
多维数组
之前我们说到的数组其实是一维数组,它比较简单,也比较适合处理比较简单的事物。那么什么是多维数组呢?
❝多维数组指的是包「含一个或多个数组的数组。」
❞
多维数组实质上是用多个下标来访问数组元素,它适用于表示表格或更加复杂的排列形式。但它还是一个数组
其实多维数组分为好多种形式:二维数组、三维数组等等。
为了简单起见,我们着重介绍一下二维数组:
其实二维数组也被称为「矩阵」,定义它的规则与定义一维数组的规则大相径庭。
double[][]balances;
可以看到double后跟着两个中括号,表示其是一个二维数组,
二维数组的初始化本质上与一维数组的初始化一样,也可以分为动态初始化和静态初始化。
动态初始化: double[][] balances=new double[5][10]
,这里表示二维数组内包含5个一维数组。静态初始化: double[][] balances={{1.0,2.0,3.0,4.0},{5.0,6.0,7.0}}
一旦进行了初始化,就可以采用两个中括号访问各个元素,例如;balances[1][0]
注意:
for each循环不能够自动处理二维数组的每个元素,它会循环处理行,而这些行本身也是一个一维数组,因此要想访问二维数组中的所有元素,需要使用两个嵌套的循环
栗子:
for(double[] row :a){
for(double value:row){
do something with value;
}
}
可以看出栗子中,外层for循环是依次遍历了一个一维数组,也就是行,内层循环是依次访问一维数组中的每个值。
当然如果你想偷懒,快速打印一个二维数组的数据元素列表。可以调用:
System.out.println(Arrays.deepToString(a))
输出的二维数组的格式为:
[16,3,2],[15,6,9],[5,98,7]
好了,数组的相关知识点就介绍到这里。