黑马程序员--java基础复习之数组

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------</span>


   在刚开始学习数据类型的时候,我们就学习过了八种基本数据类型   byte   short   int   lang  float    double  char  boolean  ,还有就是三种引用类型,第一个就是数组,以及类和接口。

   首先,是数组的定义,数组是同一类型数据的集合。其实就是一个容器,就是用于存储数据的地方。数组的好处就是可以自动给数组中的元素从0开始编号,这样方便于操作元素。如同每个班里的学生都有一个学号一样,方便管理学生。

   然后是数组的定义格式。

第一种:元素类型[]  数组名 = new  元素类型[元素个数或数组长度];

例如:

int[]  arr=new int[3];

这表示的是定义了一个数据类型为int,长度为3的数组,它的元素角标是从0开始的,最后一个角标为2。

第二种:元素类型[]  数组名 = new 元素类型[]{元素1,元素2,....};

例如:

int[] arr=new arr[]{5,4,16};
int[]  arr1={7,5,9};
上面两行代码都表示定义了一个长度为3的int类型的数组,并且都初始化了值


数组在内存中的表现形式

int []  x=new int[3];

上面这句代码在内存中是这样的,如图:


和局部变量不一样,引用型变量x是存放在栈内存中的,而数组是先分配一个地址值,然后在堆内存中开辟出一片空间,这时数组中的元素就已经有了默认初始化值。int类型默认初始化值为0,boolean 类型为false,String 类型为null.然后将这个地址值赋值给变量x,即x指向了堆内存中的这个数组。当给数组中的第一个元素x[0]赋值为59时,在堆内存中数组的第一个元素的值就修改为59,如上图。当我们将null 赋值给引用型变量x时,即 x=null时,栈内存中x的值就变成了null,就不再指向数组在堆内存的地址,那么,堆内存中的这个数组就变成没用的了,因为没有变量再指向它了,那么java就会调用垃圾回收机制来回收它了。

那么下面说栈内存和堆内存的作用和区别

栈内存:用于存储局部变量,当数据使用完,所占空间会自动释放。

堆内存:A、数组和对象,通过new建立的实例都存放在堆内存中。
                B、每一个实体都有内存地址值。
                C、实体中的变量都有默认初始化值。
                D、实体不再被使用,会在不确定的时间内被垃圾回收器回收。


小细节:1、以下这两种定义数组的方式都可以,效果是一样的,推荐使用第一种

int[] arr=new int[2];
int arr1[] =new int[2];

2、静态初始化数组时,不要写长度,如下

int[]   arr=new int[3]{1,8,6};



操作时常见问题

1、角标越界异常(ArrayIndexOutOfBoundsException ),如下图


其中,ArrayIndexOutOfBoundsException ,这个就是数组角标越界异常,这是因为操作数组时,访问到了数组中不存在的角标。如代码中所示,长度为3的数组,最大的角标位为2,而不是3。

2、空指针异常(NullPointerException) ,如图


当将null的值赋给arr时,arr的地址值就不再指向数组在堆内存中的位置了,所以用arr来操作数组中的元素时就会出现这个异常。NullPointerException:空指针异常,当引用没有任何指向值为null的情况,该引用还在用于操作实体。

数组的常见操作

1、数组的遍历

class ArrayDemo
{
	public static void main(String[] args)
	{
		//数组的遍历操作:获取数组中的元素
		//定义一个长度为3的数组
		int[] arr=new int[3];
		for(int x=0;x<3;x++)
		{
			System.out.println("arr["+x+"]="+arr[x]);
		}
	}
}

定义了一个长度为3的数组,但是并没有给其中的元素赋值,结果:

 可以看出,int类型数组默认初始化值为0。

数组有一个属性length,可以获取数组的长度

class ArrayDemo
{
	public static void main(String[] args)
	{
		//数组的遍历操作:获取数组中的元素
		//length:获取数组中元素的个数,使用方式:数组名.length
		//定义一个长度为3的数组
		int[] arr=new int[]{3,5,7,13,6,88};
		for(int x=0;x<arr.length;x++)
		{
			System.out.println("arr["+x+"]="+arr[x]);
		}
	}
}

结果:

下例

<span style="font-size:12px;">class ArrayDemo
{
	public static void main(String[] args)
	{
		//数组的遍历操作:获取数组中的元素		
		int[] arr=new int[]{3,5,7,13,6,88};	
		printArray(arr);
	}
	
	//功能:打印数组中的元素,元素间用逗号隔开
	static void printArray(int[] arr)
	{
		System.out.print("[");
		for(int x=0;x<arr.length;x++)
		{
			if(x!=arr.length-1) //当前元素不是最后一个元素时
				System.out.print(arr[x]+",");
			else
				System.out.println(arr[x]+"]"); //当遍历到最后一个元素时,不加逗号
		}
	}
}</span>
结果:


2、获取数组中的最值(最大值、最小值)

<span style="font-size:12px;">/*
获取数组中的最值

给定一个数组{6,8,4,1,14,25}

*/

class ArrayTest2
{
	public static void main(String[] args)
	{
		int[] arr=new int[]{6,8,4,1,14,25};
		int max=getMax(arr);
		System.out.println(max);
	}
	
	/*
	需求:获取数组中的最大值,以及最小值
	获取数组中的最大值
	思路:1、获取最大值需要进行比较,每一次比较都会有一个较大的值。因为该值不
	不确定,所以定义一个变量用来存储这个较大值。
	2、通过遍历,让数组中的元素分别和这个变量的值进行比较,若值大于该变量的值,则
	该变量存储这个较大的值。
	3、循环完成后,所有的元素都比较完成,那么该变量存储的就是数组中的最大值了。
	*/
	public static int getMax(int[] arr)
	{
		int max=arr[0];
		//从角标1的位置开始,因为max初始化值为arr[0],所以max不用和arr[0]比较。
		for(int x=1;x<arr.length;x++)
		{
			if(max<arr[x])  //若数组中的元素值大于max的当前值,则将此元素的值赋给max
				max=arr[x];
		}
		return max;
	}
}</span>

结果:



3、选择排序

原理:将数组中第一个元素同其他元素比较大小,得到最小值并放成0标上.然后继续在剩下的元素中寻找第二个最小元素,放在第二个位置。依此类推。就能得到排序结果。

代码如下

<span style="color:#666666;">class ArraySortDemo
{
	public static void main(String[] args)
	{
		int[] arr=new int[]{5,6,4,15,25,1,8,95};
		
		printArray(arr);  //排序前
		ArraySelectSort(arr);  //打印数组
		printArray(arr); //排序后
					
	}
	
	/*
	选择排序
	*/
	static void ArraySelectSort(int[] arr)
	{
		//外循环遍历数组
		for(int x=0;x<arr.length-1;x++)
		{
			//内循环比较大小
			for(int y=x+1;y<arr.length;y++)
			{
				//定义一个第三方变量,便于元素交换位置
				int temp;
				//若前一个元素比后一个元素大,则两元素互换位置
				if(arr[x]>arr[y])
				{
					temp=arr[x];
					arr[x]=arr[y];
					arr[y]=temp;
				}
					
			}
		}
	}
//打印数组
	static void printArray(int[] arr)
	{
		if(arr!=null)
		{
			System.out.print("[");
			//遍历数组
			for(int x=0;x<arr.length;x++)
			{
				if(x!=arr.length-1)				
					System.out.print(arr[x]+",");				
				else
					System.out.print(arr[x]);				
			}
			System.out.println("]");
		}
	}

}</span>
输出结果:


4、冒泡排序

原理:  1、先从头角标相邻两个元素之间进行比较,取较大值存放在后一个元素中,然后再与后一个元素的进行比较,直至最大值存放到最后一个元素中。 
    2、再重复1操作,每次计较次数减一,一圈比完后存放的较大元素不再参与比较。 

代码如下:

class ArraySortDemo
{
	public static void main(String[] args)
	{
		int[] arr=new int[]{5,6,4,15,25,1,8,95};
						
		
		printArray(arr);  //排序前
		ArrayBubbleSort(arr);  //打印数组
		printArray(arr); //排序后
		
	}
        //对数组冒泡排序
	//从角标0开始,相邻两个元素进行比较,符合条件就互换位置,每轮下来,最值出现在数组最后一个位置上。
	//依此类推,每轮要比较的个数少一个。
	static void ArrayBubbleSort(int[] arr)
	{
		for(int x=0;x<arr.length-1;x++)
		{
			for(int y=0;y<arr.length-(x+1);y++)
			{
				if(arr[y]>arr[y+1])
				{ 
					int temp;
					temp=arr[y];
					arr[y]=arr[y+1];
					arr[y+1]=temp;					
				}
			}
		}
	}
	
	//打印数组
	static void printArray(int[] arr)
	{
		if(arr!=null)
		{
			System.out.print("[");
			//遍历数组
			for(int x=0;x<arr.length;x++)
			{
				if(x!=arr.length-1)				
					System.out.print(arr[x]+",");				
				else
					System.out.print(arr[x]);				
			}
			System.out.println("]");
		}
	}

}

结果:


5、折半查找(两种折半方式,及一个整数返回插入有序数组后的位置)

class ArrayTest
{
	public static void main(String[] args)
	{
		int[] arr={5,6,1,4,8,7,14,23};
		int[] arr1={2,4,6,7,9,10,15,25,725};
		//int index=getIndex(arr,14);
		//折半查找一
		int index=halfSearch(arr,22);
		//折半查找二
		int index1=halfSearch_1(arr,22);
		//向有序数组中插入一数,得到该数的角标位置
		int index2=halfSearch_2(arr1,22);
		System.out.println(index+":"+index1+":"+index2);		
	}
	
	/*
	折半查找:提高效率,但是必须保证该数组是有序的数组。
	第一种
	*/	
	static int halfSearch(int[] arr,int key)
	{
		int min,mid,max;
		min=0;
		max=arr.length-1;
		mid=(min+max)/2;
		
		while(arr[mid]!=key)
		{
			if(arr[mid]>key)
			{
				max=mid-1;				
			}
			else
			{
				min=mid+1;
			}
			mid=(min+max)/2;
			if(min>max)
				return -1;
		}
		return mid;
	}
	
	/*
	折半查找
	第二种方式
	*/
	public static int halfSearch_1(int[] arr,int key)
	{
		int min=0,max=arr.length-1,mid;
		while(arr[min]<=arr[max])
		{
			mid=(min+max)>>1; //等同于除以2
			if(arr[mid]>key)
				max=mid-1;
			else if(arr[mid]<key)
				min=mid+1;
			else
				return mid;
		}
		return -1;
	}
	
	/*
	向一个有序的数组中插入一个数,插入后该数组依然是有序的
	原理:折半查找后,返回-1改成返回min的值,即是此数插入后的角标位置
	两种方式的结果一样
	*/
	public static int halfSearch_2(int[] arr,int key)
	{
		int min=0,max=arr.length-1,mid;
		while(arr[min]<=arr[max])
		{
			mid=(min+max)>>1; //等同于除以2
			if(arr[mid]>key)
				max=mid-1;
			else if(arr[mid]<key)
				min=mid+1;
			else
				return mid;
		}
		return min;
	}
	
	//从数组中查找某元素
	//参数:int类型数组,int类型元素
	static int getIndex(int[] arr,int key)
	{
		if(arr!=null)
		{
			for(int x=0;x<arr.length;x++)
			{
				if(arr[x]==key)
				return x;
			}
			return -1;
		}
			return -1;
	}
	
	
	
}

结果:


6、进制转换

代码如下:

class ArrayTest1
{
	public static void main(String[] args)
	{
		toBin(6);
		toHex(60);
		toHexBySearch(60);
		trans(60,15,4);
	}
	
	//十进制---->二进制
	static void toBin(int num)
	{		
	    //定义一个字符串缓存,用于存储转换结果
		StringBuffer sb=new StringBuffer();
		
		while(num>0)
		{
			sb.append(num%2);
			num=num/2;
		}
		System.out.println(sb.reverse());
	}
	
	//十进制转十六进制
	static void toHex(int num)
	{
		//定义一个字符串缓存,用于存储转换结果
		StringBuffer sb=new StringBuffer();
		for(int x=0;x<8;x++)
		{
			int temp=num&15;
			if(temp>9)
				sb.append((char)(temp-10+'A'));
			else sb.append(temp);
			
			num=num>>>4;
		}
		//使用字符串缓存的反转功能,输入结果的正确顺序
		System.out.println(sb.reverse());
	}
	
	/*
	查表法:将所有的元素临时存储起来。建立对应关系。
	*/
	static void toHexBySearch(int num)
	{
		char[] ch=new char[]{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
		
		char[] arr=new char[8];
		int pos=arr.length;
		while(num!=0)
		{
			int temp=num&15;			
			arr[--pos]=ch[temp];
			num=num>>>4;
			//System.out.println(arr[pos]);
		}
		for(int x=pos;x<arr.length;x++)
		{
			System.out.print(arr[x]+",");
		}
		System.out.println();
	}
	
	//进制转换
	//参数:要转换的数据,与的基数,偏移位数
	static void trans(int num,int base,int offset)
	{
		if(num==0)
		{
			System.out.println(0);
			return;
		}
		//通用查表数组
		char[] ch=new char[]{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
		
		//最大长度是二进制的32位
		char[] arr=new char[32];
		
		int pos=arr.length;
		//通过循环,倒序的方式向数组中插入
		while(num!=0)
		{
			int temp=num&base;			
			arr[--pos]=ch[temp];
			num=num>>>offset;
		}
		
		//从数组中实际位置开始输出(即第一个不为0的位置)
		for(int x=pos;x<arr.length;x++)
		{
			System.out.print(arr[x]);
		}
		
	}
}

二维数组

数组中的数组

形象比喻:以前的一维数组,就如同一个箱子,箱子里面有很多小格子,每一个小格子用于存放一个元素,箱子里格子的个数即是数组的长度。现在有一个大箱子,里面放的不是小格子,而是一个个里面有很多小格子的箱子。这个大箱子就是二维数组。而这个大箱子里小箱子的个数即为这个二维数组的长度

二维数组的定义格式

int[][]  arr=new int[2][4];  

这行代码的意思是定义一个名称为arr的二维数组,二维数组里有两个一维数组,每个一维数组的长度为4;


int[][]  arr=new int[2][];

这句代表定义了一个名称为arr的二维数组,里面有两个一维数组,每个一维数数的初始化值为null


int[][] arr={{2,4},{4,5,6},{44,8,2}};

定义一个名为arr的二维数组,该数组长度为3,其中的元素分别为{2,4},{4,5,6},{44,8,2}三个一维数组。


如下图,为二维数组与一维数组之间的关系判断



------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值