黄子涵

3.10 数组

数组存储相同类型值的序列。

声明数组

下标(index,或称索引)

数组是一种数据结构,用来存储同一类型值的集合。通过一个整型下标(index,或称索引)可以访问数组中的每一个值。例如,如果 a 是一个整型数组,a[i]就是数组中下标为 i 的整数。

在声明数组变量时,需要指出数组类型(数据元素类型紧跟[])和数组变量的名字。下面声明了整型数组 a

int[] a;

程序示例

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   int[] huangzihan_a;
	   int[] huangzihan_b;
	   int[] huangzihan_c;
   }
}

运行结果


创建数组

不过,这条语句只声明了变量 a ,并没有将 a 初始化为一个真正的数组。应该使用 new 操作符创建数组。

int[] a = new int[100];     //or var a = new int[100];

这条语句声明并初始化了一个可以存储100个整数的数组。

程序示例

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   int[] huangzihan_a = new int[0];
	   int[] huangzihan_b = new int[5];
	   int[] huangzihan_c = new int[10];
	   
	   System.out.println(huangzihan_a);
	   System.out.println(huangzihan_b);
	   System.out.println(huangzihan_c);
   }
}

运行结果

[I@24d46ca6
[I@4517d9a3
[I@372f7a8d

数组长度

数组长度不要求是常量:new int[n]会创建一个长度为 n 的数组。

程序示例

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   int[] huangzihan_a = new int[0];
	   int[] huangzihan_b = new int[5];
	   int[] huangzihan_c = new int[10];
	   
	   System.out.println(huangzihan_a.length);
	   System.out.println(huangzihan_b.length);
	   System.out.println(huangzihan_c.length);
   }
}

运行结果

0
5
10

数组列表(array list)

一旦创建了数组,就不能再改变它的长度(不过,当然可以改变单个的数组元素)。如果程序运行中需要经常扩展数组的大小,就应该使用另一种数据结构——数组列表(array list)。

注释

可以使用下面两种形式定义一个数组变量:

int[] a;

int a[];

大多数Java应用程序员喜欢使用第一种风格,因为它可以将类型int[](整型数组)与变量名清晰地分开。

初始化数组对象

在Java中,提供了一种创建数组对象并同时提供初始值的简写形式。下面是一个例子:

int[] smallPrimes = {2, 3, 5, 7, 11, 13};

程序示例

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   int[] huangzihan_a = {};
	   int[] huangzihan_b = {1, 2, 3, 4, 5};
	   int[] huangzihan_c = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
	   
	   System.out.println(huangzihan_a);
	   
	   System.out.println();
	   
	   System.out.println(huangzihan_b[0]);
	   System.out.println(huangzihan_b[1]);
	   System.out.println(huangzihan_b[2]);
	   System.out.println(huangzihan_b[3]);
	   System.out.println(huangzihan_b[4]);
	   
	   System.out.println();
	   
	   System.out.println(huangzihan_c[0]);
	   System.out.println(huangzihan_c[1]);
	   System.out.println(huangzihan_c[2]);
	   System.out.println(huangzihan_c[3]);
	   System.out.println(huangzihan_c[4]);
	   System.out.println(huangzihan_c[5]);
	   System.out.println(huangzihan_c[6]);
	   System.out.println(huangzihan_c[7]);
	   System.out.println(huangzihan_c[8]);
	   System.out.println(huangzihan_c[9]);
   }
}

运行结果

[I@24d46ca6

1
2
3
4
5

10
11
12
13
14
15
16
17
18
19

请注意,这个语法中不需要使用new,甚至不用指定长度。

数组增加值

最后一个值后面允许有逗号,如果你要不断为数组增加值,这会很方便:

String[] authors = {
   "James Gosling",
   "Bil1 Joy",
   "Guy Steele",
   // add more names here and put a comma after each name
};

程序示例

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   String[] huangzihan_authors = 
	   {
			   "Huangzihan",
			   "Huang_zihan",
			   "HuangZihan",
			   "Huang_Zihan",
			   "huangzihan",
			   "huang_zihan",
	   };
	   
	   System.out.println(huangzihan_authors[0]);
	   System.out.println(huangzihan_authors[1]);
	   System.out.println(huangzihan_authors[2]);
	   System.out.println(huangzihan_authors[3]);
	   System.out.println(huangzihan_authors[4]);
	   System.out.println(huangzihan_authors[5]);
   }
}

运行结果

Huangzihan
Huang_zihan
HuangZihan
Huang_Zihan
huangzihan
huang_zihan

匿名数组

还可以声明一个匿名数组

new int[] { 17, 19, 23, 29, 31, 37 }

这会分配一个新数组并填入大括号中提供的值。它会统计初始值个数,并相应地设置数组大小。可以使用这种语法重新初始化一个数组而无须创建新变量。例如:

smallPrimes = new int[] { 17, 19, 23, 29, 31, 37};

这是下列语句的简写形式:

int[] anonymous = { 17, 19, 23, 29, 31, 37 };
smallPrimes = anonymous;

程序示例

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   int[] huangzihan_a = new int[] {17, 19, 23, 29, 31, 37};
	   int[] huangzihan_b = huangzihan_a;
	   
	   System.out.println(huangzihan_a[0]);
	   System.out.println(huangzihan_a[1]);
	   System.out.println(huangzihan_a[2]);
	   System.out.println(huangzihan_a[3]);
	   System.out.println(huangzihan_a[4]);
	   System.out.println();
	   System.out.println(huangzihan_b[0]);
	   System.out.println(huangzihan_b[1]);
	   System.out.println(huangzihan_b[2]);
	   System.out.println(huangzihan_b[3]);
	   System.out.println(huangzihan_b[4]);
   }
}

运行结果

17
19
23
29
31

17
19
23
29
31

注释

在Java中,允许有长度为0的数组。在编写一个结果为数组的方法时,如果碰巧结果为空,这样一个长度为0的数组就很有用。可以如下创建长度为0的数组:

new elementType[0]

new elementType[] {}

注意,长度为0的数组与null并不相同。

访问数组元素

前面的数组元素的下标为从0 ~ 99(不是1 ~ 100)。一旦创建了数组,就可以在数组中填入元素。例如,使用一个循环:

image

程序示例

image

运行结果

0
1
2
3
4

boolean数组与null

创建一个数字数组时,所有元素都初始化为0。 boolean 数组的元素会初始化为 false 。对象数组的元素则初始化为一个特殊值 null ,表示这些元素(还)未存放任何对象。初学者对此可能有些不解。例如,

String[] names = new String[10];

程序示例

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   String[] huangzihan_a = new String[5];
	   boolean[] huangzihan_b = new boolean[5]; 
	   
	   System.out.println(huangzihan_a[0]);
	   System.out.println(huangzihan_a[1]);
	   System.out.println(huangzihan_a[2]);
	   System.out.println(huangzihan_a[3]);
	   System.out.println(huangzihan_a[4]);
	   System.out.println();
	   System.out.println(huangzihan_b[0]);
	   System.out.println(huangzihan_b[1]);
	   System.out.println(huangzihan_b[2]);
	   System.out.println(huangzihan_b[3]);
	   System.out.println(huangzihan_b[4]);
   }
}

运行结果

null
null
null
null
null

false
false
false
false
false

会创建一个包含10个字符串的数组,所有字符串都为 null 。如果希望这个数组包含空串,必须为元素指定空串:

image

程序示例

image

运行结果


警告

如果创建了一个100个元素的数组,并且试图访问元素a[100](或在0 ~ 99之外的任何下标),就会引发“array index out of bounds”异常。

要想获得数组中的元素个数,可以使用 array.length 。例如,

image

程序示例

image

运行结果

null

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
	at HuangZiHanTest.main(HuangZiHanTest.java:11)

for each循环

Java有一种功能很强的循环结构,可以用来依次处理数组(或者其他元素集合)中的每个元素,而不必考虑指定下标值。

这种增强for 循环的语句格式为:

for(variable:collection)   statement

它定义一个变量用于暂存集合中的每一个元素,并执行相应的语句(当然,也可以是语句块)。collection 这一集合表达式必须是一个数组或者是一个实现了 Iterable 接口的类对象(例如 ArrayList )。

例如,

for(int element:a)
   System.out.println(element);

打印数组 a 的每一个元素,一个元素占一行。

这个循环应该读作“循环a中的每一个元素”(for each element in
a)。Java语言的设计者认为应该使用诸如 foreachin 这样的关键字,但这种循环语句并不是最初就包含在Java语言中的,而是后来添加进去的,而且没有人希望破坏已经包含同名(例如 Systen.in )方法或变量的旧代码。

当然,使用传统的 for 循环也可以获得同样的效果:

image

但是,for each循环语句显得更加简洁、更不易出错,因为你不必为下标的起始值和终止值而操心。

程序示例

image

运行结果

1
2
3
4
5

1
2
3
4
5

注释

for each 循环语句的循环变量将会遍历数组中的每个元素,而不是下标值。

如果需要处理一个集合中的所有元素,for each 循环语句相对于传统循环语句所做的改进很让人欣喜。然而,在很多情况下还是需要使用传统的 for 循环。例如,如果不希望遍历整个集合,或者在循环内部需要使用下标值时。

提示

有一个更加简单的方式可以打印数组中的所有值,即利用 Arrays 类的 toString 方法。调用 Arrays.toString(a) ,返回一个包含数组元素的字符串,这些元素包围在中括号内,并用逗号分隔,例如,"[2,3,5,7,11,13]"。要想打印数组,只需要调用

System.out.println(Arrays.toString(a));

程序示例

import java.util.Arrays;

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   int[] huangzihan_int = {11, 12, 13, 14, 15};
	   double[] huangzihan_double = {1.0, 2.0, 3.0, 4.0, 5.0};
	   char[] huangzihan_char = {'黄','子','涵','是','帅','哥','!'};
	   boolean[] huangzihan_boolean = {true,false};
	   byte[] huangzihan_byte = {1, 2, 3, 4, 5};
	   System.out.println(Arrays.toString(huangzihan_int));
	   System.out.println(Arrays.toString(huangzihan_double));
	   System.out.println(Arrays.toString(huangzihan_char));
	   System.out.println(Arrays.toString(huangzihan_boolean));
	   System.out.println(Arrays.toString(huangzihan_byte));
   }
}

运行结果

[11, 12, 13, 14, 15]
[1.0, 2.0, 3.0, 4.0, 5.0]
[黄, 子, 涵, 是, 帅, 哥, !]
[true, false]
[1, 2, 3, 4, 5]

数组拷贝

在Java中,允许将一个数组变量拷贝到另一个数组变量。这时,两个变量将引用同一个数组:

int[] luckyNumbers = smallPrimes;
luckyNumbers[5] = 12;    //now smallPrimes[5] is also 12

程序示例

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   int[] huangzihan_smallPrimes = new int[6];
	   int[] huangzihan_luckyNumbers = huangzihan_smallPrimes;
	   huangzihan_luckyNumbers[5] = 12;
	   
	   System.out.println(huangzihan_luckyNumbers[5]);
	   System.out.println(huangzihan_smallPrimes[5]);
   }
}

运行结果

12
12

copyOf方法

图(拷贝一个数组变量)显示了拷贝的结果。如果希望将一个数组的所有值拷贝到一个新的数组中去,就要使用 Arrays 类的 copyOf 方法:

image

int[] copiedLuckyNumbers =
Arrays.copyOf(LuckyNumbers,LuckyNumbers.length);

第2个参数是新数组的长度。这个方法通常用来增加数组的大小:

luckyNumbers = Arrays.copyOf(luckyNumbers,2*luckyNumbers.length);

如果数组元素是数值型,那么额外的元素将被赋值为0;如果数组元素是布尔型,则将赋值为 false 。相反,如果长度小于原始数组的长度,则只拷贝前面的值。

程序示例

import java.util.Arrays;

public class HuangZiHanTest
{  
   public static void main(String[] args)
   {   
	   System.out.println("第一部分测试开始!");
	   int[] huangzihan_smallPrimes_int = {1, 2, 3, 4, 5, 6};
	   System.out.println("huangzihan_smallPrimes_int[]="+Arrays.toString(huangzihan_smallPrimes_int));
	   int[] huangzihan_luckyNumbers_int = huangzihan_smallPrimes_int;
	   System.out.println("huangzihan_luckyNumbers_int[5]="+huangzihan_luckyNumbers_int[5]);	
	   System.out.println("huangzihan_smallPrimes_int[5]="+huangzihan_smallPrimes_int[5]);
	   huangzihan_luckyNumbers_int[5] = 12;
	   System.out.println("");
	   System.out.println("huangzihan_smallPrimes_int[5]="+huangzihan_smallPrimes_int[5]);
	   System.out.println("huangzihan_luckyNumbers_int[5]="+huangzihan_luckyNumbers_int[5]);
	   System.out.println("第一部分测试结束!");
	   System.out.println("");
	   
	   System.out.println("第二部分测试开始!");
	   char[] huangzihan_smallPrimes_char = {'黄','子','涵','是','帅','哥','!'};
	   System.out.println("huangzihan_smallPrimes_char[]="+Arrays.toString(huangzihan_smallPrimes_char));
	   char[] huangzihan_luckyNumbers_char = huangzihan_smallPrimes_char;
	   System.out.println("huangzihan_smallPrimes_char[5]="+huangzihan_smallPrimes_char[5]);
	   System.out.println("huangzihan_luckyNumbers_char[5]="+huangzihan_luckyNumbers_char[5]);
	   huangzihan_luckyNumbers_char[5] = '黄';
	   System.out.println("");
	   System.out.println("huangzihan_luckyNumbers_char[5]="+huangzihan_luckyNumbers_char[5]);
	   System.out.println("huangzihan_smallPrimes_char[5]="+huangzihan_smallPrimes_char[5]);
	   System.out.println("第二部分测试结束!");
	   System.out.println("");
	   
	   System.out.println("第三部分测试开始!");
	   boolean[] huangzihan_smallPrimes_boolean = {true, false, true, false, true, false};
	   System.out.println("huangzihan_smallPrimes_boolean[]="+Arrays.toString(huangzihan_smallPrimes_boolean));
	   System.out.println("");
	   boolean[] huangzihan_luckyNumbers_boolean = huangzihan_smallPrimes_boolean;
	   System.out.println("huangzihan_luckyNumbers_boolean[5]="+huangzihan_luckyNumbers_boolean[5]);	
	   System.out.println("huangzihan_smallPrimes_boolean[5]="+huangzihan_smallPrimes_boolean[5]);
	   System.out.println("");
	   huangzihan_luckyNumbers_boolean[5] = true;
	   System.out.println("huangzihan_smallPrimes_boolean[5]="+huangzihan_smallPrimes_boolean[5]);
	   System.out.println("huangzihan_luckyNumbers_boolean[5]="+huangzihan_luckyNumbers_boolean[5]);
	   System.out.println("第三部分测试结束!");
	   System.out.println("");
	   
	   System.out.println("第四部分测试开始!");
	   int[] huangzihan_int = Arrays.copyOf(huangzihan_luckyNumbers_int, huangzihan_luckyNumbers_int.length);
	   char[] huangzihan_char = Arrays.copyOf(huangzihan_luckyNumbers_char, huangzihan_luckyNumbers_char.length);
	   boolean[] huangzihan_boolean = Arrays.copyOf(huangzihan_luckyNumbers_boolean, huangzihan_luckyNumbers_boolean.length);
	   
	   System.out.println("huangzihan_int[5]="+huangzihan_int[5]);
	   System.out.println("huangzihan_char[5]="+huangzihan_char[5]);
	   System.out.println("huangzihan_boolean[5]="+huangzihan_boolean[5]);
	   System.out.println("第四部分测试结束!");
	   System.out.println("");
	   
	   System.out.println("第五部分测试开始!");
	   huangzihan_luckyNumbers_int = Arrays.copyOf(huangzihan_luckyNumbers_int, 2*huangzihan_luckyNumbers_int.length);
	   huangzihan_luckyNumbers_char = Arrays.copyOf(huangzihan_luckyNumbers_char, 2*huangzihan_luckyNumbers_char.length);
	   huangzihan_luckyNumbers_boolean = Arrays.copyOf(huangzihan_luckyNumbers_boolean, 2*huangzihan_luckyNumbers_boolean.length);
	   System.out.println("huangzihan_luckyNumbers_int[5]="+huangzihan_luckyNumbers_int[5]);
	   System.out.println("huangzihan_luckyNumbers_char[5]="+huangzihan_luckyNumbers_char[5]);
	   System.out.println("huangzihan_luckyNumbers_boolean[5]="+huangzihan_luckyNumbers_boolean[5]);
	   System.out.println("");
	   System.out.println("huangzihan_luckyNumbers_int[10]="+huangzihan_luckyNumbers_int[10]);
	   System.out.println("huangzihan_luckyNumbers_char[10]="+huangzihan_luckyNumbers_char[10]);
	   System.out.println("huangzihan_luckyNumbers_boolean[10]="+huangzihan_luckyNumbers_boolean[10]);
	   System.out.println("第五部分测试结束!");
	   System.out.println("");
	   
	   System.out.println("第六部分测试开始!");
	   int[] Huangzihan_int = {1, 2, 3, 4, 5, 6};
	   System.out.println("Huangzihan_int[]="+Arrays.toString(Huangzihan_int));
	   int[] Huangzihan_copyOf_int = Arrays.copyOf(Huangzihan_int, 3);
	   System.out.println("Huangzihan_copyOf_int[]="+Arrays.toString(Huangzihan_copyOf_int));
	   System.out.println("");
	   char[] Huangzihan_char = {'黄','子','涵','是','帅','哥','!'};
	   System.out.println("Huangzihan_char[]="+Arrays.toString(Huangzihan_char));
	   char[] Huangzihan_copyOf_char = Arrays.copyOf(Huangzihan_char, 3);
	   System.out.println("Huangzihan_copyOf_char[]="+Arrays.toString(Huangzihan_copyOf_char));
	   System.out.println("");
	   boolean[] Huangzihan_boolean = {true, false, true, false, true, false};
	   System.out.println("Huangzihan_boolean[]="+Arrays.toString(Huangzihan_boolean));
	   boolean[] Huangzihan_copyOf_boolean = Arrays.copyOf(Huangzihan_boolean, 3);
	   System.out.println("Huangzihan_copyOf_boolean[]="+Arrays.toString(Huangzihan_copyOf_boolean));	      
	   System.out.println("第六部分测试结束!");
	   System.out.println("");
   }
}

运行结果

第一部分测试开始!
huangzihan_smallPrimes_int[]=[1, 2, 3, 4, 5, 6]
huangzihan_luckyNumbers_int[5]=6
huangzihan_smallPrimes_int[5]=6

huangzihan_smallPrimes_int[5]=12
huangzihan_luckyNumbers_int[5]=12
第一部分测试结束!

第二部分测试开始!
huangzihan_smallPrimes_char[]=[黄, 子, 涵, 是, 帅, 哥, !]
huangzihan_smallPrimes_char[5]=哥
huangzihan_luckyNumbers_char[5]=哥

huangzihan_luckyNumbers_char[5]=黄
huangzihan_smallPrimes_char[5]=黄
第二部分测试结束!

第三部分测试开始!
huangzihan_smallPrimes_boolean[]=[true, false, true, false, true, false]

huangzihan_luckyNumbers_boolean[5]=false
huangzihan_smallPrimes_boolean[5]=false

huangzihan_smallPrimes_boolean[5]=true
huangzihan_luckyNumbers_boolean[5]=true
第三部分测试结束!

第四部分测试开始!
huangzihan_int[5]=12
huangzihan_char[5]=黄
huangzihan_boolean[5]=true
第四部分测试结束!

第五部分测试开始!
huangzihan_luckyNumbers_int[5]=12
huangzihan_luckyNumbers_char[5]=黄
huangzihan_luckyNumbers_boolean[5]=true

huangzihan_luckyNumbers_int[10]=0
huangzihan_luckyNumbers_char[10]=

命令行参数

Stringarg[]参数

前面已经看到一个Java数组重复出现过很多次。每一个Java应用程序都有一个带 Stringarg[]参数的 main
方法。这个参数表明main方法将接收一个字符串数组,也就是命令行上指定的参数。

例如,来看下面这个程序:

image

如果使用下面这种形式调用这个程序:

java Message -g cruel world 

args 数组将包含以下内容:

args[0]: "-g"
args[1]:"cruel"
args[2]:"world"

这个程序会显示下面这个消息:

Goodbye,cruel world!

程序示例

image

运行结果

Hello,!

数组排序

sort方法

要想对数值型数组进行排序,可以使用 Arrays 类中的 sort 方法:

int[] a = new int[10000];
. . .
Arrays.sort(a)

这个方法使用了优化的快速排序(QuickSort)算法。快速排序算法对于大多数数据集合来说都是效率比较高的。

程序清单3-7中的程序具体使用了数组,它产生一个抽彩游戏中的随机数字组合。假如抽彩是从49个数字中抽取6个,那么程序可能的输出结果为:

Bet the following combination.It'll make you rich!
4
7
8
19
30
44

要想选择这样一个随机的数字集合,就要首先将值 1,2,...,n 存入数组 numbers 中:

image

而用第二个数组存放抽取出来的数:

int[] result = new int[k];

现在,就可以开始抽取 k 个数了。Math.random 方法将返回一个 01 之间(包含0、不包含1)的随机浮点数。用 n 乘以这个浮点数,就可以得到从 0n-1 之间的一个随机数。

int r =(int)(Math.random() * n);

下面将 result 的第 i 个元素设置为numbers[r]存放的数值,最初是 r+1 。但正如所看到的,numbers 数组的内容在每一次抽取之后都会发生变化。

result[i] = numbers[r];

现在,必须确保不会再次抽取到那个数,因为所有抽彩的数必须不相同。因此,这里用数组中的最后一个数覆盖number[r],并将 n1

numbers[r] = numbers[n - 1];
n--;

关键在于每次抽取的都是下标,而不是实际的值。下标指向数组中包含尚未抽取过的值。

在抽取了 k 个数之后,可以对result数组进行排序,这样可以让输出效果更好:

Arrays.sort(result);
for(int r : result)
    System.out.println(r);

程序示例

运行结果

你需要画多少个数字?
5
huangzihan_k=5
你能画5个数字

你能画最高的数字是多少?
10
huangzihan_n=10
你能画最高的数字是10

huangzihan_numbers.length=10

第1次循环
1

第2次循环
2

第3次循环
3

第4次循环
4

第5次循环
5

第6次循环
6

第7次循环
7

第8次循环
8

第9次循环
9

第10次循环
10

huangzihan_numbers[]=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

huangzihan_result.length=5

第1次循环
10
10
9
9

第2次循环
9
9
8
8

第3次循环
2
8
1
7

第4次循环
7
7
6
6

第5次循环
1
6
0
5

huangzihan_result[]=[10, 9, 2, 7, 1]
快速排序之后:[1, 2, 7, 9, 10]

127910

多维数组

多维数组将使用多个下标访问数组元素,它适用于表示表格或更加复杂的排列形式。假设需要建立一个数值表格,用来显示在不同利率下投资10000美元会增长多少,利息每年兑现并复投(见表(不同利率下的投资增长情况))。

不同利率下的投资增长情况

10% 11% 12% 13% 14% 15%
10 000.00 10 000.00 10 000.00 10 000.00 10 000.00 10 000.00
11 000.00 11 100.00 11 200.00 11 300.00 11 400.00 11 500.00
12 100.00 12 321.00 12 544.00 12 769.00 12 996.00 13 225.00
13 310.00 13 676.31 14 049.28 14 428.97 14 815.44 15 208.75
14 641.00 15 180.70 15 735.19 16 304.74 16 889.60 17 490.06
16 105.10 16 850.58 17 623.42 18 424.35 19 254.15 20 113.57
17 715.61 18 704.15 19 738.23 20 819.52 21 949.73 23 130.61
19 487.17 20 761.60 22 106.81 23 526.05 25 022.69 26 600.20
21 435.89 23 045.38 24 759.63 26 584.44 28 525.86 30 590.23
23 579.48 25 580.37 27 730.79 30 040.42 32 519.49 35 178.76

可以使用一个二维数组(也称为矩阵)来存储这些信息。这个数组被命名为balances

声明二维数组

在Java中,声明一个二维数组相当简单。例如:

double[][] balances;

程序示例

public class HuangZiHanTest
{  
	public static void main(String[] huangzihan_args)
    {   
	   double[][] balances;
    }
}

运行结果


初始化二维数组

对数组进行初始化之前是不能使用的。在这里可以如下初始化:

balances = new double[NYEARS][NRATES];

另外,如果知道数组元素,就可以不调用new,而直接使用简写形式对多维数组进行初始化。例如:

int[][] magicSquare =
{
    {16, 3, 2, 13},
    {5, 10, 11, 8},
    {9, 6, 7, 12},
    {4, 15, 14, 1}
};

一旦数组初始化,就可以利用两个中括号访问各个元素,例如,balances[i][j]

在示例程序中用到了一个存储利率的一维数组interest与一个存储余额的二维数组balances,一维用于表示年,另一维表示利率,使用初始余额来初始化这个数组的第一行:

image

然后计算其他行,如下所示:

image

程序示例

image

运行结果

huangzihan_balances[][]=[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]

huangzihan_magicSquare[][]=[[16, 3, 2, 13], [5, 10, 11, 8], [9, 6, 7, 12], [4, 15, 14, 1]]

[[10000.0, 10000.0, 10000.0, 10000.0, 10000.0, 10000.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]

注释

for each循环语句不能自动处理二维数组的每一个元素。它会循环处理行,而这些行本身就是一维数组。要想访问二维数组 a 的所有元素,需要使用两个嵌套的循环,如下所示:

for (double[] row : a)
    for (double value : row)
        do something with value

提示

要想快速地打印一个二维数组的数据元素列表,可以调用:

System.out.println(Arrays.deepToString(a));

输出格式为:

[[16, 3, 2, 13], [5, 10, 11, 8], [9, 6, 7, 12], [4, 15, 14, 1]]

程序示例

import java.util.Arrays;

public class HuangZiHanTest
{  
	public static void main(String[] huangzihan_args)
    {   
	    double[][] huangzihan_a =
	    {
	    		{1, 2, 3, 4},
	    		{5, 6, 7, 8},
	    		{4, 3, 2, 1},
	    		{8, 7, 6, 5},
	    };		
		for(double[] row : huangzihan_a) 
		{
			for(double huangzihan_value : row) 
			{
				System.out.println(Arrays.deepToString(huangzihan_a));
			}
		}
    }
}

运行结果

[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]
[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [4.0, 3.0, 2.0, 1.0], [8.0, 7.0, 6.0, 5.0]]

不规则数组

到目前为止,我们看到的数组与其他程序设计语言中提供的数组没有多大区别。但在底层实际存在着一些细微的差异,有时你可以充分利用这一点:Java实际上没有多维数组,只有一维数组。多维数组被解释为“数组的数组”。

例如,在前面的示例中,balances数组实际上是一个包含10个元素的数组,而每个元素

又是一个由6个浮点数组成的数组(请参看图(一个二维数组))。

image

表达式balances[i]引用第 i 个子数组,也就是表格的第 i 行。它本身也是一个数组,balances[i][j]引用这个数组的第 j 个元素。

由于可以单独地访问数组的某一行,所以可以让两行交换。

double[] temp = balances[i];
balances[i] = balances[i + 1];
balances[i + 1] = temp;

程序示例

import java.util.Arrays;

public class HuangZiHanTest
{  
	public static void main(String[] huangzihan_args)
    {   
	    double[] huangzihan_temp;
		int huangzihan_i=0;
		double[][] huangzihan_balances = 
		{
				{1, 2, 3, 4},
				{4, 3, 2, 1},
				{5, 6, 7, 8},
				{8, 7, 6, 5},
		};
		huangzihan_temp = huangzihan_balances[huangzihan_i];
		huangzihan_balances[huangzihan_i] = huangzihan_balances[huangzihan_i + 1];
		huangzihan_balances[huangzihan_i + 1] = huangzihan_temp;
	    System.out.println(Arrays.deepToString(huangzihan_balances));
    }
}

运行结果

[[4.0, 3.0, 2.0, 1.0], [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [8.0, 7.0, 6.0, 5.0]]

还可以方便地构造一个“不规则”数组,即数组的每一行有不同的长度。下面是一个标准的示例。我们将创建一个数组,第 i 行第 j 列将存放“从 i 个数中抽取 j 个数”可能的结果数。

1
1  1
1  2  1
1  3  3  1
1  4  6  4  1
1  5  10 10 5  1
1  6  15 20 15 6  1

由于 j 不可能大于 i,所以矩阵是三角形的。第 i 行有 i + 1 个元素(允许抽取 0 个元素,这种选择只有一种可能)。要想创建这样一个不规则的数组,首先需要分配一个数组包含这些行:

int[][] odds = new int[NMAx + 1][];

接下来,分配这些行:

image

在分配了数组之后,假定没有超出边界,就可以采用通常的方式访问其中的元素了。

image

程序示例

image

运行结果

5

[[0], [0, 0], [0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0, 0]]

huangzihan_lotteryoOdds=1
huangzihan_lotteryoOdds=2
huangzihan_lotteryoOdds=2
huangzihan_lotteryoOdds=1
huangzihan_lotteryoOdds=3
huangzihan_lotteryoOdds=3
huangzihan_lotteryoOdds=3
huangzihan_lotteryoOdds=3
huangzihan_lotteryoOdds=3
huangzihan_lotteryoOdds=1
huangzihan_lotteryoOdds=4
huangzihan_lotteryoOdds=4
huangzihan_lotteryoOdds=6
huangzihan_lotteryoOdds=4
huangzihan_lotteryoOdds=6
huangzihan_lotteryoOdds=4
huangzihan_lotteryoOdds=4
huangzihan_lotteryoOdds=6
huangzihan_lotteryoOdds=4
huangzihan_lotteryoOdds=1

huangzihan_odds=[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]

   1
   1   1
   1   2   1
   1   3   3   1
   1   4   6   4   1

posted @ 2021-08-25 00:12  黄子涵  阅读(110)  评论(0编辑  收藏  举报