day01-数组的定义与元素访问+数组扩容+数组特点+方法中的数组
本阶段学习任务
数组(2天)
常用类(1.5天)
集合(3.5天)
异常(1天)
IO流(2天)
线程(2天)
反射与注解(1天)
本阶段内容与前面内容相比更多, 更难
文章目录
day01学习任务
1 掌握数组的定义与元素访问 掌握数组的遍历
2 理解数组扩容的原理
3 记住数组的特点
4 理解数组是一种引用数据类型
数组的定义与元素访问
定义一个变量用于存储一个数据, 如果需要保存若干数据呢? 可以选择使用数组
- 数组就是用于存储同一种类型若干数据的容器数组与变量类似,也需要先定义,初始化,再使用, 数组定义格式: 数据类型 [] 数组名;初始化格式: 数组名 = new 数据类型[长度];也可以在定义的同时就初始化: 数据类型 [] 数组名 = new 数据类型[长度];说明: 1) 数据类型就是数组中存储数据的类型 2) 方括弧[]表示正在定义数组, 一般放在数组名前面,也可以放在数组名后面 3) 长度是数组的最大容量 4) new运算符在堆中创建一个数组,即在堆中分配一块连续的存储空间,把这块连续存储空间的引用赋值给数组名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oyc6XWRD-1677677424769)(D:\course\03-JavaSE\Note\Day01\01 定义数组.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gdfeqtgS-1677677424770)(D:\course\03-JavaSE\Note\Day01\02 通过索引值访问数组元素.png)]
-
数组通过索引值来访问每个 数组元素定义了数组之后 ,系统为每个 数组元素指定一个索引值(下标 )数组索引值是从0开始的, 最大索引值就是: 数组长度 - 1访问格式: 数组名[索引值]
-
创建数组之后 ,系统 会给数组元素默认初始化.类似于创建对象后,系统给对象的属性默认初始化一样整数数组元素默认初始化为0, 小数数组元素默认初始化为0.0; 字符数组元素默认初始化为码值为0的字符’\u0000’; 布尔数组元素默认初始化为false, 引用对象数组元素默认初始化为null
* 数组的定义 public class Test01Defination { public static void main(String[] args) { //定义数组存储10个整数 int [] ints; //先定义 ints = new int[10]; //再初始化 //定义数组存储8个小数, double[] doubles = new double[8]; //方括弧可以放在数组名前,也可以放在数组名后 boolean flags[] = new boolean[5]; //数组可以存储基本类型数据,也可以存储引用类型数据 String[] names = new String[10]; //数组名保存的是堆中数组的引用 ,直接打印数组名会显示一串十六 进制数 System.out.println( ints ); System.out.println( doubles ); System.out.println( flags ); System.out.println( names ); //堆中new出来的这一块连续的存储空间才是存储数据的地方, 通过索引值来访问 ints[0] = 123; //把整数123保存到ints[0]数组元素中 ints[1] = 456; //给ints[1] 数组元素赋值 456 int x = ints[0]; //把ints[0]元素存储 的 123赋值给 x int y = ints[1]; //把ints[1]元素的值赋值给y变量 System.out.println( x ); System.out.println( y ); //定义了数组之后,系统给数组元素进行默认初始化 System.out.println( ints[3] ); //0 System.out.println( doubles[0]); //0.0 System.out.println( flags[0]); //false System.out.println( names[0] ); //null } }
-
通过for循环遍历数组的每个 元素, 格式为: for( int i = 0 ; i < 数组的长度; i++){ 数组名[i]}
* for循环遍历数组的每个 元素 public class Test02Array { public static void main(String[] args) { //定义存储10个整数的数组 int[] ints = new int[10]; //定义了数组后,系统会给数组元素默认初始化, //依次把数组的每个 元素打印到屏幕上 /* System.out.println( ints[0] ); System.out.println( ints[1] ); System.out.println( ints[2] ); System.out.println( ints[3] ); System.out.println( ints[4] ); System.out.println( ints[5] ); System.out.println( ints[6] ); System.out.println( ints[7] ); System.out.println( ints[8] ); System.out.println( ints[9] );*/ //每个 数组都有一个length属性表示数组的长度 for (int i = 0; i < ints.length; i++) { System.out.println( ints[i] ); } //给数组的每个元素依次赋值: 0 , 11 , 22, 33 , 44, 55 ..... //在IDEA中,输入fori会生成for循环代码块 for (int i = 0; i < ints.length; i++) { ints[i] = i*10 + i; } for (int i = 0; i < ints.length; i++) { System.out.print( ints[i] + " "); } System.out.println(); } }
* 数组练习 public class Test03 { public static void main(String[] args) { //已知: java.lang包中有Math数学类, 该类提供一个静态方法random()返回 [ 0 , 1)范围内的随机小数 for (int i = 0; i < 10; i++) { System.out.println( Math.random() ); } //1要求: 定义存储10个小数的数组, 给数组元素赋值[0, 100)范围内的随机小数 double[] doubles = new double[10]; for (int i = 0; i < doubles.length; i++) { doubles[i] = Math.random() * 100; } for (int i = 0; i < doubles.length; i++) { System.out.println( doubles[i] ); } //2 定义存储10个整数的数组, 要求给数组元素赋值[0, 100)范围内的随机整数 int[] ints = new int[10]; for (int i = 0; i < ints.length; i++) { ints[i] = (int)( Math.random() * 100 ); } for (int i = 0; i < ints.length; i++) { System.out.print( ints[i] + " "); } System.out.println(); //3 定义存储20个布尔值的数组, 给数组元素赋值随机的布尔值 boolean[] flags = new boolean[20]; for (int i = 0; i < flags.length; i++) { flags[i] = Math.random() > 0.5 ? true : false; } for (int i = 0; i < flags.length; i++) { System.out.print( flags[i] + " "); } System.out.println(); //4 定义存储50个字符的数组, 给数组元素赋值随机的小写字母 char[] chars = new char[50]; for (int i = 0; i < chars.length; i++) { //Math.random()生成的是[0,1)范围内的随机小数, Math.random()*26就是[0, 26)范围内的随机小数 , Math.random() * 26 + 'a' 表达式的取值范围是[97, 123) //char cc = (char)( Math.random() * 26 + 'a' ); double xx = Math.random(); //生成的是[0,1)范围内的随机小数 int nn = (int)( xx * 26); //把xx转换为[0,26)范围内的整数 char cc = (char)( nn + 'a'); //把整数nn转换为字符 System.out.println(xx + " ---- " + nn + " ---- " + cc ); chars[i] = cc; } for (int i = 0; i < chars.length; i++) { System.out.print( chars[i] + " "); } System.out.println(); } }
-
先定义数组,再给数组元素赋值,称为数组的动态初始化.也可以在定义数组的同时就给所有数组元素赋值,称为数组的静态初始化,格式: 数据类型 [] 数组名 = new 数据类型[]{值1,值2,值3…};注意: 数组静态初始化时, 不需要指定数组长度,数组长度由初始化元素的个数决定静态初始化也可以简化为: 数据类型 [] 数组名 = {值1, 值2, 值3…};
* 数组的静态初始化及foreach循环遍历数组元素 public class Test04StaticInitForEach { public static void main(String[] args) { //在定义数组的同时就给所有 数组元素赋值,称为数组的静态初始化 int [] ints = new int[]{ 123,34,65,76,43}; double [] scores = new double[] {32.9, 78.0, 100 }; String[] names = new String[]{"zhangsan", "lisi", "wangwu", "zhaoliu"}; //静态初始化简化为 boolean [] flgas = { true, false, true, true}; char [] chars = {'A', 'b', '5', '&', '汉', '字', 97, 98 , 30066, 30088}; //定义char类型的变量可以赋值单引号引起来的单个字符, 也可以赋值0~65535之间的整数 char cc = 'a'; //系统执行这一行时, 会给cc变量分配 2 个字节, 这两个字节存储的是'a'对应的二进制: 00000000 01100001, 这个二进制转换为整数,称为码值. 给char类型数据赋值时,可以赋值 0 ~65535之间的整数 //使用foreach循环遍历ints数组的每个 元素 for( int x : ints ){ System.out.print( x + " "); //执行时, 系统依次把ints数组的每个 元素赋值给x再执行循环体. 即把ints[0]元素的值123赋值给x执行循环体,再把ints[1]元素的值34赋值给x执行循环体,再把ints[2]元素的值65赋值给x执行循环体,再把ints[3]元素的值76赋值给x执行循环体,再把ints[4]元素的值43赋值给x执行循环体 } System.out.println(); //在IDEA中,可以直接输入 iter 会生成foreach循环代码块 for (String name : names) { System.out.print( name + " "); } System.out.println(); for (char aChar : chars) { System.out.print(aChar + " "); } System.out.println(); } }
-
在遍历数组元素时,除了for循环外,还可以使用foreach循环, 也称为增强的for循环,格式为: for( 数据类型 变量名 : 数组名 ){ foreach循环在执行时, 会把数组的每个 元素依次赋值给变量,再执行循环体 注意: 在循环体中给变量重新 赋值, 不影响数组元素 }即foreach循环仅用于遍历访问数组元素,不能修改数组元素
* 数组练习 public class Test05 { public static void main(String[] args) { //从键盘上定义人数 Scanner sc = new Scanner(System.in); //Scanner是Java定义的类, sc是对象名(是开发人员命名的), new运算符用于创建对象的, new运算符后面跟构造方法Scanner(InputStream), 实参传递System.in, System类有静态变量in它是InputStream类型的. System.in代表系统的标准输入设备(键盘). System.out.println("请输入同学的人数"); int num = sc.nextInt(); //调用sc对象的nextInt()实例方法,该方法的作用是从键盘上读取整数,并返回读到的整数, 把该方法的返回值赋值给num //根据人数定义存储姓名的数组, 数组的长度不能为负数 while ( num < 0 ){ System.out.println("人数不能为负数,请重新输入"); num = sc.nextInt(); } String [] names = new String[ num ]; //从键盘上输入姓名保存到数组中 for (int i = 0; i < names.length; i++) { System.out.println("请输入第" + (i+1) +"个同学的姓名"); names[i] = sc.next(); } //foreach遍历数组中的姓名 for (String name : names) { System.out.print( name + " "); } System.out.println(); } }
-
数组是一种引用数据类型java引用 类型包括: 类, 接口, 数组, 枚举, 注解int [] ints = new int[10]; 数组中ints数组名其实就是一个变量名, 它的数据类型是: int [] 相同类型的变量可以相互赋值int [] another = ints; 定义int[]类型的数组another, 把 ints变量的值赋值给another
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rgj7iWjm-1677677424771)(D:\course\03-JavaSE\Note\Day01\03 数组名相互赋值.png)]
* 数组名相互赋值
public class Test06ArrayAsign {
public static void main(String[] args) {
int [] ints = new int[]{12,34,56,78,90};
System.out.println( ints ); //[I@4554617c
//定义新数组
int [] another = ints; //把ints变量的值赋值给another
System.out.println( another ); //[I@4554617c
//遍历 another数组的元素
for (int xx : another) {
System.out.print(xx + " ");
}
System.out.println(); //12 34 56 78 90
//修改another数组元素
another[0] = 123;
another[1] = 456;
//遍历ints数组
for (int anInt : ints) {
System.out.print(anInt + " ");
}
System.out.println(); //123 456 56 78 90
//给ints重新赋值
ints = new int[]{6,6,6,6,6};
//遍历another数组元素
for (int xx : another) {
System.out.print(xx + " ");
}
System.out.println(); //123 456 56 78 90
//给数组名重新赋值
another = new int[20];
another = new int[]{1,2,3,4,5,6,7,8};
//another = {8,8,8,8}; //这种简化形式仅用于数组的静态初始化,不能用于数组名重新赋值
}
}
数组扩容
- 定义了数组之后 , 数组能够存储数据的最大容量就确定了.int [] ints1 = new int[10]; 数组ints1 最多可以存储10个int整数int [] ints2 = {1,2,3,4,5,6}; 数组ints2最多可以存储 6 个int整数如果想向数组中存储更多数据呢? 就需要对数组扩容
在使用数组时面临的两个小问题1) 数组初始化容量多大合适? 需要进行估算2) 数组如何扩容? 按实际需求扩容 按1.5倍, 或者2倍大小扩容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfUTNLf4-1677677424771)(D:\course\03-JavaSE\Note\Day01\04 数组扩容.png)]
- 数组扩容: 1) 定义更大的数组 2) 把原来数组元素复制到大数组中 3) 让原来数组名指向 这个大的数组
- System.arraycopy(src, srcPos, dest, destPos, length); 把src数组中从srcPos开始的元素复制到dest数组中从destPos开始的位置 上,复制length个元素
* 数组扩容
public class Test07Expand {
public static void main(String[] args) {
int [] ints = {12,34,56,78,90};
//需求: 向ints数组中再存储2个整数, 需要对ints数组扩容
//1) 定义更大 的数组
int[] bigger = new int[ints.length + ints.length / 2];
//2) 把原来数组的数据复制到大数组中
/* for (int i = 0; i < ints.length; i++) {
bigger [i] = ints[i];
}*/
//System.arraycopy(src, srcPos, dest, destPos, length); 把src数组中从srcPos开始的元素复制到dest数组中从destPos开始的位置 上,复制length个元素
//该方法使用native修饰,只有方法声明没有方法体,它的方法体是用C/C++实现的 . 即在java程序中可以调用其他语言编写的代码
//把ints数组中从索引值为0开始的元素复制到bigger数组中从 0 开始的位置上, 复制 ints.length个元素
System.arraycopy(ints,0, bigger,0,ints.length);
//3)让原来数组名指向 大的数组
ints = bigger;
//遍历ints数组
for (int anInt : ints) {
System.out.print(anInt + " ");
}
System.out.println();
}
}
数组特点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5By4JUzX-1677677424771)(D:\course\03-JavaSE\Note\Day01\05 数组优点.png)]
- 优点: 通过索引值可以计算出每个 数组元素的地址 ,通过元素地址直接访问, 效率高
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9FgJNIyj-1677677424772)(D:\course\03-JavaSE\Note\Day01\06 数组缺点.png)]
- 缺点: 向数组中插入/删除元素时,可能需要扩容, 复制/移动大量元素,效率低
- 数组一般用于存储基础数据以访问为主, 很少插入/删除的场景
方法中的数组
- 方法是用于完成某个功能编写的代码方法需要的数据通过参数接收 方法返回值类型是由方法体中return返回的数据决定的
- 如果方法需要对数组进行处理则通过参数接收一个数组如果方法体中return返回了一个数组则方法返回值类型是数组类型
* 数组作为方法参数, 作为方法返回值
public class Test08MethodArray {
public static void main(String[] args) {
//调用 getIntArray() 方法, 可以定义变量(数组)来保存方法的返回值
int [] array = getIntArray();
/* for (int x : array) {
System.out.print(x + " ");
}
System.out.println();*/
//调用 printIntArray( int [] ints)方法把array数组元素打印到屏幕上
printIntArray( array );
}
//定义方法,把int[]整数数组元素打印到屏幕上, 通过参数接收一个数组
public static void printIntArray( int [] ints){
//在方法体中把参数ints接收的数组元素打印到屏幕上即可
for (int anInt : ints) {
System.out.print(anInt + " ");
}
System.out.println();
}
//定义方法返回数组
public static int[] getIntArray(){
//定义存储整数的数组
int[] ints = new int[10];
//给数组元素赋值[0,100)范围内的随机整数
for (int i = 0; i < ints.length; i++) {
ints[i] = (int) (Math.random() * 100);
}
//返回ints, 方法返回值类型就是ints的数据类型: int[]
return ints;
}
}
练习
1 有数组: int [] ints = {34,56,78,90,63,41,18}; 编程程序找出数组最大元素的索引值
public class Test01 {
public static void main(String[] args) {
int [] ints = {3344,56,78,90,63,401,18};
//定义变量保存最大元素索引值,先假设 0 元素最大
int max = 0 ;
// 从 max + 1 开始遍历数组后面的其他元素
for(int i = max + 1 ; i < ints.length; i++){
//如果有某个元素比max标识的元素还大,则这个元素就是当前最大的
if ( ints[i] > ints[max] ){
max = i; //把当前最大元素索引值赋值给max
}
}
System.out.println("输出最大元素索引w值:" + max + ",对应的最大值:" + ints[max]);
}
}
2 定义存储 100个字符的数组, 给数组元素赋值随机的大写字母. 统计大写字母A在数组中出现的次数 统计每个 大写字母在数组中出现的次数
public class Test02 {
public static void main(String[] args) {
//定义存储 100个字符的数组,
char[] chars = new char[100];
// 给数组元素赋值随机的大写字母.
for (int i = 0; i < chars.length; i++) {
chars[i] = (char)( 'A' + Math.random() * 26 );
}
for (char aChar : chars) {
System.out.print(aChar + " ");
}
System.out.println();
/* //统计大写字母A在数组中出现的次数,
int count = 0 ; //定义变量保存A在数组中出现的次数
//遍历数组的每个元素,如果这个元素是A就进行计数
for (char aChar : chars) {
if (aChar == 'A'){
count++;
}
}
System.out.println("A的次数为: " + count);*/
//统计每个大写字母在数组中出现的次数,
/*for(char cc = 'A' ; cc <= 'Z' ; cc++) {
int count = 0; //定义变量保存 cc 在数组中出现的次数
//遍历chars数组的每个元素,如果这个元素是 cc 就进行计数
for (char aChar : chars) {
if (aChar == cc ) {
count++;
}
}
System.out.println(cc + "的次数为: " + count);
}
*/
//定义长度为26的存储整数的数组,保存每个 大写字母出现的次数
int[] counts = new int[26]; //约定把A的次数保存到counts[0]元素中, 把B的次数保存到counts[1]元素中, 把C的次数保存到counts[2]元素中, 把D的次数保存到counts[3]元素中,.....把Z的次数保存到counts[25]元素中. 规律: 对于任意一个字符cc出现的次数保存到 counts[cc - 'A'] 数组元素中
//遍历 chars 数组的每个 元素
for (char aChar : chars) {
//把保存aChar字符出现次数的数组元素counts[aChar-'A']的值自增
counts[aChar - 'A']++;
}
//打印结果
for(char cc = 'A' ; cc <= 'Z'; cc++){
System.out.println(cc + "出现的次数: " + counts[cc - 'A']);
}
}
}
3 定义方法向数组的某个位置插入元素 定义方法删除数组中指定索引值的元素
public class Test03 {
public static void main(String[] args) {
int [] ints = {12,34,56,78,90};
//调用insert方法向ints数组中索引值为2的位置插入元素66, 把方法返回的较大的数组再赋值给ints
// ints = insert(ints,2,66);
//调用delete方法删除ints数组中索引值为1的元素,把方法返回的较小的数组再赋值给 ints
ints = delete( ints, 1);
for (int anInt : ints) {
System.out.print(anInt + " ");
}
System.out.println();
}
//定义方法删除数组指定位置的元素
public static int[] delete( int [] array, int i ){
//把array[i]数组元素从数组中删除
//1 定义更小的数组
int [] smaller = new int[array.length - 1];
//2 把array数组从 0 开始 的元素复制到smaller数组中从0开始的位置上, 复制i个
System.arraycopy(array,0, smaller,0,i);
//3 跳过array[i]元素,把array数组中从 i +1 开始的元素复制到smaller数组中从i开始的位置上,复制 array.length - i - 1 个元素
System.arraycopy(array, i+1, smaller,i,array.length - i - 1);
//4) 返回较小的数组
return smaller;
}
//定义 方法向数组中指定的位置插入元素, 通过参数接收一个数组, 接收一个插入的位置 ,插入的数据
public static int[] insert( int [] array, int i, int key){
//把key元素插入到array数组的 i 位置上
//1 定义更大的数组
int [] bigger = new int[array.length + 1];
//2 把array源数组从 0 开始的元素复制到bigger数组中从 0 开始的位置上, 复制i个元素
System.arraycopy(array,0, bigger, 0, i);
//3 把key数据保存到bigger[i]元素中
bigger[i] = key;
//4 把array数组从 i 开始的元素复制到bigger数组中从 i + 1 开始的位置上,需要复制 array.length - i 个元素
System.arraycopy(array, i, bigger, i+1, array.length - i);
// 让原来数组名指向大的数组
// array = bigger;
//5 返回bigger这个较大的数组
return bigger;
}
}
位置上
//1 定义更大的数组
int [] bigger = new int[array.length + 1];
//2 把array源数组从 0 开始的元素复制到bigger数组中从 0 开始的位置上, 复制i个元素
System.arraycopy(array,0, bigger, 0, i);
//3 把key数据保存到bigger[i]元素中
bigger[i] = key;
//4 把array数组从 i 开始的元素复制到bigger数组中从 i + 1 开始的位置上,需要复制 array.length - i 个元素
System.arraycopy(array, i, bigger, i+1, array.length - i);
// 让原来数组名指向大的数组
// array = bigger;
//5 返回bigger这个较大的数组
return bigger;
}
}