黑马程序员——003——函数、数组
来源:互联网 发布:二战德国实力 知乎 编辑:程序博客网 时间:2024/06/06 19:10
我们用一个小程序来开篇热身,也算是对上一小节的复习:
程序1:使用for循环打印九九乘法表。
——————————————————————————
class Demo3_1{ /* 程序1:使用for循环打印九九乘法表。 思路:采用嵌套循环的方式。 */ public static void main(String[] args) { for(int i=1;i<=9;i++) { for(int j=1;j<=i;j++)//关键是这里的j<=i,是最巧妙的地方 { //是用制表符\t,能够让排列更加对齐 System.out.print(j+"*"+i+"="+(i*j)+"\t"); } //当输出语句什么内容都不写的时候,就相当于一个换行符 System.out.println(); } }}
——————————————————————————
执行结果如下图:
——————————————————————————
如果我们有个需求就是只需要1到6的乘法表的话,程序该如何修改?如下:
——————————————————————————
class Demo3_2{ /* 程序2:只需要1到6的乘法表 思路:采用嵌套循环的方式+break语句。 */ public static void main(String[] args) { for(int i=1;i<=9;i++) { for(int j=1;j<=i;j++)//关键是这里的j<=i,是最巧妙的地方 { //是用制表符\t,能够让排列更加对齐 System.out.print(j+"*"+i+"="+(i*j)+"\t"); } //当输出语句什么内容都不写的时候,就相当于一个换行符 System.out.println(); if(i==6) break; //当循环执行完第六行,就是用break跳出for循环 } }}
——————————————————————————
执行结果如下图:
——————————————————————————
今天我们首先讲的是函数,我们前面也已经提到过,函数也可以做叫方法,因为它适用于解决问题的。
那么官方的定义就是:定义在类中的具有特定功能的一段独立小程序。也称方法。
——————————————————————————
格式:
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,…)
{
执行语句;
return返回值;
}
——————————————————————————
其中:
—返回值类型:函数运行后的结果的数据类型。
—参数类型:是形式参数的数据类型。
—形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数。
—实际参数:传递给形式参数的具体数值。
—return:用于结束函数。
—返回值:该值会返回给调用者。
——————————————————————————
特点:
—定义函数可以将功能代码进行封装,便于对该功能进行复用。
—函数只有被调用才会被执行。
—函数的出现提高了代码的复用性。
—对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行可以省略不写。
——————————————————————————
注意:
—①函数中只能调用函数,不可以在函数内部定义函数。
—②定义函数时,函数的结果应该返回给调用者,交由调用者处理。
——————————————————————————
如何定义一个函数?
—明确要定义的功能最后的结果是什么。
—明确在定义该功能的过程中,是否需要未知内容参与运算。
——————————————————————————
函数的一个重要特性——重载(override)
—概念:在同一个类中,允许存在一个以上的同名函数,只要它们的参数列表的个数或者参数类型不同即可。
—特点:与返回值类型无关,只看参数列表。
—好处:方便于阅读,优化了程序设计。
——————————————————————————
—示例:
//返回两个整数的和
int add(int x,int y){return x+y;}
//返回三个整数的和
int add(int x,int y,int z){returnx+y+z;}
//返回两个小数的和
double add(double x,double y){return x+y;}
——————————————————————————
什么时候用到重载?
当定义的功能相同,但参与运算的未知内容不同。那么,这时就定义一个函数名称以表示起功能,方便阅读,而通过参数列表的不同来区分多个同名函数。
——————————————————————————
那么现在再来看一个示例程序:
输出如下矩形(5*7):
- *
- *
- *
——————————————————————————
/*输出如下矩形(5*7):******** ** ** *********/class Demo3_3{ public static void main(String[] args) { for(int j=0;j<5;j++) { if(j==0 || j==4)//如果是首末行则输出七个* for(int i=0;i<7;i++) System.out.print("* "); else////如果不是首末行则输出头尾* { //打印出只有两的头的* System.out.print("* "); for(int k=0;k<5;k++) System.out.print(" "); System.out.print("* "); } //一行输出完换行 System.out.println(); } }}
——————————————————————————
执行结果如下图:
——————————————————————————
现在需求有所改变,又想要输出10*11的矩形,那么我们每次都需要回去修改源代码,非常的繁琐,因此这里就可以运用函数了。
我们把长宽变成两个参数,让调用函数的人使用参数传进去,如下则程序:
——————————————————————————
/*将输出矩形封装成方法,使用方法得到10*11矩形*/class Demo3_4{ public static void main(String[] args) { getRec(5,7);//输出5*7矩形 getRec(10,11);//输出10*11矩形 } static void getRec(int height,int width) { for(int j=0;j<height;j++) { if(j==0 || j==height-1)//如果是首末行则输出七个* for(int i=0;i<width;i++) System.out.print("* "); else////如果不是首末行则输出头尾* { //打印出只有两的头的* System.out.print("* "); for(int k=0;k<width-2;k++) System.out.print(" "); System.out.print("* "); } //一行输出完换行 System.out.println(); } }}
——————————————————————————
这就是函数在实际开发中的应用,我们把一个复杂的功能封装起来,根据变量参数之间的关系规律来编程,来简化代码,才是最好的。
有这么一句话:一个优秀的程序员是不会写出毁灭地球的方法的,他会写出毁灭行星的方法然后把地球当做参数传进去。
Java中最小的功能单元就是函数。
另外,这里再对上文中的提到的方法的重载作补充,请看下面的这则程序:
——————————————————————————
class Demo3_5{ public static void main(String[] args) { System.out.println(add(1,2));//打印3 System.out.println(add(1,2,3));//打印6 } /*求两个数的和*/ static int add(int a,int b) { return a+b; } //重载add方法 /*求3个数的和*/ static int add(int a,int b,int c) { return a+b+c; }}
——————————————————————————
重载方法使用场景:
—当定义的功能相同,但是参数与运算的未知内容不同的时候,那么这时候就定义一个函数名称以表示其功能,方便阅读,而通过参数列表的不同区分多个同名字函数。
—JVM会根据你传入的参数的不同进行不同方法的调用。
注意:只要方法同名并且参数类型不同,那就是重载。不用管返回类型是什么。
——————————————————————————
——————————————————————————
数组
概念:
—同一种类型数据的集合。简单的来说就是一容器,用来装东西的。
—数组的好处:使用数组的好处:可以自动给数组中的元素从0开始编号,方便操作这些元素。
数组格式:
—格式1:元素类型 [ ]数组名 = new 元素类型 [元素个数或数组长度] ;
——如: int [] arr = new int [3]; 也可以写成: int arr[] = new int[3];
—格式2:元素类型 []数组名 = new 元素类型 [ ]{元素1,元素2,…};
——如: int [] arr = new int []{1,2,3,4,5};
——还有一种简写的静态初始化格式:如: int [] arr={1,2,3,4,5};
——其中:new是用来在堆内存中产生一个容器实体。
—示例:int[] x = new int[3];
—示例:int[] x = {1,2,3,4,5};
————x[2] = 7;//将角标对应的数值,原来的2改成7
——这里的x并不是int类型,而是数组类型,是引用类型的一种。
数组在内存中的表现形式:
—Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,有对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
—栈内存:用于存储局部变量,当数据使用完,所占空间会自动释放。
—堆内存:
——①数组和对象,通过new建立的实例都存放在堆内存中。
——②每一个实体都有内存地址值。
——③实体中的变量都有默认初始化值。
——④实体不在被使用,会在不确定的时间内被垃圾回收器回收。
之所以要把空间细划分,因为每一片空间处理的方式不一样;
——————————————————————————
示例:
int[] x = new int[3];
//使用x的代码略
x=null;
/*当使用完x的时候,执行x = null;让x不在指向堆内存地址,堆内存中的就是垃圾,空间会被java垃圾回收机制不定时间回收;
*/
——————————————————————————
小插曲:
—Java和C++的关系:
——Java语言成长至C++,其优化了C++的一些特性,而变得更简单,尤其在内存这一块要比C++做的好,C++需要手动清楚不用的空间,如果程序员忘记做了,那么内存会越来越少,计算机就越来越慢,最后死机;
注意1:
—堆内存的有没有垃圾存在,需要看有没有变量指向它,有则不是垃圾,否则没有就死垃圾,会被垃圾回收器回收再利用。
注意2:
—int[] x = new int[3];
—int[] y = new int[3];
——x和y指向的是堆内存中两块不同的区域,两者数据的使用是互不干扰的。
——————————————————————————
关于数组有连个常见的问题需要注意一下:
—1.数组越界问题
—例:
——int[] arr = new int[2];
——System.out.println(arr[3]);
——原因:访问到了数组中的不存在的脚标时发生。
—2.空指针问题
—例:
——int[][] arr= new int[3][2];
——//使用完arr后
——int[]arr = null;
——System.out.println(arr[0]);
——原因:arr引用没有指向实体,却在操作实体中的元素时。
—Java中会把出现的问题用特有的机制表示,Java中叫做异常,我们会在后面涉及到。
——上面的1中问题,Java中使用ArrayIndexOutOfBoundsException表示。
——上面的2中问题,Java中使用NullPointerException表示。
——从单词的直译上,我们也能窥探一二,能够知道异常的原因。
————————————————————————————
多维数组(数组中的数组 )
—以二维数组为例:
—格式1: int[][] arr= new int[3][2];
—解释:以上格式表示定义了名称为arr的二维数组。有3个一维数组,每一个一维数组中有2个元素。一维数组的名称分别为arr[0],arr[1],arr[2]。给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78。
一格式2: int[][] arr= new int[3][];
一注意:此种格式中每个一维数组都是默认初始化值null。
一格式3:int[][] arr = {{3,8,2},{2,7},{9,0,1,6}};//每一个一维数组中具体元素都初始化了。
一注意:一种特殊定义写法:int[]x,y[]; x是一维数组,y是二维数组。
二维数组在内存中的分配情况示例:
—(左边是栈内存,右边是堆内存);
注意:
—二维数组的声明还可以这样:int[] y[];
——但是不推荐这样写,因为这样导致阅读性变差了,几乎没有人这么写,如果在开发中这样写,项目组长肯定和你玩命!
————————————————————————————
当我们掌握了,数组这个容器候的时候,我们可以思考其应用了:
—1.是一个容器,用来存放数据;
—2.对其中的数据进行大小排序;
—3.对其中的数据进行某一个值的查找;
那现在我们就用三则小程序来结束这小节。
程序1:
—使用数组完善前一小节中的获取一个数的十六进制程序;
————————————————————————————
/*程序1:—使用数组完善前一小节中的获取一个数的十六进制程序;*/class Demo3_6{ static char c; public static void main(String[] args) { toHex(60); //打印3C,60的十六进制是3C toHex(90); //打印5A,90的十六进制是5A } static void toHex(int a) { //定义一份表格(数组),让十六进制的每个数字 //都有一个字母对应 char[] cs = new char[]{'1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'}; //定义一个临时容 char[] cs_result = new char[10]; //让角标等于临时容器的最后一个角标 int indexOfCs_result = cs_result.length-1; int temp = a; while(true) { if(temp<=0) break; //低四位 int num = temp&15; temp = temp>>>4; //从最后一个开始往前存 cs_result[indexOfCs_result--] = cs[num-1]; } for(int i=0;i<cs_result.length;i++) { if(cs_result[i]==0)//因为在堆内存中的char类型,默认值为0 continue; else System.out.print(cs_result[i]); } }}
————————————————————————————
执行结果:
————————————————————————————
程序2:
—对数组中的数据进行排序,使用冒泡排序算法;
————————————————————————————
/*程序2:—对数组中的数据进行排序,使用冒泡排序算法;*/import java.util.*;class Demo3_7{ public static void main(String[] args) { int[] a = new int[]{5,6,13,1,3,2,9,11}; //排序前结果 System.out.println("初始数组\t"+Arrays.toString(a)); popUpSort(a);//调用冒泡排序方法 //排序后结果 System.out.println("排序结果\t"+Arrays.toString(a)); /* 这个方法能够将数组转换成字符串打印出来 Arrays.toString(数组) */ } /*冒泡排序*/ static void popUpSort(int[] a) { if(a==null)//防止a是null,导致空指针异常 return; //计数器 int count = 0; for(int i=a.length-1;i>0;i--) { for( int j=0;j<i;j++) { if(a[j]>a[j+1])//如果 swap(a,j,j+1); } count++; System.out.println("第"+count+"轮\t"+Arrays.toString(a)); } } /*数组a中角标为index1和index2的数值交换*/ static void swap(int[] a,int index1,int index2) { int tmp = a[index1]; a[index1] = a[index2]; a[index2] = tmp; }}
————————————————————————————
执行结果:
————————————————————————————
程序3:
—对数组中的数据进行排序,使用冒泡排序算法,并使用折半查找算法查找其中的某个数值;
————————————————————————————
/*程序3:—对数组中的数据进行排序,使用冒泡排序算法,并查找其中的某个数值;*/import java.util.*;class Demo3_8{ public static void main(String[] args) { int[] a = new int[]{5,6,13,1,3,2,9,11}; System.out.println("初始数组\t"+Arrays.toString(a)); popUpSort(a); System.out.println("排序数组\t"+Arrays.toString(a)); System.out.println("查找数字9角标\t"+halfSearch(a,9)); System.out.println("查找数字5角标\t"+halfSearch(a,5)); } /*折半查找*/ static int halfSearch(int[] a,int findMe) { int left = 0; int right = a.length-1; int mid=(left +right)/2; //首先获得中间的值 while(true) { if(a[mid]>findMe) { //中间值大于目标,说明目标在左边 right = mid-1; //因此中间角标的左边一个变成下一轮的右边界角标 } else if(a[mid]<findMe) { //中间值小于目标,说明目标在右边 left = mid+1; //因此中间角标的右边一个变成下一轮的左边界角标 } else //否则就找到了,直接返回该角标值 return mid; //每一轮都需要把角标定位在left和right的中间 mid=(left+right)/2; } } /*冒泡排序*/ static void popUpSort(int[] a) { /*见程序2*/} /*数组a中角标为index1和index2的数值交换*/ static void swap(int[] a,int index1,int index2) { /*见程序2*/} }
————————————————————————————
执行结果:
- 黑马程序员——函数、数组
- 黑马程序员——函数与数组
- 黑马程序员——函数及数组
- 黑马程序员——Java函数、数组
- 黑马程序员——函数与数组
- 黑马程序员——语句 函数 数组
- 黑马程序员——函数与数组
- 黑马程序员——函数与数组
- 黑马程序员—函数及数组
- 黑马程序员—数组
- 黑马程序员—数组
- 黑马程序员——003——函数、数组
- 黑马程序员——数组
- 黑马程序员——数组
- 黑马程序员——数组
- 黑马程序员——数组
- 黑马程序员——数组
- 黑马程序员——数组
- IOS常用第三方库
- 富有动感的 Sheet(选择器)
- 数据迁移工具kettle简单上手
- Parallels Desktop 11 for Mac 发布啦!
- C语言多级指针的使用
- 黑马程序员——003——函数、数组
- android 用fragment实现简单菜单点击功能
- ORA-01034: ORACLE not available
- codeforces 567F mausoleum dp
- HBase表设计——Column Family列族的设计数量不宜过多
- PostgreSQL使用pg_basebackup搭建主备流复制环境
- 欢迎使用CSDN-markdown编辑器
- Spring Dependency Injection (DI)
- xStream完美转换XML、JSON