黑马程序员-----java基础之数组及堆和栈

来源:互联网 发布:java中框架的作用 编辑:程序博客网 时间:2024/06/07 18:20

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

 

数组


一、数组的概述
引述:当我们需要定义多个同一的数据类型来进行以后的运算的时候(例如,我们要需求是统计某公司的员工的工资),这是我们会定义很多的变量,但是这样极大的不便,所以java提供了数组给我们。
概述:数组是储存同一数据类型多个元素的集合,也可以将其看做是一个容器。数组可以存储基本数据类型,也可以存储引用数据类型。
定义数组的格式:
格式1:数据类型[]   数组名;例:int[] arr (建议使用此格式)
格式2:数据类型   数组名[]; 例:int   arr[]
二、数组的初始化
初始化的意义:在java中,数组必须先进行初始化才可以使用。所谓初始化,就是为每个数组分配内存空间,为数组中的元素分配内存空间,并为其赋初始值。
初始化的分类:
1、动态初始化:只给定长度,由系统给出初始值
动态初始化格式:数据类型[] 数组名 = new 数据类型[数组长度];
例:int[] arr = new int[3];
定义了一个int类型的数组,数组的长度为3,其实就是数组中有三个元素。
2、静态初始化:为每一个元素赋初值,由系统给定长度。
静态初始化格式:数据类型[] 数组名 = new 数据类型{元素1 ,元素2,.....元素n}
例:int[] arr= new int{1,2,3,4,5};
定义了一个int类型的数组,元素分别为1,2,3,4,5.
注意:这两种方式,只能使用一种,不能使用动静结合。
三、内存分配和堆栈
java虚拟机中大致分为五块内存
1、堆内存:简单来说,所有new出来的东西都存放在堆内存中
特点:a、每个new出来的东西在堆中都会为其分配一个地址值
  b、每个变量都会有一个默认的值
byte,short,int,long 默认为0
float,double默认为0.0
char默认为’\u0000‘
boolean默认为false
引用数据类型默认为null
  c、当使用完毕之后就会变成垃圾,等待垃圾回收器对其回收
2、栈内存:存放的是局部变量
局部变量:在方法定义中和方法声明上的变量都是局部变量
tedian 
3、方法区(在面向对象时再详细解释)
4、本地方法区(和系统相关,在这里不做解释)
5、寄存器(和CPU相关,这里不做解释)
下面我们用图形和代码来演示一下数组在内存中的存储过程:


解释:首先,将main方法的字节码文件加载到方法区,然后方法进栈,arr这个变量就在栈内存中,又因为new了一个数组,所以堆内存中会出现一个数组,并未其分配地址值,在这里我们假设为0x0001,然后因为是动态初始化,所以数组的长度确定了为3,也就是的三个元素,系统会为每个元素分配空间,在0x0001之下,再然后为是三个元素赋系统默认的初始值,因为是int类型的,所以默认为0。然后将0x0001赋给arr,arr就指向了这个数组。再之后我们为每个元素人为的赋值,分别为1,2,3,所以初始值0被覆盖掉,变为1,2,3.


四、数组的练习

下面我们来学习一下对于数组的常用方法:

1、遍历数组:

public static void sop(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.print(arr[x] + ",");
}
}
System.out.println();
}

解释:定义一个方法,用来封装代码,参数类型是数组,这样程序的运行结果是[元素1 ,元素2,元素3,、、元素n]

if的作用是判断是否是最后一个元素,是就加上"]",不是就加上",".。


2、排序:
a、冒泡排序 
原理:两个相邻的数字进行比较,然后按比较规则互换位置,依次比较,第一次完毕,最大(最小)的会在最后一个索引处

代码示例:

public static void sort1(int[] arr){
for(int a = 0 ; a <arr.length-1; a++){
for(int b = 0 ; b < arr.length - 1 -a ; b++){
if(arr[b] > arr[b+1]){
int temp = arr[b];
arr[b] = arr[b+1];
arr[b+1] = temp;
}
}
}
}

解释:外循环决定比较的次数,内循环决定比较后的结果,每次比较之后都会少一个数,所以外循环的次数越多,内循环的次数就越少。

b、选择排序

原理:从0索引处开始,依次和后面的比较,按比较规则,一次完毕之后,最大的(最小的)会在第一个索引处。

代码示例:

public static void sort2(int[] arr){
for(int index = 0 ; index < arr.length -1 ; index++){
for(int b = 1 + index ; b < arr.length  ; b++){
if(arr[index] < arr[b]){
int temp = arr[index];
arr[index] = arr[b];
arr[b] = temp;
}
}
}
}

解释:外循环是决定每个索引处的数据的比较,内循环是把外循环提供的索引处数据和其之后的索引处数据比较,外循环的次数越多,内循环的比较次数就越少。

3、二分查找法

原理:每一次都从中间的索引开始查找,比较大了或者小了就可以减少一半的元素。

前提是数组必须是有序的。

代码示例:

public static int binarySearch(int x,int[] arr){
int maxIndex = arr.length - 1;
int minIndex = 0;

while(maxIndex >= minIndex){
int midIndex = (maxIndex + minIndex) / 2;
if(x == arr[midIndex]){
return midIndex;
}else if(x > arr[midIndex]){
minIndex = midIndex + 1 ;

}else if (x < arr[midIndex]){
maxIndex = midIndex - 1;

}
}
return -1 ;
}

解释:首先判断中间索引处的元素是否和传递进来的元素相等,相等则返回中间索引。如果大于中间索引,就把最小索引变成中间索引加一,然后再产生新的中间索引,如此循环,直到找到指定数据并返回,反之相同。如果要找的数不在数组中,这样循环下去最大索引会超过最小索引,循环结束,返回-1.


五、二维数组

简单的说,二维数组就是每一个元素都是一维数组。

格式1:数据类型[][] 数组名 = new数据类型[m][n];

定义了一个二维数组,m表示二维数组中有m个一维数组,n表示每个一维数组中有n个元素。

注意:一下格式也可以定义二维数组

数据类型数组名[][] = new 数据类型[m][n];

数据类型[]数组名[] = new 数据类型[m][n];

这两种格式不建议使用。

格式2:数据类型[][] 数组名 = new 数据类型[m][];

这一次没有给出一维数组的元素个数,可以动态给出。

格式3:数据类型[][]  数组名= {{元素1 ,元素2},{元素1,元素2 },{元素1,元素2}};

这个格式属于静态初始化,我们给出数组的具体值,由系统给分配数组长度

二维数组内存图解:


解释:首先字节码文件到方法区,然后main方法进栈,然后new了一个二维数组,在堆内存中开辟一块空间,地址值为0x001(假设为),0x001中存放了两个地址值,初始化值都为null,同时堆内存还会再开辟两个空间,地址值分别为0x0001和0x0002,然后初始化值默认为0,然后把0x0001和0x0002赋给0x001,这样0x0001和0x0002就指向0x001,把null覆盖掉,再把0x001赋给arr,这样arr就指向了0x001,然后我们为每一个一维数组赋了值,分别是1,2,3,4,然后把0覆盖掉。这样arr就赋值完毕了。


本人也在学习之中,这个算是我作为与其他志同道合的朋友交流的一种方法,也作为我的一个笔记,如果有朋友看到之后发现我的错误和不足之处,请不吝赐教,学习编程是一条艰难的路,希望能和大家一起努力,相互进步。



0 0
原创粉丝点击