数组:
在Java
中,数组是用来存储一组数据类型相同的变量的值,这些变量共用一个变量名。Java
中的数组可以是一维数组也可以是多维数组,其中一维数组使用的频率比较高。
一维数组:
一维数组的声明:
type array-name[] = new type[size];
或者type[] array-name = new type[size];
type
:表示数组的数据类型
array-name
:表示数组的名字
size
:表示要创建的数组大小,即包含的数组有多少个元素。
从上面可以看出来,创建数组一般需要两个步骤:
(1)声明一个数组的引用变量
(2)给数组分配内存空间,并把数组的引用变量指向内存,使用new
操作符来动态分配。
举个例子:
int[] arr;//创建一个int类型数组的引用
arr = new int[10];//给arr数组分配内存空间,大小为10,并且用=连接引用与分配的内存
。数组都是具有索引的,索引表示的是该元素在数组中的位置,数组的索引都是从0开始的。
public class arraydemo {
public static void main(String [] args) {
//创建一个Int类型的数组,分配内存大小为10
int sample[] = new int[10];
int i;
//循环给数组赋值
for(i = 0; i < 10; i = i+1)
sample[i] = i;
//循环然后输出数组的值
for(i = 0; i < 10; i = i+1)
System.out.println("sample[" + i + "]: " + sample[i]);
}
}
输出结果:
This is sample[0]: 0
This is sample[1]: 1
This is sample[2]: 2
This is sample[3]: 3
This is sample[4]: 4
This is sample[5]: 5
This is sample[6]: 6
This is sample[7]: 7
This is sample[8]: 8
This is sample[9]: 9
而且数组也在常见的查找最大值最小值也是经常用到的,二分查找也有用到,比如:
public class minmax {
public static void main(String [] args) {
int nums[] = new int[10];
int min, max;
nums[0] = 99;
nums[1] = -10;
nums[2] = 100123;
nums[3] = 18;
nums[4] = -978;
nums[5] = 5623;
nums[6] = 463;
nums[7] = -9;
nums[8] = 287;
nums[9] = 49;
min = max = nums[0];
for (int i = 1; i < 10; i++) {
if(nums[i] < min) min = nums[i];
if(nums[i] > min) min = nums[i];
}
System.out.println("min and max: " + min + " " + max);
}
}
输出结果:
min and max: -978 100123
上面是先创建数组然后在初始化数组,下面这种语法是在创建数组的时候就初始化了数组的元素值,语法如下:
type array-name[] = {val1, val2, val3,......., valN};
如果是按照上面这种语法,那么就不需要使用new操作符,同效的代码如下:
public class Minmax2 {
public static void main(String [] args) {
int nums[] = {99, -10, 100123, 213, -9873, 5623, -9, 287, 49};
int min, max;
min = max = nums[9];
for(int i =1; i < 9; i++) {
if(nums[i] < min) min = nums[i];
if(nums[i] > max) max = nums[i];
}
System.out.println("Min and max: " + min + " " + max);
}
}
在日常使用数组的时候,还需要特别注意的一点是数组的边界,如果稍微不注意,那么就可能会抛出ArrayIndexOutOfBoundsException
异常,表示数组越界。
你可以使用下面这段带来来验证一下:
public class arrayerr {
public static void main(String [] args) {
int sample[] = new int[10];
int i;
//i=10时数组越界抛出异常
for(i = 0; i < 100; i = i+1)
sample[i] = i;
}
}
当i到10的时候,此时程序就会抛出异常ArrayIndexOutOfBoundException
,原因就是数组越界。
多维数组
二维数组是最简单的多维数组,换句话说二维数组也就是一维数组的数组。下面是定义一个二维数组,类似于表结构,一维表示行,二维表示列。
int table[][] = new int[10][20];
或者int[][] table = new int[10][20];
二维数组的赋值:
public class twod {
public static void main(String [] args) {
int t, i;
int table[] [] = new int [3] [4];
for(t = 0; t < 3; ++t) {
for (i = 0; i < 4; ++i) {
table [t] [i] = (t*4)+i+1;
System.out.println(table[t][i] + " ");
System.out.println(table [t] [i] + " ");
}
System.out.println();
}
}
}
二维数组的创建和声明
对于二维数组,你必须对于二维数组的一维进行大小分配,二维可以选择分配(可以确定值也可以不用写大小)。例如下面的代码,我们在声明的时候只给一维分配了大小,二维是我们手动分配的。
int table[][] = new int [3][];
table[0] = new int[4];
table[1] = new int[4];
table[2] = new int[4];
虽然在这种情况下单独分配第二维数组没有任何优势,但在其他情况下可能存在。 例如,单独分配维度时,不需要为每个索引分配相同数量的元素。 由于多维数组是作为数组的数组实现的,因此每个数组的长度都在您的控制之下。比如下面这段代码:
public class ragged {
public static void main(String [] args){
int riders[][]= new int[7][];
riders[0] = new int[10];
riders[1] = new int[10];
riders[2] = new int[10];
riders[3] = new int[10];
riders[4] = new int[10];
riders[5] = new int[2];
riders[6] = new int[2];
int i, j;
// 初始化
for(i = 0; i < 5; i++)
for (j = 0; j < 10; j++)
riders[i][j] = i + j + 10;
for(i = 5; i < 7; i++)
for(j = 0; j< 2; j++)
riders[i][j] = i + j + 10;
System.out.println("二维数组riders内容: ");
for(i = 0; i < 5; i++) {
for(j = 0; j < 10; j++)
System.out.println(riders[i][j] + " ");
System.out.println();
}
System.out.println();
for (i = 5; i < 7; i++) {
for(j=0; j < 2; j++)
System.out.println(riders[i][j] + " ");
System.out.println();
}
}
}
三维数组或者更多维数的数组
多维数组的声明语法:
type name []....[] = new type[size1][size2]....[sizeN];
比如,下面声明了一个三维数组:
int multidim[][][] = new int [4][10][3];
多维数组的初始化:
可以通过将每个维度初始化列表括在其自己的花括号集中来初始化多维数组。 例如,此处显示了二维数组的数组初始化的一般形式,语法糖如下:
type-specifier array_name[][] = {
{val, val, val,....val},
{val, val, val,....val},
...
{val,val, val, val....val}
};
具体例子:
public class square {
public static void main(String [] args) {
int sqrs[][] = {
{1, 1},
{2, 4},
{3, 9},
{4, 16},
{5, 25},
{6, 36},
{7, 49},
{8, 64},
{9, 81},
{10, 100}
};
int i, j;
for(i = 0; i < 10; i++) {
for(j = 0; j < 2; j++)
System.out.print(sqrs[i][j] + " ");
System.out.println();
}
}
}
输出:
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100
创建数组的其他方法:
创建了三个一维数组
int[] nums, nums2, nums3;
int num[], num2[], num3[];
下面主要说一下数组之间的指向问题,具体看下面的代码:
public class assignreff {
public static void main(String [] args) {
int i;
//声明两个int类型的数组,数组名分别是num1和nums2
int nums1[] = new int[10];
int nums2[] = new int[10];
//循环对数组进行赋值
for(i = 0; i < 10; i++)
nums1[i] = i;
for(i = 0; i < 10; i++)
nums2[i] = -i;
System.out.println("num1: ");
for(i = 0; i < 10; i++)
System.out.print(nums1[i] + " ");
System.out.println();
System.out.println("num2: ");
for(i = 0; i < 10; i++)
System.out.print(nums2[i] + " ");
System.out.println();
//nums2指向了nums1的地址,引用nums1的数组内容
nums2 = nums1;
System.out.println("num2指向num1的结果: ");
for(i = 0; i < 10; i++)
System.out.print(nums2[i] + " ");
System.out.println();
// 通过操作nums2来影响nums1,原因就是nums1和nums2现在指向同一个地址
nums2[3] = 99;
System.out.println("num1被影响后的结果: ");
for(i = 0; i < 10; i++)
System.out.print(nums1[i] + " ");
System.out.println();
}
}
输出结果:
num1:
0 1 2 3 4 5 6 7 8 9
num2:
0 -1 -2 -3 -4 -5 -6 -7 -8 -9
num2指向num1的结果:
0 1 2 3 4 5 6 7 8 9
num1被影响后的结果:
0 1 2 99 4 5 6 7 8 9
数组的length
属性:
数组有一个length
属性,这个属性表示数组中包含了多少个元素。下面是一个代码示例:
public class lengthdemo {
public static void main(String [] args) {
int list[] = new int[10];
int nums[] = {1, 2, 3 };
int table[][] = {
{1, 2, 3},
{4, 5},
{6, 7, 8, 9}
};
System.out.println("length of ist is " + list.length);
System.out.println("length of nums is " + nums.length);
System.out.println("length of table is " + table.length);
System.out.println("length of table[0] is " + table[0].length);
System.out.println("length of table[1] is " + table[1].length );
System.out.println("length of table[2] is " + table[2].length);
System.out.println();
// 使用length属性来初始化数组元素
for(int i = 0; i < list.length; i++)
list[i] = i * i;
System.out.println("here is a list: ");
// 使用length属性来打印数组元素
for(int i = 0; i< list.length; i++)
System.out.print(list[i] + " ");
System.out.println();
}
}
运行结果如下图所示:
length of ist is 10
length of nums is 3
length of table is 3
length of table[0] is 3
length of table[1] is 2
length of table[2] is 4
here is a list:
0 1 4 9 16 25 36 49 64 81
使用数组长度length
的时候,一定要注意:
对于二维数组,数组名.length
表示的是这个二维数组中有多少个一维数组,就拿上面的距离table.length=3
表示table
数组中只有三个数组。如果你想知道某个数组中有多少个元素,那么就应该使用table[index].length
。
public class Acopy {
public static void main(String [] args) {
int i;
int nums1[] = new int[10];
int nums2[] = new int[10];
for(i = 0; i < nums1.length; i++)
nums1[i] = i;
//将nums1的数组内容copy到nums2数组中
if(nums2.length >= nums1.length)
for(i = 0; i < nums1.length; i++)
nums2[i] = nums1[i];
for(i = 0; i < nums2.length; i++)
System.out.println(nums2[i] + " ");
}
}
for-each
循环(增强for
循环)
语法:for(type itr-var: collection) statement-block
type
指定类型,itr-var
指定迭代变量的名称,该变量将从集合中一次一个地从头到尾接收元素。 循环的集合由集合指定。 有各种类型的集合可以与for
一起使用,随着循环的每次迭代,集合中的下一个元素被检索并存储在itr-var
中。 循环重复直到获得集合中的所有元素。 因此,当在大小为N
的数组上进行迭代时,增强的用于以索引顺序从0到N-1
获得数组中的元素。
因为itr-var
接收的是来自集合collection
的元素,所以type
必须要和collection
存储元素的数据类型保持一致。
因此,当迭代数组的时候,type
的类型必须与数组的元素类型保持一致。
使用传统的for
循环来计算数组中值的总和。为了计算总和,从开始到结束按顺序读取nums
中的每个元素。 因此,整个序列以严格的顺序读取。 这是通过用循环控制变量i
手动索引nums
数组来完成的。 此外,必须明确指定循环控制变量的开始和结束值及其增量。
for-each
样式用于自动化前一个循环。 具体来说,它消除了建立循环计数器,指定起始值和结束值以及手动索引数组的需要。 相反,它会自动循环整个数组,从头到尾依次获得一个元素。
for-each
循环举例
public class foreach {
public static void main(String [] args) {
int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = 0;
// 使用for-each循环来打印每个元素值,并且求这些元素的总和
for(int x: nums) {
System.out.println("value is: " + x);
sum += x;
}
System.out.println("Summation: " + sum);
}
}
运行结果:
value is: 1
value is: 2
value is: 3
value is: 4
value is: 5
value is: 6
value is: 7
value is: 8
value is: 9
value is: 10
Summation: 55
可以for-each
循环中使用break
关键字来终止循环。例子如下:
for(int x: nums) {
System.out.println("Value is: " + x);
sum += x;
// 当x等于5的时候,循环就结束了
if(x == 5) break;
}
关于for-each
样式for
循环,有一点需要了解。 它的迭代变量是“只读”,因为它与底层数组有关。 迭代变量的赋值对底层数组没有影响。 换句话说,您不能通过为迭代变量分配新值来更改数组的内容
public class nochange {
public static void main(String [] args) {
int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for(int x : nums) {
System.out.print(x + " ");
//下面的这个操作是不会改变nums数组的内容的
x = x * 10;
}
System.out.println();
for(int x : nums)
System.out.print(x + " ");
System.out.println();
}
}
程序运行结果:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
增强版也适用于多维数组。 但请记住,在Java中,多维数组由数组组成。 这在迭代多维数组时很重要,因为每次迭代都会获得下一个数组,而不是单个元素。 此外,for循环中的迭代变量必须与所获得的数组类型兼容。 例如,在二维数组的情况下,迭代变量必须是对一维数组的引用。 通常,当使用for-each迭代N维的数组时,获得的对象将是N-1维的数组。 要理解其含义,请考虑以下程序。 它使用嵌套for循环以行顺序从第一个到最后一个获取二维数组的元素.
public class foreach2 {
public static void main(String [] args){
int sum = 0;
int nums[][] = new int[3][5];
//给nums数组赋值
for (int i = 0; i < 3; i++)
for(int j = 0; j < 5; j++)
nums [i][j] = (i + 1) * (j + 1);
// 使用for-each来打印每个元素和总和
//这里需要特别注意int x[] :nums
for(int x[] : nums) {
for(int y: x) {
System.out.println("Value is: " + y);
sum += y;
}
}
System.out.println("Summation: " + sum);
}
}
运行结果:
Value is: 1
Value is: 2
Value is: 3
Value is: 4
Value is: 5
Value is: 2
Value is: 4
Value is: 6
Value is: 8
Value is: 10
Value is: 3
Value is: 6
Value is: 9
Value is: 12
Value is: 15
Summation: 90