四、数组操作时常见的问题
小白在写程序的时候,可能经常会面临报错提醒的问题,这个时候不要慌,也没必要烦躁,因为烦躁也没用。我们能做的正面动作,就是尽量把这些出现的错误提示记录下来,这样会大大节省以后找bug的时间,也是逐渐向大神晋级的垫脚砖。
(一)、数组索引越界
先写一段代码:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int [] cc={1,2,3};
System.out.println(cc[3]);
}
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at demon.main(demon.java:6)
Process finished with exit code 1
Array Index Out Of Bounds Exception
数组索引越界,因为访问了不存在的索引。
在这段代码中,索引有3个,分别是0,1,2,没有索引为3的元素。
这种感觉,就相当于你在一栋只有三户的公寓里(101,102,103),非要找第四户(104),结果肯定找不到。
(二)、空指针异常
来看一段代码:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int [] cc={1,2,3};
cc=null;
System.out.println(cc[2]);
}
}
Exception in thread "main" java.lang.NullPointerException
at demon.main(demon.java:7)
Process finished with exit code 1
Null Pointer Exception
空指针异常,因为数组已经不再指向堆内存,而你还用数组名访问元素。
在这段代码中,本来int [] cc后,系统在堆内存里new出一块空间,并分配了地址值给int [] cc,但是由于你强行把null 赋值给
int [] cc,导致该地址值丢失。
至于指针是啥,我后面会讲,现在请不要考虑这么费脑子的问题。
这里报错的感觉就好像是,一栋公寓,本来被政府分配好了一个名字——恒远地产,结果开发商不喜欢,非要改成自己喜欢的——翠花大楼,导致某度地图上只能通过翠花大楼找到该公寓,而找不到恒远地产。
五、数组的常见操作
(一)、数组遍历
①、定义
所谓数组遍历,就是依次输出数组中的每一个元素。
如此说来,这不就是上一篇里咱们经常执行的动作吗?定义一个数组,然后依次输出其中的每一个元素。
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int [] cc={13,34,55,67,88};
//输出元素
System.out.println(cc);
System.out.println(cc[0]);
System.out.println(cc[1]);
System.out.println(cc[2]);
System.out.println(cc[3]);
System.out.println(cc[4]);
}
}
[I@1b6d3586
13
34
55
67
88
Process finished with exit code 0
虽然这种方法可行,但作为一个合格的懒惰的程序员,难道不觉得代码的重复率太高了吗?
想一个办法,既能降低代码重复率,又能达到题目要求。
提示:用之前学过的一种语句。
②、单个数组的遍历
????????
答案公布:可以使用循环语句来实现。
比如我们可以这样写:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int [] cc={13,34,55,67,88};
//循环语句
for(int x=0;x<5;x++){
System.out.println(cc[x]);
}
}
}
13
34
55
67
88
Process finished with exit code 0
是不是清爽了许多,也增加了代码的可读性。
但这里面还有一个问题,即 x的范围是如何得知的?即,x<5的这个数字是怎么界定的?
数出来的……吗?
o( ̄▽ ̄)d o( ̄▽ ̄)d o( ̄▽ ̄)d
给你点个赞,大聪明!
那麻烦下面这个数组,也请你帮我数一数:
int[] cc1={1,3,4,6,8,44,55,77,33,66,73,2,33,8,9,54,5,26,45,76,87,98,22,23,24,25,27,28,82,84,83,82,81,80,36,37,38,39,83,56,57,58,59};
很显然,总有一些数组,里面的元素是不能靠数出来的。所以这时,数组也很贴心的给我们提供了一个属性,length,专门用于获取数组的长度,具体格式如下:
数组名.length
所以上面例子里的数组长度,就可以这样得出:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int[] cc1={1,3,4,6,8,44,55,77,33,66,73,2,33,8,9,54,5,26,45,76,87,98,22,23,24,25,27,28,82,84,83,82,81,80,36,37,38,39,83,56,57,58,59};
//length
System.out.println(cc.length);
}
}
43
Process finished with exit code 0
就是说,这个数组里面有43个元素,因此,之前的例子可以这样改写:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int [] cc={13,34,55,67,88};
//循环语句
for(int x=0;x<cc.length;x++){
System.out.println(cc[x]);
}
}
}
③、多个数组的遍历
以上是针对单个数组的遍历,但当我们要对多个数组进行遍历时,同样面临代码重复率高的问题,这时同样需要用方法进行改进。
下面,我要对数组CC和CC1进行遍历。
首先明确两点:
第一、返回值类型——void;
第二、参数列表——int [] cc和 int [] cc1
代码如下所示:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int[] cc = {13, 34, 55, 67, 88};
int[] cc1 = {1, 3, 4, 6, 8, 44, 55, 77, 33, 66, 73, 2, 33, 8, 9, 54, 5, 26, 45, 76, 87, 98, 22, 23, 24, 25, 27, 28, 82, 84, 83, 82, 81, 80, 36, 37, 38, 39, 83, 56, 57, 58, 59};
shuzu(cc);
shuzu(cc1);
}
//方法
public static void shuzu(int[] cc) {
for (int x = 0; x < cc.length; x++) {
System.out.println(cc[x]);
}
}
}
13
34
55
67
88
1
3
4
6
8
44
55
77
33
66
73
2
33
8
9
54
5
26
45
76
87
98
22
23
24
25
27
28
82
84
83
82
81
80
36
37
38
39
83
56
57
58
59
Process finished with exit code 0
(二)、数组获取最值
①、定义
所谓获取最值,就是获取数组中的最大值或最小值
假设现在有一个数组:
int[] cc={23,76,45,65,11,86,51};
要求获取该数组中的最大值和最小值。
应该怎么做呢。
正常思维下,首先应找到一把标尺,然后将数组中的每一个元素,依次与其进行对比,找到最大和最小值。
但是这个标尺不能随便找,最简单有效的方法是,从数组里的元素里找。
比如我们可以将23这个元素作为临时标尺,比他大的留下,成为新标尺,比他小的扔回数组,以此类推,直到找出最大值。
最小值也如法炮制,只不过反过来比较。
之所以不从外部寻找标尺,是因为可能会出现以下两种情况:
第一、找到的标尺比数组里所有元素都大;
第二、找到的标尺比数组里所有元素都小。
这样虽然能找到最大值或最小值,但这个值不属于该数组,答案无意义。
捋清思路后,关于数组获取最值的步骤就呼之欲出了。
②、步骤
第一步:定义一个数组,并对该数组的元素进行静态初始化;
第二步:从数组中任意找一个元素作为参照物(一般取第一个),默认该元素为最大值;
第三步:遍历其他元素,并依次和其他元素进行比较,如果大于参照物,就留下作为新参照物,若小,原参照物不变;
第四步:当数组内所有元素都参与比较后,参照物里面保存的元素就是最大值。
求数组 int[] cc={23,76,45,65,11,86,51}的最值
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int[] cc={23,76,45,65,11,86,51};
//用第一个元素(编码为0)作为参照物:
int max=cc[0];
//遍历其他数组:
for(int x=1;x<cc.length;x++){
if (cc[x] >max){
max=cc[x];
}
}
System.out.println("max:"+max);
}
}
max:86
Process finished with exit code 0
由于在以后的码农生涯中,我们会更多接触到方法这步分,所以上面的题,又可以改写为:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int[] cc = {23, 76, 45, 65, 11, 86, 51};
//调用
int max = getmax(cc);
System.out.println("max:"+max);
}
//方法改写
public static int getmax(int[] cc) {
//用第一个元素(编码为0)作为参照物:
int max=cc[0];
//遍历其他数组:
for (int x = 1; x < cc.length; x++) {
if (cc[x] > max) {
max = cc[x];
}
}
return max;
}
}
max:86
Process finished with exit code 0
求最小值同理,只需要把max改成min就OK,具体代码此处略。
(三)、数组元素逆序
①、定义
所谓数组元素逆序,就是把原数组中的起始元素和末尾元素进行互换,实现数组元素倒序存放的操作。比如数组12345,变成数组54321
②、步骤
根据上文中给出的定义,数组元素逆序的大体步骤,也就呼之欲出了。
第一步:定义一个数组,并进行静态初始化;
第二步:把索引为0的元素,和索引为数组名.length-1的元素进行交换;
把索引为1的数据,和索引为数组名.length-2的数据进行交换……
第三步:只需要交换到数组名.length/2的长度即可。
假设现在有一个数组:
int[] cc={2,13,23,55,56,7,18,77};
问题:请对该数组进行逆序操作。
根据前面总结的步骤,一般人的思路可能是这样:
//第一次交换:
int temp=cc[0];
cc[0]=cc[cc.length-1];
cc[cc.length-1]=temp;
//第二次交换:
int temp=cc[1];
cc[1]=cc[cc.length-2];
cc[cc.length-2]=temp;
//第三次交换:
int temp=cc[3];
cc[3]=cc[cc.length-3];
cc[cc.length-3]=temp;
………………………………………………
思路很清晰,但不会有人想这样一只写下去的。
通过仔细观察,上面代码中的cc.length-1、cc.length-2、cc.length-3可以改写为:
cc.length-1 = cc.length-1-0
cc.length-2 = cc.length-1-1
cc.length-3 = cc.length-1-2
那么这道题的代码,用方法写成:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int[] cc={2,13,23,55,56,7,18,77};
//调用
System.out.println("顺序:");
bianli(cc);
System.out.println("逆序:");
nixu(cc);
bianli(cc);
}
//遍历
public static void bianli(int[] cc) {
for (int x = 0; x < cc.length; x++) {
System.out.println(cc[x]);
}
}
//逆序
public static void nixu(int[] cc) {
for (int x = 0; x < cc.length/2; x++) {
int temp=cc[x];
cc[x]=cc[cc.length-1-x];
cc[cc.length-1-x]=temp;
}
}
}
顺序:
2
13
23
55
56
7
18
77
逆序:
77
18
7
56
55
23
13
2
Process finished with exit code 0
这道题的代码,有很多种写法,下面再介绍一种:
public class demon {
public static void main(String[] args) {
//定义第一个数组:
int[] cc={2,13,23,55,56,7,18,77};
//调用
System.out.println("顺序:");
bianli(cc);
System.out.println("逆序:");
nixu(cc);
bianli(cc);
}
//遍历
public static void bianli(int[] cc) {
for (int x = 0; x < cc.length; x++) {
System.out.println(cc[x]);
}
}
//逆序
public static void nixu(int[] cc) {
for (int start = 0, end=cc.length-1;start<=end;start++,end--) {
int temp=cc[start];
cc[start]=cc[end];
cc[end]=temp;
}
}
}
关于这道题,其实还有别的写法,但我实在懒得动脑筋了,大家可以自己开发,在此就不一一赘述。
Thanks♪(・ω・)ノ 观看
部分图片来自网络,侵权立删