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)。一旦创建了数组,就可以在数组中填入元素。例如,使用一个循环:
程序示例
运行结果
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 。如果希望这个数组包含空串,必须为元素指定空串:
程序示例
运行结果
警告
如果创建了一个100个元素的数组,并且试图访问元素a[100](或在0 ~ 99之外的任何下标),就会引发“array index out of bounds”异常。
要想获得数组中的元素个数,可以使用 array.length 。例如,
程序示例
运行结果
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语言的设计者认为应该使用诸如 foreach 、 in 这样的关键字,但这种循环语句并不是最初就包含在Java语言中的,而是后来添加进去的,而且没有人希望破坏已经包含同名(例如 Systen.in )方法或变量的旧代码。
当然,使用传统的 for 循环也可以获得同样的效果:
但是,for each循环语句显得更加简洁、更不易出错,因为你不必为下标的起始值和终止值而操心。
程序示例
运行结果
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 方法:
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方法将接收一个字符串数组,也就是命令行上指定的参数。
例如,来看下面这个程序:
如果使用下面这种形式调用这个程序:
java Message -g cruel world
args 数组将包含以下内容:
args[0]: "-g"
args[1]:"cruel"
args[2]:"world"
这个程序会显示下面这个消息:
Goodbye,cruel world!
程序示例
运行结果
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 中:
而用第二个数组存放抽取出来的数:
int[] result = new int[k];
现在,就可以开始抽取 k 个数了。Math.random 方法将返回一个 0 到 1 之间(包含0、不包含1)的随机浮点数。用 n 乘以这个浮点数,就可以得到从 0 到 n-1 之间的一个随机数。
int r =(int)(Math.random() * n);
下面将 result 的第 i 个元素设置为
numbers[r]
存放的数值,最初是 r+1 。但正如所看到的,numbers 数组的内容在每一次抽取之后都会发生变化。
result[i] = numbers[r];
现在,必须确保不会再次抽取到那个数,因为所有抽彩的数必须不相同。因此,这里用数组中的最后一个数覆盖
number[r]
,并将 n 减 1 。
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,一维用于表示年,另一维表示利率,使用初始余额来初始化这个数组的第一行:
然后计算其他行,如下所示:
程序示例
运行结果
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个浮点数组成的数组(请参看图(一个二维数组))。
表达式
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][];
接下来,分配这些行:
在分配了数组之后,假定没有超出边界,就可以采用通常的方式访问其中的元素了。
程序示例
运行结果
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