Java的一维数组真的有你想象得那么简单吗?

一、前言

C: 循环是 Java 语法上的一个小坎儿,跨过来之后,我们马上就要从语法入门上岸了。

本篇,要带着大家学习 Java 语法入门的一个进阶知识,数据结构:数组。

在目前已学的 Java 知识中,如果我们想利用程序存储一个成绩数据,如下所示即可:

// 声明一个变量,存储成绩
double score = 90;

但当我们要存储5个、10个,甚至更多成绩数据时,变量这种单一存储的方式的效率将变得低下:

double score1 = 90;
double score2 = 80;
double score3 = 70;
double score4 = 60;
double score5 = 59;
...

所以我们需要一种更为先进的,能够同时存储多个数据的存储方式。

二、数据结构概述

在开始介绍数组前,我们先来普及一下数据结构的基本概念。

数据结构是计算机存储、组织数据的方式。

数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。[1]

数据结构有很多种,一般来说,按照数据的逻辑结构对其进行简单的分类,包括线性结构(线性表)和非线性结构(非线性表)两类。[2]

  1. 线性表(Linear List),就是表中各个结点具有线性关系。数据排成像一条线一样的结构。[3]

    常见的线性表数据结构有:数组,队列、栈、链表等。

    线性表
  2. 非线性表,就是表中各个结点之间具有多个对应关系。[2]

    常见的非线性表数据结构有:树、图等。

    非线性表

数据结构在计算机系是一门非常重要的基础学科。数据结构产生的目的,就是为了让计算机能够以更加简单、高效、便捷的方式来 存储使用 数据。

三、数组概述

数组是线性数据结构中最为基础,最为典型的一种顺序型结构。它用一组 连续的内存空间 ,来存储一组具有 相同类型 的数据。[3]

我们拿数组和变量对比一下:

  • 变量:就是在内存中划出一块合适的空间。
  • 数组:就是在内存中划出一串连续的空间。

四、数组组成

我们也再拿变量的组成要素和数组来对比一下:

变量 数组
变量数据类型 数组元素的类型:在数组中存储的数据都必须是相同的数据类型
变量名 数组名:用于区分不同的数组,命名规范同变量名一致
变量值 数组元素:在数组中存储的数据
数组下标/索引:数组是一串连续的空间,每个空间都有其相应的 "序号",从0开始计数

数组的下标是由数组的长度(容量)决定的,数组的长度为5,那么数组的下标就是0、1、2、3、4。数组长度一经定义,就不可再变。

五、数组定义

了解了数组的组成,接下来我们亲自定义一个数组来使用,在 Java 中,数组的定义方式很灵活,查老师带你认识三种比较常见的定义方式。

1. 方式一

// 声明一个长度为5的用来存储double类型数据的数组
// 语法:数据类型[] 数组名 = new 数据类型[数组长度];
double[] scores = new double[5];

这种是最传统的数组定义方式了,通过指定好数据类型及数组长度,来划定好一串连续的空间。

定义好数组后,如果要向数组中存储数据,需要我们借助数组名和数组下标来进行。

// 数组赋值(存储/更新)
// 语法:数组名[下标] = 元素值;
// 把90赋值给数组的第一个空间
scores[0] = 90;
scores[1] = 80;
scores[2] = 70;
scores[3] = 60;
scores[4] = 50;
// 【小心点】下标是从0开始计数,极其容易出现超出数组容量范围的使用
// 问题是它在编译期不报错,在运行时才报错(数组越界异常)
// scores[5] = 40;  

存储好了数据,在使用的时候也是需要借助数组名和数组下标来进行。

// 语法:数组名[下标]
System.out.println(scores[0]); // 90.0

① 数组的默认值

定义好数组之后,如果你不进行任何赋值就直接来使用,会发现数组的空间竟然都有值?

这是因为在数组声明时,会伴随一个初始化动作,初始化动作就是对数组每一个空间,根据数据类型来设置一个默认值的过程。

  • byte、short、int、long:默认值为0
  • float、double:默认值为0.0
  • boolean:默认值为false
  • char:默认值为一个空格(\u0000)
double[] dArr = new double[5];
System.out.println(dArr[0]); // 0.0

int[] iArr = new int[5];
System.out.println(iArr[0]); // 0

boolean[] bArr = new boolean[5];
System.out.println(bArr[0]); // false

char[] cArr = new char[5];
System.out.println(cArr[0]); // 一个空格,\U0000

② 动态赋值

在方式一的赋值中,学习过循环的我们,很快就能发现一些重复性,有规律性的操作。

赶快来用循环优化一下吧。

思路分析:

  1. 根据效果图分析,为行级规律,采用单层循环
  2. 循环要素
    1. 循环条件: < 数组长度
    2. 循环操作: 数组名[循环变量] = 输入的元素值;
  3. 固定次数循环,采用 for 循环
  4. 检查循环是否可以正常退出
// 声明数组,存储5个同学成绩
double[] scores = new double[5];

// 动态录入学生成绩
Scanner input = new Scanner(System.in);
// 数组名.length 可以获取数组的容量
for (int i = 0; i < scores.length; i++) {
    System.out.print("请输入第" + (i+1) + "个学生成绩:");
    scores[i] = input.nextDouble();
}

System.out.println("第3名同学成绩:" + scores[2]);

2. 方式二

// 声明数组时赋值
// 语法:数据类型[] 数组名 = {元素1, 元素2, ....};
double[] scores = {90, 80, 70, 60, 50};

这种定义方式,非常适合快速定义一个有值数组的情况。不需要指定长度,数组会根据元素的数量指定好长度。

定义时直接赋值,还可以写成这样:

// 声明数组时赋值
// 语法:数据类型[] 数组名 = new 数据类型[] {元素1, 元素2, ...};
// 注意:有[],也不需要指定数组长度,它是空的
double[] scores1 = new double[] {90, 80, 70, 60, 50};

肯定有同学会问:这种定义方式,和上方几乎一模一样,再学习有什么用?

别着急,后续在一些篇章的场景中,这种写法可能是你使用数组唯一的、更好的选择,相信查老师。

五、数组遍历

掌握了三种数组的定义方式之后,我们马上就要开始进行数组的使用练习了,但在此之前,我们再来介绍一下数组的遍历方式,这是数组使用的常见操作。

遍历: 将数组中的元素挨个取出来的过程,就叫遍历。

因为取出来的过程是一个重复、有规律性的操作,所以循环是自然少不了的。

1. 循环下标遍历

最常见的遍历方式,就是通过循环数组的下标,来进行遍历。刚才我们动态赋值就是用的这种循环规律。

// 定义数组
double[] scores = {90, 80, 70, 60, 50};

// 循环下标的所有值,来遍历出数组的每一个元素
for (int i = 0; i < scores.length; i++) {
    // 数组名[循环下标]
    System.out.println(scores[i]);
}

2. forEach遍历

除此之外,还有一种较为特别的方式:使用 forEach 循环(俗称增强 for 循环)遍历。这种遍历方式,主要强调的就是将数组中的元素挨个取出来,每次都临时存储到一个变量中。

// 定义数组
double[] scores = {90, 80, 70, 60, 50};

// for (数组元素数据类型 变量名 : 要遍历的数组名)
// score 是在循环中,临时存储每一个元素的变量
for (double score : scores) {
    System.out.println(score);
}

增强 for 循环遍历方式与循环下标遍历相比,在使用时更简单,但前期可能不太好理解,如果实在理解不好的话,就先用循环下标的遍历方式。

而且有些时候,我们需要下标来作为辅助计算因素时,采用循环下标遍历更方便。

六、数组使用

光说不练假把式,接下来我们通过数组来解决一些需求问题。

1. 打印消费记录

案例需求:根据效果图实现,会员消费清单打印。

// 定义数组,存储本月消费记录
double[] records = new double[5];

// 动态赋值
Scanner input = new Scanner(System.in);
System.out.println("请输入会员本月的消费记录:");
for (int i = 0; i < records.length; i++) {
    System.out.print("请输入第" + (i+1) + "笔购物金额:");
    records[i] = input.nextDouble();
}

System.out.println();

// 定义变量,存储消费总金额
double sum = 0;
System.out.println("序号\t\t金额(元)");
for (int i = 0; i < records.length; i++) {
    System.out.println((i+1) + "\t\t" + records[i]);
    sum += records[i];
}
System.out.println("总金额\t\t" + sum);

2. 猜数字

案例需求:有一个数列:8,4,2,1,23,344,12。

  1. 循环输出数列的值
  2. 求数列中所有数值的和
  3. 猜数游戏: 从键盘中任意输入一个数据,判断数列中是否包含此数

两种遍历数组的方式都用用。

// 定义一个数列
int[] numArr = {8, 4, 2, 1, 23, 344, 12};

// 1.循环输出数列的值  
System.out.println("数列中的值有:");
for (int num : numArr) {
    System.out.println(num);
}
System.out.println("-------------------------");

// 2.求数列中所有数值的和  
int sum = 0;
for (int i = 0; i < numArr.length; i++) {
    sum += numArr[i];
}
System.out.println("数列的所有数值的和为:" + sum);
System.out.println("-------------------------");

// 3.猜数游戏:从键盘中任意输入一个数据,判断数列中是否包含此数  
// >从键盘中任意输入一个数据
Scanner input = new Scanner(System.in);
System.out.print("请输入一个数值:");
int num = input.nextInt();

// >判断数列中是否包含此数  
// 标志位
boolean flag = false; // 假设数列中不包含此值
for (int i = 0; i < numArr.length; i++) {
    if (numArr[i] == num) {
        flag = true;
        break;
    } 
}
// 判断标志位
if (flag) {
    System.out.println("数列中包含此值!");
} else {
    System.out.println("数列中不包含此值!");
}

3. 求最高分

案例需求:从键盘输入本次Java考试五位学生的成绩,求考试成绩最高分。

思路提示:打擂台。

武侠电视剧中,经常上演 "文无第一,武无第二" 的戏码。比武招亲或武林大会:最开始有一个守擂的,随后有各大侠士争相对抗,赢的就成为新的守擂者,等结束剩下的就是最强的。

//  1.从键盘输入本次 Java 考试五位学生的成绩
double[] scoreArr = new double[5]; 

Scanner input = new Scanner(System.in);
for (int i = 0; i < scoreArr.length; i++) {
    System.out.print("请输入第" + (i + 1) + "位学生的成绩:");
    scoreArr[i] = input.nextDouble();
}

// 2.求考试成绩最高分
// 假定一个最高分(从要比较的数据中假定一个数据)
double max = scoreArr[0];
for (double score : scoreArr) {
    // 如果挨个比较过程中,有比max还大的值
    // 那就将max的值换为最新的数据
    if (score > max) {
        max = score;
    }
}
System.out.println("最高分为:" + max);

4. 求最低价

案例需求:输入4家手机店的 OnePlus 8T 价格,输出哪家店价格最低及最低手机价格。

// 定义数组,存储4家店手机价格
double[] prices = new double[4];

// 动态赋值
Scanner input = new Scanner(System.in);
System.out.println("请输入4家店的 OnePlus 8T 手机价格:");
for (int i = 0; i < prices.length; i++) {
    System.out.print("第" + (i+1) + "家店的价格:");
    prices[i] = input.nextDouble();
}

// 定义变量,假定最低价格为第1家
double min = prices[0];
// 定义变量,存储最低价格是第几家
int minStore = 1;
for (int i = 0; i < prices.length; i++) {
    // 如果有比最低价格还低的
    if (prices[i] < min) {
        // 更换最低价格
        min = prices[i];
        // 更换最低价格店铺
        minStore = i + 1;
    }
}
System.out.println("第" + minStore + "家价格最低,价格为:" + min);

七、总结

如果觉得本文对你有帮助的话,请你也不要吝啬你的赞,你们的支持是对我最大的鼓励。今天的Java知识分享就到这里!点关注,不迷路,关注程序员曾曾,每天分享不同的Java基础知识,想要知道更多Java基础知识和面试答案的我这边整理了一个我自己的GitHub仓库:Java小白修炼手册,大家如果有需要可以自行查看

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容