目录
变量:存储数据的空间(装数据的容器),变量中只能存储一个数据
数组:存储数据的空间(装数据的容器),数组中可以存储多个相同类型的数据
数组的组成部分
- 标识符:数组的名称,取名原则与变量一样
- 数组元素:数组中存储的每一个数据称之为数组元素
- 元素下标:因为数组在内存中是连续的空间,所以会给数组里的元素按照顺序进行编号,编号从0开始,我们把这个编号叫下标(索引)
- 元素类型:描述的是数组中的元素类型
声明数组
数据类型[] 数组名; 或者 数据类型 数组名[];
int[] nums ;
String[] strs;
分配空间
告诉你我这个数组里能装多少个元素(数据)
数组名 = new 数据类型[元素个数];
nums = new int[5];
strs = new String[3];
赋值
将数据存储到数组中
数组名[下标] = 数据;
nums[0] = 99;
nums[1] = 83;
nums[2] = 78;
nums[3] = 88;
nums[4] = 66;
//nums[5] = 100; //ArrayIndexOutOfBoundsException:数组下标越界
ArrayIndexOutOfBoundsException:数组下标越界
操作数据:通过数组名[下标]来操作数据
S
ystem.out.println(nums[0]); //99
System.out.println(nums[1]); //83
nums[1]+=50; //nums[1]=nums[1]+50;
System.out.println(nums[1]);
声明数组、分配空间合并写
数据类型[] 数组名 = new 数据类型[数组长度]; 或 数据类型 数组名[] = new 数据类型[数组长度]
声明一个长度为3的double类型的数组
double[] nums = new double[3];
赋值,通过数组名[下标]给元素赋值,如果没有给元素赋值,系统会给元素赋予一个默认值
nums[0] = 12.5;
nums[1] = 22.5;
输出数组里的每一个元素
System.out.println(nums[0]);//12.5
System.out.println(nums[1]);//22.5
System.out.println(nums[2]);//0.0
默认值
char[] chs = new char[2]; System.out.println(chs[0]);
//char类型数组元素默认值是空格
boolean[] bools = new boolean[2];
System.out.println(bools[0]);//false
声明数组、分配空间、赋值合并写
方法一:数据类型[] 数组名 = new 数据类型[ ]{数据1,数据2,…,数据n};
方法二:数据类型 数组名[] = new 数据类型[ ]{数据1,数据2,…,数据n};
注意:{}前面那个[ ]里不能写长度,写了就报错**
声明一个长度为3的数组,并向数组里赋值 “hello” “java” “word”
String[] strs = new String[] { "hello", "java", "word" };
操作数据
System.out.println(strs[0]);
System.out.println(strs[1]);
System.out.println(strs[2]);
声明数组、分配空间、赋值合并写的简写方式
方式一:数据类型[] 数组名 = {数据1,数据2,…,数据n};
方式二:数据类型 数组名[] = {数据1,数据2,…,数据n};
声明一个char类型的数组,并向数组里赋值 ‘a’ ‘b’ ‘c’ ‘d’
char[] chs = { 'a','b','c','d'};
System.out.println(chs[0]);// a
//System.out.println(chs[6]); //ArrayIndexOutOfBoundsException
练习1:声明一个长度为4的int类型的数组,使用键盘输入给数组每个元素赋值。遍历输出数组。
package cn.bdqn.demo01;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 声明一个长度为4的int类型的数组
int[] nums = new int[4];
// 使用键盘输入给数组每个元素赋值
// System.out.println("请输入数组里的第1个元素值:");
// nums[0]=sc.nextInt();
// System.out.println("请输入数组里的第2个元素值:");
// nums[1]=sc.nextInt();
// System.out.println("请输入数组里的第3个元素值:");
// nums[2]=sc.nextInt();
// System.out.println("请输入数组里的第4个元素值:");
// nums[3]=sc.nextInt();
//上述赋值操作,可以使用循环来实现
for(int i =0;i<4;i++){
System.out.println("请输入数组里的第"+(i+1)+"个元素值:");
nums[i]=sc.nextInt();
}
System.out.println("数组中的元素依次是:");
//输出数组里的每一个元素值
// System.out.println(nums[0]);
// System.out.println(nums[1]);
// System.out.println(nums[2]);
// System.out.println(nums[3]);
//遍历数组:将数组中元素按照下标顺序依次输出
for(int i = 0;i<4;i++){
System.out.println("数组第"+(i+1)+"个元素是:"+nums[i]);
}
}
}
遍历以及length的灵活运用
遍历
数据元素是怎样在内存中存放的?
主要有2种存储方式:
1、顺序存储,Random Access(Direct Access):
这种方式,相邻的数据元素存放于相邻的内存地址中,整块内存地址是连续的。可以根据元素的位置直接计算出内存地址,直接进行读取。读取一个特定位置元素的平均时间复杂度为O(1)。正常来说,只有基于数组实现的集合,才有这种特性。Java中以ArrayList为代表。
2、链式存储,Sequential Access:
这种方式,每一个数据元素,在内存中都不要求处于相邻的位置,每个数据元素包含它下一个元素的内存地址。不可以根据元素的位置直接计算出内存地址,只能按顺序读取元素。读取一个特定位置元素的平均时间复杂度为O(n)。主要以链表为代表。Java中以LinkedList为代表。
每个遍历方法的实现原理是什么?
- 传统的for循环遍历,基于计数器的:
遍历者自己在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到最后一个元素后,停止。主要就是需要按元素的位置来读取元素。 - 迭代器遍历,Iterator:
每一个具体实现的数据集合,一般都需要提供相应的Iterator。相比于传统for循环,Iterator取缔了显式的遍历计数器。所以基于顺序存储集合的Iterator可以直接按位置访问数据。而基于链式存储集合的Iterator,正常的实现,都是需要保存当前遍历的位置。然后根据当前位置来向前或者向后移动指针。 - foreach循环遍历:
根据反编译的字节码可以发现,foreach内部也是采用了Iterator的方式实现,只不过Java编译器帮我们生成了这些代码。
各遍历方式对于不同的存储方式,性能如何?
- 传统的for循环遍历,基于计数器的:
因为是基于元素的位置,按位置读取。所以我们可以知道,对于顺序存储,因为读取特定位置元素的平均时间复杂度是O(1),所以遍历整个集合的平均时间复杂度为O(n)。而对于链式存储,因为读取特定位置元素的平均时间复杂度是O(n),所以遍历整个集合的平均时间复杂度为O(n2)(n的平方)。
ArrayList按位置读取的代码:直接按元素位置读取。 - 迭代器遍历,Iterator:
那么对于RandomAccess类型的集合来说,没有太多意义,反而因为一些额外的操作,还会增加额外的运行时间。但是对于Sequential
Access的集合来说,就有很重大的意义了,因为Iterator内部维护了当前遍历的位置,所以每次遍历,读取下一个位置并不需要从集合的第一个元素开始查找,只要把指针向后移一位就行了,这样一来,遍历整个集合的时间复杂度就降低为O(n);
length的写法:
数组名.length自动获取该数组的长度。
遍历输出以下数组:
package cn.bdqn.demo01;
public class Demo05 {
public static void main(String[] args) {
//遍历以下数组
int[] nums = {11,23,45,6,78,96,88,73,62,12,10,36,55,99,45,66,19,64,13};
//获取数组中元素的个数: 数组名.length;
int length =nums.length;
System.out.println("数组中元素个数:"+length);
//遍历数组
for(int i =0;i<nums.length;i++){
System.out.println(nums[i]);
}
}
}
练习一:
需求:
1)根据班级人数来创建数组
2)将每个学生的成绩存入到数组中
3)求班级学生成绩总和
4)求班级学生平均成绩
package cn.bdqn.demo02;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 1)根据班级人数来创建数组:班级人数有多少个,数组的长度为就为多少
System.out.println("请输入班级人数:");
int num = sc.nextInt();
// 根据班级人数来创建一个存放学生成绩的数组
double[] scores = new double[num];
// 声明一个变量sum用来累加所有学生的成绩
double sum = 0;
// 2)将每个学生的成绩存入到数组中
for (int i = 0; i < scores.length; i++) {
System.out.println("请输入第" + (i + 1) + "个学生的成绩:");
scores[i] = sc.nextDouble();
// 3)求班级学生成绩总和
sum += scores[i];
}
// 4)求班级学生平均成绩
double avg = sum / num;
System.out.println("该班学生成绩总和:" + sum);
System.out.println("该班学生平均成绩:" + avg);
}
}
增强for循环
语法结构:
for(数据类型 变量名:数组名或集合名){
对变量进行操作的代码
}
执行规律:
将数组或者集合中的元素依次取出来存入到变量中,然后操作这个变量就等同于操作数组或者集合中的数据
注意:增强for循环的执行效率比普通for循环高
增强for循环遍历数组的运用:
public static void main(String[] args) {
int[] nums = { 11, 22, 33, 44, 55 };
// 遍历数组
System.out.println("-----普通for循环遍历数组-----");
for (int i = 0; i < nums.length; i++) {
System.out.println(nums[i]);
}
System.out.println("-----增强for循环遍历数组-----");
for(int a : nums){
System.out.println(a);
}
System.out.println("------------------------");
for (int i : nums) {
i+=100;
System.out.println(i);
}
声明变量并将变量直接输出
int num = 10;
System.out.println(num); // 10
数组是一个引用数据类型,直接输出数组名,输出的是数组在内存中的地址值
int[] nums = { 11, 22, 33, 44, 55 };
System.out.println(nums); //[I@4eafccbe
练习二:
有一个数列:8,4,2,1,23,344,12
循环输出数列的值
求数列中所有数值的和
猜数游戏:从键盘中任意输入一个数据,判断数列中是否包含此数
package cn.bdqn.demo02;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
int[] num = {8,4,2,1,23,344,12};
//循环输出数列的值
for (int i : num) {
System.out.println(i);
}
//求数列中所有数值的
//声明一个变量sum用来累加数组中所有元素之和
int sum = 0;
for (int i : num) {
sum+=i;
}
System.out.println("数组中所有元素之和为:"+sum);
//猜数游戏:从键盘中任意输入一个数据,判断数列中是否包含此数
Scanner sc = new Scanner(System.in);
System.out.println("请任意输入一个整数:");
int guess = sc.nextInt();
for (int i : num) {
if(i==guess){
System.out.println("数组中包含你猜测的数据");
break;
}
}
}
}
练习三:
有一个数列:8,4,2,1,23,344,12
猜数游戏:从键盘中任意输入一个数据,判断数列中是否包含此数,如果包含此数,输出此数在数组中的位置(下标),如果不包含此数,则输出数组中不包含此数
package cn.bdqn.demo02;
import java.util.Scanner;
public class Demo05 {
public static void main(String[] args) {
int[] num = { 8, 4, 2, 1, 23, 344, 12 };
Scanner sc = new Scanner(System.in);
System.out.println("请任意输入一个整数:");
int guess = sc.nextInt();
//声明一个变量,用来统计比较的次数
int count = 0;
for (int i = 0; i < num.length; i++) {
//判断你猜测的数据在不在数组
if(guess!=num[i]){
count++;
if(count==num.length){
System.out.println("你猜测的数据不在此数组中");
}
}else{
System.out.println("你猜测的数据在此数组中,下标为:"+i);
//只要猜测的数据在数组中,后续就不需要再进行比较,退出整个循环
}
}
}
}
获取数组中的最大值或者最小值
思想:
1)先假设数组中的第1个元素(下标为0)为最大值
2)依次将数组中后面的元素与这个最大值进行比较,如果比这个最大值还要大,取代它称为新的最大值
3)比较到最后一个元素,就可以获取这个数组中的最大值
package cn.bdqn.demo03;
public class Demo01 {
public static void main(String[] args) {
int[] nums = { 56, 60, 78, 42, 311, 88, 12 };
// 1)先假设数组中的第1个元素(下标为0)为最大值
int max = nums[0];
// 2)依次将数组中后面的元素与这个最大值进行比较,如果比这个最大值还要大,取代它称为新的最大值
// if(nums[1]>max){
// max=nums[1];
// }
//
// if(nums[2]>max){
// max = nums[2];
// }
//
// if(nums[3]>max){
// max = nums[3];
// }
//
// if(nums[4]>max){
// max = nums[4];
// }
//
// if(nums[5]>max){
// max = nums[5];
// }
//
// if(nums[6]>max){
// max = nums[6];
// }
for (int i = 0; i < nums.length; i++) {
if (nums[i] > max) {
max = nums[i];
}
}
System.out.println("数组中的最大值:" + max);
// 获取最小值思路与获取最大值思路一样
// 假设数组中第一个元素为最小值
int min = nums[0];
// 依次将数组中的元素取出来与这个最小值进行比较,如果元素值比这个最小值还小,就成为新的最小值,比较到最后一个元素,就可以得到数组中的最小值
for (int i = 0; i < nums.length; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
System.out.println("数组中的最小值:" + min);
}
}
练习四:
有一组学员的成绩{99,85,82,63, 60},已经是按降序排列。 要增加一个学员的成绩,将它插入成绩序列,并保持降序
思想:
1)声明一个长度比原来数组长度大1的数组
2)将原来数组里元素按照顺序存入到新的数组中
3)使用Scanner类获取你要增加的学员成绩
4)通过循环比较获取增加的学员成绩的插入位置
5)从插入元素插入位置开始及之后的元素依次往后移动一位(从最后一个元素开始,倒着移动)
6)将要插入的成绩存储到插入位置
package cn.bdqn.demo03;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
// 创建Scanner类对象
Scanner sc = new Scanner(System.in);
int[] scores = { 99, 85, 82, 63, 60 };
// 1)声明一个长度比原来数组长度大1的数组
int[] newScores = new int[scores.length + 1];
// 2)将原来数组里元素按照顺序存入到新的数组中
// newScores[0]=scores[0];
// newScores[1]=scores[1];
// newScores[2]=scores[2];
// newScores[3]=scores[3];
// newScores[4]=scores[4];
// 使用循环来实现上述赋值操作,赋值结束后,新数组元素是[99,85,82,63,60,0]
for (int i = 0; i < scores.length; i++) {
newScores[i] = scores[i];
}
System.out.println("插入学生成绩前的数组:");
for (int i : newScores) {
System.out.print(i + " ");
}
System.out.println();
// 3)使用Scanner类获取你要增加的学员成绩
System.out.println("请输入你要增加的学员成绩:");
int insert = sc.nextInt();
// 设置插入的成绩插入的位置,默认将其插入在数组最后位置
int index = newScores.length - 1;
// 4)通过循环比较获取增加的学员成绩的插入位置
for (int i = 0; i < newScores.length; i++) {
// 比较,如果插入的学员成绩比数组里的元素大,得到其插入位置
if (insert > newScores[i]) {
index = i;
// 一旦得到插入成绩比数组元素大,就结束比较,后面不再进行比较
break;
}
}
// 5)从插入元素插入位置开始及之后的元素依次往后移动一位(从最后一个元素开始,倒着移动)
for (int i = newScores.length - 1; i > index; i--) {
newScores[i] = newScores[i - 1];
}
// 6)将要插入的成绩存储到插入位置
newScores[index] = insert;
// 输出数组里的所有元素,看一下是否满足了需求
System.out.println("插入学生成绩后的数组:");
for (int i : newScores) {
System.out.print(i + " ");
}
}
}
练习五:
删除数组strs中的某个元素,删除完这个元素之后,后面的元素依次往前移动一位
package cn.bdqn.demo03;
import java.util.Scanner;
public class Demo03 {
public static void main(String[] args) {
String[] strs = { "hello", "java", "html", "css", "JavaScript" };
System.out.println("---元素删除前---");
for (int i = 0; i < strs.length; i++) {
System.out.print(strs[i] + " ");
}
System.out.println();
Scanner sc = new Scanner(System.in);
System.out.println("请输入你想删除的元素的下标(0-4):");
int index = sc.nextInt();
if (index == 4) {
strs[4] = null;
} else {
for (int i = index; i < strs.length - 1; i++) {
strs[i] = strs[i + 1];
}
// 元素往前移动之后,最后一个元素赋值为null
strs[strs.length - 1] = null;
}
System.out.println("---元素删除后---");
for (int i = 0; i < strs.length; i++) {
System.out.print(strs[i] + " ");
}
System.out.println();
}
}
总结
数组常用写法:
数据类型[] 数组名 = new 数据类型[数组长度];
数据类型[] 数组名 = new 数据类型[ ]{数据1,数据2,…,数据n};
数组是一个引用数据类型,直接输出数组名,输出的是数组在内存中的地址值
遍历:通过for循环来遍历
length函数:数组名.length自动获取该数组的长度。
增强for循环:将数组或者集合中的元素依次取出来存入到变量中,然后操作这个变量就等同于操作数组或者集合中的数据