Java 25天基础-DAY 04

    xiaoxiao2022-04-24  206

    Java 25天基础-DAY 04 1、数组定义: 数组:同一种数据类型的集合,其实数组就是个容器 数组的好处:可以自动给数组中的元素从0开始编号,方便操作这些元素 格式1: 元素类型[] 数组名 = new 元素类型 [元素个数或数组长度]; 示例: int [] arr = new int [5]; 格式2: 元素类型[] 数组名 = new 元素类型 [元素, 元素, ...]; 示例:int [] arr = new int []{2,4,6,8}; int [] arr = {2,4,6,8} java在启动时一共在内存中划分了5片空间: 1、栈内存 :用于存储局部变量,当数据使用完,所占空间会自动释放 2、堆内存 :数组和对象,通过new建立的实例都存放在堆内存中 每一个实体都有内存地址值 实体中的变量都有默认初始化值 实体在不被使用,会在不确定的时间内被垃圾回收器回收。 下面三种暂时不用 3、方法区;4、本地方法区;5、寄存器 例1:数组的书写方式以及不同数据类型的默认输出等 class shuzu1 { public static void main(String[] args) { int [] arr = new int []{1,2,3,45,6,6};//正规方式 System.out.println(arr[3]); int [] ar = {12,3,4,2,55};//简写方式 System.out.println(ar[3]); int [] a = new int [4]; // 数组只要被定义就存在值 (0) System.out.println("int="+a[3]); //无数值定义默认输出为0 double [] b = new double [5]; System.out.println("double="+b[3]); //无数值定义默认输出为0.0 float [] c = new float [5]; System.out.println("float="+c[3]); //无数值定义默认输出为0.0f(但是编译后输出为0.0) boolean [] d = new boolean [5]; System.out.println("boolean="+d[3]);//无数值定义默认输出为false System.out.println("========================================="); //检查下面是否有垃圾存在? int [] x=new int []{1,2,3,21,4,6,5,4}; int [] y=x; // 将y也指向数组 //当y重新定义数组后 int [] y=new int []{1,3,4,11,42}; x =null; 这是x对应的数组为垃圾。 x =null; System.out.println(y[3]); //从上面实验得知,数组并没有被当作垃圾回收,因为数组y仍然在使用。 System.out.println("========================================="); //从下面实验得知,只要new后就会在堆内存中创建一个新的数组。 int [] z=new int []{1,2,3,21,4,6,5,4}; int [] z1=new int []{12,23,32,221,24,36,35,14}; System.out.println(z[3]); System.out.println(z1[3]); System.out.println("========================================="); / /数组中常见问题 int [] zz= new int [3]; //System.out.println(zz[3]); /* 编译不报错,运行时报以下错误:数组异常, Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at shuzu1.main(shuzu1.java:52) 操作数组时,访问到了数组中不存在的角标。 */ System.out.println("========================================="); int [] zzz= new int [3]; zzz=null; System.out.println(zzz[1]); /* 编译不报错,运行时报以下错误:空指针异常 Exception in thread "main" java.lang.NullPointerException at shuzu1.main(shuzu1.java:62) 当引用没有任何指针指向值为null的情况,该引用还在用于操作实体。 */ } } 2、数组的遍历: 获取数组中的元素,通常会用到遍历(循环)。 例1:遍历时,使用数组的方式:数组名称.length class shuzu2 { public static void main(String[] args) { int [] arr = new int [] {1,4,6,9,10}; for (int x=0;x< arr.length ;x++ ) { System.out.println(arr[x]); } System.out.println("You are hero"); } } 输出结果: D:\Skill\JAVA\2017>java shuzu2 1 4 6 9 10 You are hero 例2、优化输出方式: class shuzu2 { public static void main(String[] args) { int [] arr = new int [] {1,4,6,9,10}; for (int x=0;x<arr.length ;x++ ) { //数组中有一个属性可以直接得到元素的个数,length //System.out.print("arr["+x+"]="+arr[x]+", "); System.out.print("arr["+x+"]="+arr[x]+", "); } System.out.println(); } } 输出结果: D:\Skill\JAVA\2017>java shuzu2 arr[0]=1, arr[1]=4, arr[2]=6, arr[3]=9, arr[4]=10, D:\Skill\JAVA\2017> 3、数组中的元素求和 例: class shuzu2 { public static void main(String[] args) { int [] arr = new int [] {1,4,6,9,10}; int sum=0; //定义一个变量用来记住循环内部加法的和。 for (int x=0;x<arr.length ;x++ ) { sum=arr[x]+sum; //可以简写为:sum+=arr[x],将数组内所有元素相加。 } System.out.println("sum="+sum); System.out.println("我真牛逼!!!!"); } } 4、使用函数定义功能 例:定义一个功能,用于打印数组中的元素,元素间用,号隔开。使用函数的方式实现。 class shuzu2 { public static void main(String[] args) { int [] arr = new int [] {1,4,6,9,10}; suzu (arr); System.out.println("我真牛逼!!!!"); } public static void suzu (int []a) { for (int x=0;x<a.length ;x++ ) { if (x!=a.length-1) //使用if语句排除掉最后一个逗号,如果x不等于最后一个元素的角标值则打印的带逗号,否则直接打印元素并回车。 System.out.print("arr="+a[x]+","); else System.out.println("arr="+a[x]); } } } 5、获取数组中值最大的元素: 给定一个数组{1,2,4,6,9,3}; 1、获取数组中的最大值 分析思路: 1、互相比较,每一次比较都有一个较大的值,因为该值不确定,通过一个变量来存储。 2、让数组中的每一个元素都和这个变量中的值进行比较。如果大于了变量中的值,就用该变量记录较大的值。 3、当所有的元素都比较完成,那么该变量中存储的就是数组中的最大值了。 步骤: 1,定义变量,初始化为数组中的任意一个元素即可。 2、通过循环语句对数组进行遍历 3、在遍历过程中定义判断条件,如果遍历到的元素比变量中的元素大,就赋值给该变量。 需要定义一个功能来完成,以提高复用性。 1、明确结果,数组中的最大元素int 2、未知内容:一个数组 int [] 例:记录元素的方式 class shuzu2 { public static void main(String[] args) { int [] arr = new int [] {1,4,60,9,10}; suzu (arr); System.out.println("我真牛逼!!!!"); } public static void suzu (int a[]) { int max= a [0]; //定义一个变量来存储最大元素 for (int x=0;x<a.length ;x++ ) { if (max < a [x]) //判断max是否小于a[x] { max = a [x]; //如果max小于a[x]则将值付给max,记录了最大的元素。 } } System.out.println("MAX="+max); } } 例2、记录角标的方式 class shuzu2 { public static void main(String[] args) { int [] arr = new int [] {1,4,60,9,10}; int Max=suzu (arr); //调用函数suzu并传入arr数组,然后将返回值付给Max。 System.out.println("MAX="+Max); System.out.println("我真牛逼!!!!"); } public static int suzu (int a[]) { int max=0; //定义一个max变量并赋值为0,该值为下面a数组的0角标。 for (int x=1;x<a.length ;x++ ) { if (a [max] < a [x]) //第一次循环时,用该数组的0角标上的元素和1角标上的元素进行比较。后面循环以此类推。 { max =x; //记住最大值得角标。 } } return a[max]; //返回最大值的角标 } } 6、选择排序: 思路:遍历、条件语句、第三方变量。 数组角标1循环向后比较,每次都少一个比较值,相当下图 **** *** ** * 也就是大圈套小圈的for嵌套循环。 如果想打印出排序后的结果。 可以使用数组 特点:内循环结束一次,最值出现在0角标未知。 例:选择排序 class shuzu3 { public static void main(String[] args) { int [] arr = new int [] {1,4,6,99,10}; System.out.println("排序前"); prin (arr); tst (arr); System.out.println("排序后"); prin (arr); } //定义一个打印数组列表的方法。 public static void prin (int prin []) { for (int x=0;x<prin.length ;x++ ) { if (x!=prin.length-1) { //定义一个条件,给数字后面加上逗号,如果是最后一个数字不加逗号并且换行。 System.out.print(prin[x]+" "); //如果x不等于数组中的最后一个数组打印数字并加逗号 else System.out.print(prin[x]); //如果x不满足上面条件打印x } System.out.println(); //换行操作。 } //选择排序循环 public static void tst (int arr[]) { for (int x=0;x<arr.length ;x++ ) { for (int y=x+1;y<arr.length ;y++ ) /* 因为x=0是0角标,所以y应该是1,但是当内循环完成后, 当再次进入内循环时,y仍然等于1,所以y必须要等于x+1 才能保证每次x都是和后面一个角标进行比较 */ { if (arr[x]>arr[y]) { int temp=arr[x]; arr[x]=arr[y]; arr[y]=temp; //通过使用temp第三方变量的方式是数组中的元素进行换位操作。 } } } } } 7、冒泡排序 class shuzu5 { public static void main(String[] args) { int [] maopao = new int [] {1,3,5,4,6,7,9}; System.out.println("排序前"); // Arrays.sort(maopao); printarry (maopao); arrypaixu (maopao); System.out.println("排序后"); printarry (maopao); } //定义一个方法,实现角标的排序 public static void arrypaixu (int [] maopao) { for (int x=0;x<maopao.length-1 ;x++ ) { //maopao.length-1表示最后一个数值不用比较。外循环定义比较次数。 for (int y=0;y<maopao.length-x-1 ;y++ ) {//-x:表示每次都减少一个比较的数值,-1表示最后的数值不用比较。定义比较数值。 if (maopao[y]>maopao[y+1]) { //设立条件,第y个角标和第y个角标+1进行比较。如果是小于则为倒序。 int temp=maopao[y]; //角标换位 maopao[y]=maopao[y+1]; maopao[y+1]=temp; } } } } public static void printarry (int [] maopao) { for (int x=0;x<maopao.length ;x++ ) //定一个循环语句进行遍历, { if (x!=maopao.length-1) { //定义一个条件,给数字后面加上逗号,如果是最后一个数字不加逗号并且换行。 System.out.print(maopao[x]+", "); } //如果x不等于数组中的最后一个数组打印数字并加逗号 else System.out.print(maopao[x]); //如果x不满足上面条件打印x } System.out.println(); //换行操作。 } } /* 冒泡和选择排序效率比较低,因为都是在堆内存中进行的。 */ 8、上面两个例子中都出现了数组元素对调的功能,所以直接定义成一个包含该功能的函数 //数组元素位置对调函数。 public static void swap (int [] arr, int a, int b) { if (arr[a]>arr[b]) { int temp=arr[a]; arr[a]=arr[b]; arr[b]=temp; } } 9、数组的查找,查找一个元素在数组中的位置。 例1:普通查找 class shuzu3 { public static void main(String[] args) { int [] arr = new int [] {1,4,6,99,10}; int getnum = search (arr,99); System.out.println("GetNum="+getnum); } //定义一个遍历数组,并判断传入的key的角标,然后返回该角标的函数。如果该元素不存在则返回-1。 public static int search (int arr [],int key) { for (int x=0;x<arr.length ;x++ ) { if (arr[x]==key) return x; } return -1; } } 例2、折半查找方法1 class shuzu6 { public static void main(String[] args) { //当数组中有两个相同的数值时,找到的是第一个出现的值。 int [] arr=new int []{1,2,3,4,5,6,7,9}; int b=zheban (arr,30) ;//定义一个折半查找的数值 System.out.println("b="+b); //打印查找出来的数值。 System.out.println("================================="); } /* 折半查找确定范围。只能查找有序的数组。 */ public static int zheban(int []arr, int key) { //定义一个方法,用来查找数组中数值的位置。 int min,mid,max ;//定义最小值,中间值,最大值,来判断数值所在的范围。 min =0; //起始最小值为0 max=arr.length-1; //最大值等于,数组个数-1。 mid=(min+max)/2 ;//中间值,等于最小值加最大值除2. while (key!=arr [mid]) //使用while语句直接判断循环条件。 { if (key>arr[mid]) //使用条件选择语句,判断范围。 min=mid+1; //使最小值上的指针向右移动 else if (key<arr [mid]) //不知道是否能够直接写else,而不写else if??? max=mid-1 ;//使最大值的指针向做移动。 if (min>max) //当输入的数值大时,会陷入死循环,因为key永远不等于arr [mid] return -1 ;//返回一个-1表示,数值不存在。 mid=(min+max)/2; //第二次折半查找。 //注意上面的key不要写成arr[key],因为key是一个数值,而不是角标。 } return mid; //返回的中间值即使,数值所在的位置。 } } 例2、折半查找方法2 class shuzu6 { public static void main(String[] args) { //当数组中有两个相同的数值时,找到的是第一个出现的值。 int [] arr=new int []{1,2,3,4,5,6,7,9}; int c=zheban2 (arr,3); System.out.println("c="+c) ;//打印查找出来的数值。 } //普通查找,一个一个数值查找 //定义一个查找数组的功能。一个未知的数组,和一个未知的要查找的数。 public static int getshuzu (int [] arr,int key) { //查找一个数值在数组中的位置。 for (int x=0;x<arr.length;x++ ) //遍历数组, { if (arr[x]==key) //如果这个数组中的数值和key相等返回X { return x; } } return -1;//如果没有默认返回-1 } /* 第二种折半方式 */ public static int zheban2 (int []arr , int key) { int min =0 ,max=arr.length-1, mid; while (min<=max) //当最小值小于等于最大值的时候循环 { mid =(min+max)/2; //当中间值等于先进行折半,找出中间值。 if (key>arr[mid]) //如果要查找的值大于了中间值 min=mid+1; //最小值向右移动,等于中间值加一 //否则如果,要查找的值小于了中间值,最大值的指针向左移动。最大值=mid-1 else if (key<arr[mid]) max=mid-1; else return mid; } return -1; } 例3: class shuzu6 { public static void main(String[] args) { //当数组中有两个相同的数值时,找到的是第一个出现的值。 int [] arr=new int []{1,2,3,4,5,6,7,9}; int d=zheban3 (arr,8); //定义一个折半查找的数值 System.out.println("d="+d); //打印查找出来的数值。 } /* 面试题练习,有一个数值,找到这个数值应插入数组中的位置,并使数组有序。 思路,需要进行遍历,查找数组,并且判断这个数值应该大于min并且小于max, 也就是mid,但是这个mid是循环后最后一个mid。 */ public static int zheban3 (int [] arr, int key) { int min=0, max=arr.length-1, mid; while (min<=max) { mid=(min+max)/2; if (key>arr[mid]) min=mid+1; else if (key<arr[mid]) max=mid-1; else return mid ; } return min; //当返回最小值时既是这个数值应插入的位置。 } } 10、进制转换 例1、十进制转二进制 class shuzu3 { public static void main(String[] args) { to2 (2); } public static void to2 (int num) { StringBuffer SB= new StringBuffer (); //定义一个容器用来存储num % 2的结果 while (num>0) { SB.append(num % 2); //将num % 2的结果存到容器中 num = num /2; } System.out.println(SB.reverse()); //翻转打印SB.reverse()的内容 } } 例2、十进制转换十六进制 class shuzu3 { public static void main(String[] args) { to16 (60); } public static void to16 (int num) { for (int x=0;x<8 ;x++ ) //因为一共是8个4位,所以右移做多8次。 { int temp = num & 15; //temp是num&15的结果。 if (temp>9) System.out.print((char)(temp-10+'A')); else System.out.print(temp); num = num >>>4; //num是传入的值右移4位的结果。 } } } 十进制==>>十六进制 取最低4位,算一个值,再取下一个四位,算一个值 60的二进制:0000-0000 0000-0000 0000-0000 0011-1100 0000-0000 0000-0000 0000-0000 0011-1100 ==>>60 & 0000-0000 0000-0000 0000-0000 0000-1111 ==>>15 --------------------------------------------------------------------------------- 0000-0000 0000-0000 0000-0000 0000-1100 ==>>12==>>C 0000-0000 0000-0000 0000-0000 0011-1100 >>>无符号右移 --------------------------------------------------------------------------------- 0000-0000 0000-0000 0000-0000 0000-0011右移后等于3 60的十六进制为3C 输出结果: D:\Skill\JAVA\2017>java shuzu3 C3000000 D:\Skill\JAVA\2017> 例3、因为例2的输出结果不理想继续优化。 class shuzu3 { public static void main(String[] args) { to16 (60); } public static void to16 (int num) { StringBuffer SB = new StringBuffer(); //定义一个SB的容器用来存储每次循环的值 for (int x=0;x<8 ;x++ ) //因为最多8个4位所以,最多循环8次 { int temp = num & 15; //temp是num&15的结果。 if (temp>9) //因为从10-15是A-F SB.append ((char)(temp-10+'A')); //使用容器SB存储temp的值,当大于9时,强制转换为字符。 else SB.append (temp); //使用容器SB存储temp的值 num = num >>>4; //num是传入的值右移4位的结果。 } System.out.println (SB.reverse()); } } 输出结果: D:\Skill\JAVA\2017>java shuzu3 0000003C D:\Skill\JAVA\2017> 例4、因为例3的输出结果还是带了很多没用的0,使用 查表法继续优化。 十六进制程序三:查表法 0,1,2,3,4,5,6,7,8,9,A, B, C, D, E, F 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 任何数与上15结果都在15之内。 可以把0-F的十六进制数存到一个数组的表里面。并且使用与15的结果,和右移的结果去找 数组表中角标对应的数字。 例如:60的十六进制3C C对应的是与完15后12对应的值,3是右移后对应的值。 思路: 可以通过数组的方式建立一个表。 class shuzu3 { public static void main(String[] args) { to16 (60); } public static void to16 (int num) { char [] chs = {'0','1','2','3','4', '5','6','7','8','9', 'A','B','C','D','E','F'}; //定义一个char类型的数组,因为里面有数字也有字母。 char [] chr = new char [8]; //因为只有8个4位所以定义数组的长度为8,用来存储查表出来的值。 int pos = 0; //定义一个指针,用来确定num & 15的结果所在的角标的值。 while (num!=0) //当num不等于0时循环,num是传入的值,(也即是4个8位的值不能全是0) { int temp = num & 15; //定义一个temp变量,用来存储num & 15这个角标值。 chr [pos++] = chs [temp]; //因为pos的角标是不断增加的,所以必须要pos++(后加) num = num >>>4; } for (int x=pos-1;x>=0 ;x-- ) //因为 x=pos-1所以是倒着打印的。从最大角标值向最小值循环。 /*因为这时的pos时有效值加1的位置,所以必须要减1(只打印有效位), 并且, 1、角标是顺序存储的,所以正常顺序需要从最大角标值打印。 2、如果从chr.length打印会出现空位。 */ { System.out.print(chr[x]); } } } 例5、十六进制的数组表中包含了二进制、八进制数 将二进制查表法和十六进制查表法融合。 num是要转换的数,base是要与上的数,offset是要右移的位数 二进制要与的数是1,右移1位; 十六进制要与的数是15,右移4位; 8进制要与的数是7,右移3位; class shuzu3 { public static void main(String[] args) { to2(60); to8(60); to16(60); } public static void JZZH (int num, int base, int offset) //num传入的数值,base&的值,offset右移的值。 { char [] chs = {'0','1','2','3','4', '5','6','7','8','9', 'A','B','C','D','E','F'}; //定义一个char类型的数组,因为里面有数字也有字母。 char [] chr = new char [32]; //因为最多有32个二进制位所以定义数组的长度为32,用来存储查表出来的值。 int pos = 0; //定义一个指针,用来确定num & 15的结果所在的角标的值。 while (num!=0) //当num不等于0时循环,num是传入的值 { int temp = num & base; //定义一个temp变量,用来存储 num & base 这个角标值。 chr [pos++] = chs [temp]; //因为pos的角标是不断增加的,所以必须要pos++(后加) num = num >>>offset; } for (int x=pos-1;x>=0 ;x-- ) //因为 x=pos-1所以是倒着打印的。从最大角标值向最小值循环。 /*因为这时的pos时有效值加1的位置,所以必须要减1(只打印有效位), 并且, 1、角标是顺序存储的,所以正常顺序需要从最大角标值打印。 2、如果从chr.length打印会出现空位。 */ { System.out.print(chr[x]); } } public static void to2 (int num) { JZZH(num,1,1); System.out.println(); System.out.println("二进制"); } public static void to8 (int num) { JZZH(num,7,3); System.out.println(); System.out.println("八进制"); } public static void to16 (int num) { JZZH(num,15,4); System.out.println(); System.out.println("十六进制"); } } 11、二维数组 例1、 class shuzu { public static void main(String[] args) { int [] [] arr = new int [3] [4]; arr[0] [0] = 100; arr[1] [3] = 200; arr[2] [2] = 300; int [] [] arr1 = new int [3] []; System.out.println("Arr第一个小数组的第1个元素 "+arr[0][0]); System.out.println("Arr第二个小数组的第4个元素 "+arr[1][3]); System.out.println("Arr第三个小数组的第3个元素 "+arr[2][2]); System.out.println("Arr1第三个小数组的第3个元素 "+arr1[2][2]); //因为只初始化了二维数组的长度,没有初始化二维数组中一维数组的长度,所以当打印一维数组时返回值为NULL } } 输出结果: D:\Skill\JAVA\2017>java shuzu Arr第一个小数组的第1个元素 100 Arr第二个小数组的第4个元素 200 Arr第三个小数组的第3个元素 300 Exception in thread "main" java.lang.NullPointerException at shuzu.main(shuzu.java:15) D:\Skill\JAVA\2017> 例、二维数组中的元素求和(for嵌套循环) class shuzu { public static void main(String[] args) { int num = 0; int [] [] arr = {{1,2,3},{3,2,1},{4,5,6}}; for (int x=0;x<arr.length ;x++ ) //确定二维数组长度为arr.lgenth { for (int y=0;y<arr[x].length ;y++ ) //确定一维数组长度为arr[x].length { num = num + arr[x][y]; //求和。 } } System.out.println("Arr的元素和为: "+num); } } 特殊格式说明: int [][]y; 二维数组 int []y[]; 二维数组 int []x,y[];这个相当于: int []x; int[]y[]; 也就是定义了一个一维数组x;和一个二维数组y。 例、 a. x[2]=y; 这句话的意思是把y这个二维数组赋值给x这个一维数组,肯定是错误的。 b. y[0]=x; 这句话的意思是把x这个一维数组赋值到y这个二维数组,肯定OK c. y[0][0]=x; 这句话的意思是把一维数组对y二维数组中的元素,肯定错误 d. x[0][0]=y; 这句话的意思是把y这个二维数组赋值给x二维数组中的一个元素,明显不对。因为x是一维数组。

    最新回复(0)