数组(容器)
- 数组是一组数据类型相同的数据的组合,将这些数据统一的管理起来
- 数组本身是一个引用数据类型,数组内存储的类型可以是基本类型,也可以是引用类型
数组的特点
- 数组是一个引用数据类型
- 数组是在堆内存中的一串连续的地址存在
- 数组在初始化时必须指定长度
- 堆内存的数组空间长度一旦确定,不能再发生改变
- 栈内存的变量中存储的是数组的地址引用
- 数组内部存储的类型可以是基本的,也可以是引用
栈内存、堆内存中的形态
- 栈内存:栈内存中存的元素是变量,创建(初始化)出来的变量,如果没有往里存值那就是真的变量空间里没有任何东西的
- 堆内存:堆内存中的元素,创建出来都会有默认值,现在学习的数组是在堆内存,以后的对象也是存在堆内存的,堆内存中的元素,如果不赋值,也是会有默认值存在的
-
数组的定义(声明)
数据类型[] 数组名字; int[] x; 三种都能用,但是一般使用int[] x; int x[]; int []x;
-
数组的赋值(初始化)
-
静态初始化
int[] array = new int[]{1,2,3,4,5};
int[] array = {1,2,3,4,5};
int[] array; 一百行 array = new int[]{1,2,3,4,5};
-
动态初始化
有长度,没有元素(有默认值)
int[] array = new int[长度]; //int[] array = new int[5]; 长度只能是>=0的整数
数组元素的默认值
整数默认值 -- 0
浮点数默认值 -- 0.0
字符型默认值 -- 0 -- char 97-a 65-A 48-'0'
布尔型默认值 -- false
引用数据默认值 -- null
- 数组的访问和遍历
import java.util.Arrays;
public class Arr{
public static void main(String[] args){
int[] array = new int[]{1,2,3,4,5};
//打印数组
//System.out.println(Arrays.toString(array));
//取值,打印数组的某一个元素
//System.out.println(array[3]);
//存值(更新已有值),index 3必须存在,
//超出,运行(编译不会出错)会抛异常java.lang.ArrayIndexOutOfBoundsException
//array[4] = 5;
//System.out.println(Arrays.toString(array));
//array是可迭代对象,value是一个变量,用来接收array中遍历出来的元素
for(int value:array){
System.out.println(value);
}
}
}
-
基本数据类型和引用数据类型在内存结构上的区别
- 基本数据类型变量空间存储的是值,传递的就是值, 一个改变 另一个不变
- 引用类型变量空间存储的是地址(引用),传递的是引用,一个改变另一个跟着改变
总结:
- 所有的变量空间都存储在栈内存
- 变量空间可以存储基本数据类型,也可以存储引用数据类型
- 如果变量空间存储的是基本数据类型,存储的是值,一个变量的值改变,另一个不会跟着改变
- 如果变量空间存储的是引用数据类型,存储的是引用(地址),一个变量地址对应的值改变,另一个跟着改变
栗子:创建一个数组,用来存储1-100之间的偶数
/* arr[0]=2 arr[1]=4 arr[2]=6 arr[3]=8 */ //import java.util.Arrays; public class ArrEven{ public static void main(String[] args){ int[] arr = new int[50]; for(int i=0;i<arr.length;i++){ arr[i] = i*2+2; } for(int value:arr){ System.out.println(value); } //System.out.print(Arrays.toString(arr)); } }
-
练习题
-
创建一个数组用来存储1-100之间的奇数
/* 创建一个数组用来存储1-100之间的奇数 index value 0 1 1 3 2 5 3 7 4 9 */ import java.util.Arrays; public class ArrOddNum{ public static void main(String[] args){ int[] arr = new int[50]; for(int i=0;i<arr.length;i++){ arr[i] = i*2+1; } for(int value:arr){ System.out.println(value); } //System.out.print(Arrays.toString(arr)); } }
-
*给定两个数组a{1,2,3,4},b{5,6,7,8} 将两个数组内的元素对应位置互换a{5,6,7,8} b{1,2,3,4}
import java.util.Arrays; public class ArrNumjiaohuan{ public static void main(String[] args){ int[] a = new int[]{1,2,3,4}; int[] b = new int[]{5,6,7,8}; //方式2:直接交换变量a和b中的数组引用(地址),没有循环,一次搞定,没有长度限制 int[] temp = a; a = b; b = temp; //方式1:交换数组中对应的元素(循环次数多,受长度限制) //for(int i=0;i<a.length;i++){ // a[i] = a[i] + b[i]; // b[i] = a[i] - b[i]; // a[i] = a[i] - b[i]; //} System.out.println(a); //打印a,a存的是内存地址,十六进制 [I@4e25154f [表示变量的数据类型是数组,I表示变量里面的元素数据类型是int System.out.println(Arrays.toString(a)); System.out.println(Arrays.toString(b)); } }
方式2的内存变化
-
给定一个数组a{1,2,3,4,5,6}将这个数组中的元素头尾对应位置互换
/* a[0] -- a[5] a[1] -- a[4] a[2] -- a[3] */ import java.util.Arrays; public class ArrHeaderEnd{ public static void main(String[] args){ int[] a = new int[]{1,2,3,4}; System.out.println(Arrays.toString(a)); for(int i=0;i<a.length/2;i++){ int x = a[i]; a[i] = a[a.length-1-i]; a[a.length-1-i] = x; } System.out.println(Arrays.toString(a)); } }
- 给定一个数组a{1,2,3,4,5,6}计算数组所有元素的平均值
public class ArrAvg{ public static void main(String[] args){ int[] a = new int[]{1,2,3,4,5,6}; int sum = 0; for(int i=0;i<a.length;i++){ sum += a[i]; } System.out.println(sum); int avg = sum/a.length; System.out.println(avg); } }
- *给定一个数组a{1,3,5,7,9,0,2,4,6,8}找寻数组中的最大值和最小值(极值问题)
public class ArrMaxMin{ public static void main(String[] args){ int[] a = new int[]{1,3,5,7,9,0,2,4,6,8}; int max = a[0]; int min = a[0]; for(int i=0;i<a.length;i++){ if(a[i]>max){ max = a[i]; }else{ if(a[i]<min){ min = a[i]; } } } System.out.println("数组a的最大值:"+max); System.out.println("数组a的最小值:"+min); } }
-
给定两个数组a{1,2,3},b{4,5} 合并两个数组(创建一个新的数组长度5)
import java.util.Arrays; public class ArrMerge{ public static void main(String[] args){ int[] a = new int[]{1,2,3}; int[] b = new int[]{4,5}; int[] c = new int[a.length+b.length]; //思路2:想要将新数组填满, //如果新数组的索引大于a的长度就从b里取元素填入新数组, //否则从a取 for(int i=0;i<c.length;i++){ if(i<a.length){ c[i] = a[i]; }else{ c[i] = b[i-a.length]; } } System.out.println(Arrays.toString(c)); //思路1:将a的元素填入新数组,然后再将b的元素填入新数组 //for(int i=0;i<a.length;i++){ // c[i] = a[i]; //} //for(int j=0;j<b.length;j++){ // c[a.length+i] = b[j]; //} //System.out.println(Arrays.toString(c)); //for(int v:c){ // System.out.println(v); //} } }
-
给定一个数组a{1,2,3,9,4,5}按照数组中的最大值位置,将数组拆分成两个{1,2,3} {4,5}
/* 给定一个数组a{1,2,3,9,4,5}按照数组中的最大值位置,将数组拆分成两个{1,2,3} {4,5} oldarr[0] -- newa[0] oldarr[1] -- newa[1] oldarr[2] -- newa[2] index = 3 oldarr[3+1] -- newb[0] oldarr[3+2] -- newb[1] */ import java.util.Arrays; public class ArrSplit{ public static void main(String[] args){ int[] oldarr = new int[]{1,2,3,4,5,6,90,4,5,6,7,8}; int max = oldarr[0]; int index = 0; //找出最大值的位置 for(int i=0;i<oldarr.length;i++){ if(oldarr[i]>max){ max = oldarr[i]; index = i; } } System.out.println("最大值索引:"+index); int[] newb = new int[index]; int[] newc = new int[oldarr.length-index-1]; for(int i=0;i<oldarr.length-1;i++){ if(i<index){ newb[i] = oldarr[i]; }else{ newc[i-index] = oldarr[i+1]; } } System.out.println(Arrays.toString(newb)); System.out.println(Arrays.toString(newc)); } }
-
*给定一个数组a{1,2,3,0,0,4,5,0,6,0,7}去掉数组中的0元素(创建一个新的数组 短的 非0元素跳出来 )
/* *给定一个数组a{1,2,3,0,0,4,5,0,6,0,7}去掉数组中的0元素 (创建一个新的数组 短的 非0元素跳出来 ) */ import java.util.Arrays; public class ArrDel{ public static void main(String[] args){ //1.定义一个数组 int[] a = {1,2,3,0,0,4,5,0,6,0,7}; //2.找出非0元素个数 int count = 0; for(int i=0;i<a.length;i++){ if(a[i]!=0){ count += 1; } } //3.创建一个新数组,装原数组的非0元素 int[] newa = new int[count]; //4.将原数组中非0元素挑出来,存入新数组 int index = 0; for(int i=0;i<a.length;i++){ if(a[i]!=0){ newa[index++] = a[i]; } } //5.删除a变量的地址,堆内存的数组没有人引用,会被gc回收 a = null; System.out.println(Arrays.toString(newa)); } }
数组删除操作内存变化
-
创建一个数组,存储2-100之间的素数(质数)
import java.util.Arrays; public class ArrPrime{ public static void main(String[] args){ int[] arr = new int[50]; int index = 0; for(int i=2;i<=100;i++){ boolean flag = true; for(int j=2;j<=i/2;j++){ if(i%j==0){ flag = false; break; } } if(flag==true){ arr[index] = i; index++; } } int[] newArr = new int[index]; for(int i=0;i<arr.length;i++){ if(arr[i]!=0){ newArr[i]=arr[i]; } } //删除原来的arr引用,这样栈内存没引用了,堆内存就会被gc回收 arr = null; System.out.println(Arrays.toString(newArr)); } }
-
*数组元素的排序(冒泡 选择 快排 希尔 堆排序 桶排序 归并排序 递归...)
/* 5 2 3 1 4 每次从底端开始和上一个比较,最小的升到顶端,最大的沉到底端 第1轮比较,比较4次,冒出来第一小的1 1 5 2 3 4 第2轮比较,比较3次,冒出来第二小的2 1 2 5 3 4 第3轮比较,比较2次,冒出来第三小的3 1 2 3 5 4 第4轮比较,比较1次,冒出来第四小的4 1 2 3 4 5 */ import java.util.Arrays; public class ArrBubble{ public static void main(String[] args){ int[] arr = new int[]{5,2,3,1,4}; //控制比较轮次,每一轮冒出来第一小,第二轮确认第二小 for(int i=1;i<arr.length;i++){ //控制比多少次,从数组底端一直比到顶端 for(int j=arr.length-1;j>=i;j--){ if(arr[j]<arr[j-1]){ int temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; } } } for(int value:arr){ System.out.println(value); } } }
-
*用户的登录认证(用数组当作小数据库 存值 用户验证)
/* 用户的登录认证(用数组当作小数据库 存值 用户验证) case: 先比账号 账号是唯一存在(主键) 登录成功 密码错误 用户名不存在 思路 用户名 String 张三,李四,王五 密码 int 123, 666, 888 1.new两数组分别存放账号和密码,账号和密码的索引位置一致 2.输入一个账号, 加一个标志位flag=false 从用户名数组里去遍历,找到账号,就停止遍历,不再往下找 再输入一个密码, 比对密码, 对了 登录成功, flag=true //错了, //提示用户名密码错误 break 如果遍历用户名数组都没找到,就是说用户名不存在 if(!flag) 提示用户名或密码错误 */ import java.util.Arrays; import java.util.Scanner; public class ArrLogin{ public static void main(String[] args){ String[] userBox = {"张三","李四","王五"}; int[] passwdBox = {123,666,888}; Scanner input = new Scanner(System.in); System.out.print("请输入账号:"); String user = input.nextLine(); boolean flag = false; for(int i=0;i<userBox.length;i++){ if(userBox[i].equals(user)){ //如果账号存在 System.out.print("请输入密码:"); int pwd = input.nextInt(); if(passwdBox[i]==pwd){ System.out.println("登录成功!"); flag = true; //当且仅当账号和密码都对改变标志位 } break;//只要找到账号,不管密码对不对,都不再继续for循环 } } //如果上面的for循环走完了,从来没有进去过if,那么账号不存在 //这种情况一般使用一个标志位 //密码错误或者账号错误,都使用一个提示语 if(!flag){ System.out.println("用户名或密码错误!"); } } }
-