黑马程序员——java基础(面向对象)进制转换、数组、内存分析

来源:互联网 发布:桌游 淘宝 编辑:程序博客网 时间:2024/06/05 09:20

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


第四章:java基础(进制转换、数组、内存分析)

 



本章概述:

第一部分:进制转换

数据的表现形式

进制间转换

第二部分:数组

数组的概念

数组的应用

多维数组

数组工具类

第三部分:内存分析

java内存结构

内存操作原理

垃圾回收机制

 





 

第一部分:进制转换

1、数据的表现形式

1.1java中,整数的表现形式有三种,分别为十进制、八进制、十六进制

十进制:即我们平常用的数学进制,用数字0~9表示,数位每满十进一

八进制:用数字0~7表示,数位每满八进一位,数字前要用0标识

十六进制:用数字0~9a~f表示,数位每满十六进一位,数字前要加0x标识,表示这是一个十六进制的数。

二进制是计算机的物理进制,即计算机的所有运算都是基于电位开关的开关转换完成的

1.2负数的表现形式

java用二进制作基本数值表示时,将数值的第一位定义为符号位,如果符号位是0表示该数是正数,符号位为1时表示该数为负数。java中用正数的二进制取反加1表示正数对应的负数,如:-10


2、进制间转换

2.1二进制、八进制、十六进制转换成十进制

2.1.1其他进制转换成十进制原理都是一样的,即用原来数的每一位分别与进制的位数减一次方,再将每位乘得的结果相加。

如:二进制数:110001

 二进制: 1         1        0        0        0        1

                =1*2^5+1*2^4+0*2^3+0*2^2+0*2^1+1*2^0

十进制:=49


八进制数:02235

  八进制:    2        2        3        5

=2*8^3+2*8^2+3*8^1+5*8^0

十进制:    =1181


十六进制数:0xa5f

  十六进制:  a           5            f

十进制表示:10         5           15

=10*16^2+5*16^1+15*16^0

十进制:    =2655

2.2十进制转成其他进制

(1)同理,用十进制的数做逆向运算就可以得到其他进制的数值,但逆向除进制的位数幂在不知道该数值相应进制下的位数的情况下运算起来比较繁琐,所以可以用一个简单的方法进行转换,即递归除以进制数每次取其余数,将得到的余数队列反转就是十进制在该进制下的对应值。

如图:


这里举的例是将十进制的数值13转换成二进制,反向读取获得的余数则为13的二进制表示形式1101

(2)十进制转八进制和十六进制同理,只是将除数2换成8或者16这些进制元数而已,这里不再详述了。

2.3其他进制转换

二进制、八进制、十六进制之间的转换就比较简单了,因为三者存在倍数和位数的对应关系,如三位二进制数值恰好能完整表达一个八进制位,四个二进制位恰好能完整表达一个十六进制位,如下图所示(水印不要理会):

 

2.4用Java类中的方法进行进制转换计算

(1)三个十进制数值分别转成二进制、十六进制、八进制字符串的静态方法:

Integer.toBinaryString(int i):传入十进制的int值参数,返回表示转换成二进制数值的字符串

Integer.toHexString(int i):传入十进制的int值参数,返回表示转换成十六进制数值的字符串

Integer.toOctalString(int i):传入十进制的int值参数,返回表示转换成八进制数值的字符串

(2)其他进制转成十进制字符串的静态方法:

Integer.toString(int i, int radix):第一个参数是要转换成十进制的其他进制的数值,第二个参数表示第一个参数的进制基数

(3)代码如下:

<pre name="code" class="java">//创建一个类,命名Case(转换)class  Case{//主函数public static void main(String[] args) {//声明一个字符串变量,调用十进制转二进制的方法,将60的二进制结果赋给字符串变量String bin = Integer.toBinaryString(60);//按同样的方法将十进制数转成十六进制的字符串表示形式String hex = Integer.toHexString(60);//同理,十进制转八进制String oct = Integer.toOctalString(60);//将十六进制的3c转成十进制的字符串表示形式String dec = Integer.toString(0x3c,10);//用打印语句将获得的四个数值的字符串打印到控制台System.out.print("bin="+bin+"\r\nhex="+hex+"\r\noct="+oct+"\r\ndec="+dec);//\r\n是转义字符,这里表示的是windows平台的回车符,可以换行}}

 

 

 

第二部分:数组

1、数组的概念

数组是同一种类型数据的集合,是一个存储数据的容器

2、数组的应用

2.1、数组的声明

用“[]”符号声明一个数组,声明的格式为:

数据类型 [] 数组名;

或 :数据类型 数组名[]

2.2、数组的赋值

(1)直接在声明时赋值:

声明数组时赋值有3种形式:

数据类型 [] 数组名 = {元素1,元素2,···};

或者:数据类型[] 数组名 = new 数据类型[数组长度];

或者:数据类型[] 数组名 = new 数据类型[]{元素1,元素2···};

(2)声明后赋值:

数据类型[] 数组名;

数组名 = {元素,元素···};

或者:数据类型[] 数组名; 

数组名= new 数据类型[数组长度];

数组名[0] = 元素1;

数组名[1] = 元素2;

......

或者:数据类型[] 数组名;

数组名 = new 数据类型[]{元素1,元素2};

注意:这种赋值方式new后面的[]内不可以写数组的长度,数组长度由元素个数而定。

2.3、数组的元素带有编号,我们通常称为数组角标,数组角标从0开始到数组长度减一,数组的编号方便对数组的单个元素进行操作,不可以对超出定义范围的角标进行操作,否则系统会发生异常。

2.4数组有一个长度属性,可以调用“数组名.length”获取

代码展示如下:

//创建一个类,命名ArrayDemo(数值演示)class  ArrayDemo{//主函数public static void main(String[] args) {//声明一个int型的数组的几种方式int[] arr = {1,2,3};int[] arr1 = new int[]{4,5,6,7};//下面两种是先声明后赋值int arr2[] = new int[2];arr2[0] = 9;arr2[1] = 10;int[] arr3;arr3 = {11,12,13};//定义打印语句,将数组中的数值打印到控制台//注意:直接打印打印的是数组的内存地址的哈希码值System.out.println(arr);//定义循环语句通过操作角标打印,通过数组的length长度属性限定循环条件for (int x =0;x<arr.length ;x++ ){System.out.println(arr[x]);}}}


2.5根据数组的这些属性,可以对数组内的元素进行排序和查找数组内特定元素的操作

(1)数组元素的查找

顺序查找

按数组角标顺序查找

折半查找

每次查找排除上一次查找的一半的数据,这种查找比顺序查找快,但需要数组元素的排列是有序

不多说,直接上代码说明:

/*需求:演示顺序查找和折半查找*///创建一个类,命名SearchDemoclass  SearchDemo{//主函数public static void main(String[] args) {//声明一个数组,给数组赋有序的数值int[] arr = {3,4,6,12,22,32,33,36,43,53,62,67};//调用自定义的两个查找方法,如果找到,则返回该数值在数组中的角标,没有则返回-1,将返回值打印出来System.out.println(search(arr,53));//下面是折半查找System.out.println(halfSearch(arr,53));}//定义一个函数,实现在给定int类型的数组中查找元素的功能,参数是给定数组和要查找的元素public static int search(int[] arr,int val){//定义for循环,遍历数组for (int i = 0;i<arr.length ;i++ ){//如果遍历到的元素和给定义数值相等,则返回数组角标if(arr[i] == val)return i;}//如果没有找到,最后返回-1return -1;}//定义一个折半查找的函数,对给定义元素进行查找public static int halfSearch(int[] arr,int val){//定义查找数组的指针,分别定义最大角标、最小角标和中值int max=arr.length-1,min = 0,mid = (max+min)/2;//使用while循环,给定条件是最大角标要大于等于最小角标while(max>=min){//判断中值角标中的值是否等于给定数值,是则返回角标值if (arr[mid] == val){return mid;}//否则判断如果角标指向的数值大于给定数值,则向左折半else if (arr[mid]>val){//重新将中值赋给最大值max = mid;//再将中值折半,使查找范围缩小一半mid = (mid+min)/2;}//最后,给定值更大,则向右折半,原理同上,但由于int数值折半省略余数,所以可能永远也到达不了最大角标的位置,所以用加1处理else{min = mid;mid = (mid+max)/2+1;}}//找不到还返回-1return -1;}}


(2)数组元素的排序

选择排序

冒泡排序

老规矩,上代码:

/*需求:演示选择排序和冒泡排序*///创建一个类,命名SortDemoclass  SortDemo{//主函数public static void main(String[] args){//定义一个元素无序的数值int[] arr = {8,9,33,22,82,11,54};//分隔一下,以示区分System.out.println("arr排序前:");//调用自定义的遍历打印数值的函数,查看排序前的数值print(arr);//调用冒泡排序给数值排序bubbleSort(arr);//遍历打印数值查看排序结果System.out.println("arr排序后:");print(arr);//下面的是演示选择排序的,步骤同上面一样,不详述了int[] arr1 = {88,33,83,45,22,12,53};System.out.println("arr1排序前:");print(arr1);selectSort(arr1);System.out.println("arr1排序后:");print(arr1);}//定义冒泡排序的函数public static void bubbleSort(int[] arr){//逐个用前一位数值和后一位数值进行比较,将大的移动到后面,每一轮确定一个较大的数值,要比较的数值往前减一位for(int x=0;x<arr.length-1;x++){//每一轮x加1,则y的条件减1for(int y=1;y<arr.length-x;y++){//如果前一位比后一位数值大,则交换位置if(arr[y-1]>arr[y]){swap(arr,y-1,y);}}}}//定义选择排序的函数public static void selectSort(int[] arr){//用前面的数和后面的所有数比较一次,找出最小的一位放到前面的位置,然后角标位置前移一位继续如此比较for(int x=0;x<arr.length-1;x++){//和后面所有数值比较for(int y=x+1;y<arr.length;y++){//如果前面一位比后面的数值大,则交换位置if(arr[x]>arr[y]){//调用交换位置函数swap(arr,x,y);}}}}//定义一个交换元素的函数,以便功能代码的复用public static void swap(int[]arr,int x,int y){//定义一个临时变量,用于存储要交换的数据//将x的值赋给tempint temp = arr[x];//将y的值赋给xarr[x] = arr[y];//将temp(原x的值)的值赋给yarr[y] = temp;//完成交换位置过程}//定义一个遍历int类型数值的函数public static void print(int[] arr){for (int i = 0;i<arr.length ;i++ ){System.out.println(arr[i]);}}}


3、多维数组

3.1二维数组

3.1.1定义:二维数组即是数组里面装的还是数组,将数组的整体作为一个元素装到另一个数组中,那么这个装有数组的数组就称为二维数组。

3.1.2声明二维数组

数据类型[][] 数组名 = {数组1,数组2,···}

数据类型[]数组名[] = new 数据类型[子数组个数][子数组的长度]

3.2多维数组的实现跟二维数组的实现类似,就是在数组容器中不断嵌套数组容器的过程。

上代码:

/*需求:演示多维数组*///创建一个类,命名Arrayssclass  Arrayss{//主函数public static void main(String[] args){//声明两个二维数组int[][] arr = {{2,3,1},{5},{5,4,6,9};int[] arr1[] = new int[3][2];//给arr1赋值1、2、3、4······int x = 1;for (int i =0;i<3 ;i++ ){for (int j = 0;j<2 ;j++ ){arr1[i][j] = x++;}}//打印arr[2][2]的值System.out.println("arr[2][2]="+arr[2][2]);//遍历arr1for (int i =0;i<3 ;i++ ){for (int j = 0;j<2 ;j++ ){System.out.println(arr1[i][j]);}}}}


4、数组工具类Arrays

4.1数组工具类是专门用于对数组进行操作的工具类,里面封装了一些对数组进行复制、查找、排序等静态方法。

4.2Arrays方法

sort:对数组元素进行排序

equals:比较数组

binarySearch:折半查找

copyOf:复制数组

copyOfRange:指定范围复制数组

fill:将数组中指定范围的元素替换成同一个指定元素

equals:比较数组

toString:返回数组的字符串表示形式

toString:如果数组中的元素都是对象,那么将元素转到集合中,如果数组中的元素是基本数据类型,那么将数组转成集合中的一个对象


选两个做代码演示:

/*需求:数组工具类*///使用工具类需要在Java类库中导入该工具类import java.util.Arrays;//创建一个类,命名Arrayssclass  ArraysDemo{//主函数public static void main(String[] args){//声明一个个数组int[]arr = {2,3,1,5,4,6,9};//使用数组工具类中的toString方法获得数组的字符串形式String arrStr = Arrays.toString(arr);//打印数组元素System.out.println(arrStr);//用数组工具类中的Sort方法排序Arrays.sort(arr);//排序后打印元素arrStr = Arrays.toString(arr);System.out.println(arrStr);//使用fill方法替换元素Arrays.fill(arr,8);System.out.println(Arrays.toString(arr));}}





第三部分:内存分析

1、java内存结构

组成结构:栈内存、堆内存、方法区、本地方法区、寄存器

三个个需要重点关注的内存区:

栈内存:方法和局部变量存放的地方,分层,每层的方法独立串行运行,数据使用完,空间自动释放

堆内存:大致分为老生代、新生代和持久层,是存放对象的地方,数组和对象通过new关键字在堆内存中建立存放空间,每个对象实体都有内存地址值,实体中的变量都有默认初始化值,实体不再被引用,内存会在不确定的时间内被垃圾回收器回收。

方法区:存放静态数据、常量、字节码文件对象的区域。

2、内存操作原理

java虚拟机通过调用方法实现程序的运行,被调用的方法存放在栈内存中,每一个方法在栈内存中都有一个独立的栈帧,在方法中需要创建对象时,虚拟机会在堆内存中为对象开辟一块内存空间,将该内存的地址值引用给创建对象的方法,方法运行完毕内存会被释放用于重新加载数据。

3、垃圾回收机制

内存垃圾,即一些被创建的数据使用完后就不会在被使用了,但该数据依然占据着内存空间。java语言有很完善的内存管理机制,程序运行时JVM会不定时的启动垃圾回收机制对JVM运行时产生的不再被使用却占据着内存空间的数据进行清除,JVM使用的是混合的垃圾回收算法,在不同的情况下采用不同的算法对内存垃圾进行管理,垃圾回收算法有:标记垃圾回收、分代垃圾回收和增量垃圾回收。这使得java程序员可以不必耗费大量的时间和精力对内存进行管理,可以投入更多的精力在算法的优化上,当然java还会存在内存溢出的现象,这些将在深入学习后深入分析。

 

 

本章总结

本章主要对java语言的运行原理和基础数据的处理进行分析,了解java的数据存储和转换,结合前一章就能整理出java的整个命令体系和操作运行体系,在后期学习过程中如果遇到难以理解的问题可以根据java的运行机制思考程序的设计是否存在问题,从而利于问题的解决。本章还介绍了java学习的第一个对象——数组,以及对数组的操作,二维及多维数组的讲解,还介绍了一些基本的算法思想,如查找、排序的思路。以及工具类和方法的使用,后面的学习都是按照这样的思路进行扩展的。




------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

 




0 0