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是一维数组。