黑马程序员——Java基础--函数与数组

时间:2023-02-25 18:36:25
------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

函数与数组

一、函数
1、定义:
函数就是定义在类中的具有特定功能的一段独立小程序,也成为方法。
2、格式:
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,..)
{
执行语句;
return 返回值
}
a.返回值类型:函数运行后的结果的数据类型。
b.参数类型:是形式参数的数据类型。
c.形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数。
d.实际参数:传递给形式参数的具体数值。
e.return:用于结束函数。
f.返回值:该值会返回给调用者
示例:
calss FunctionDemo
{
public static void main(String[] args)
{
/*
int x = 3;
System.out.println(x*3+5);

int x = 3;
System.out.println(x*3+5);
*/
int x = getResult(4);
System.out.println(x);
}
/*
发现以上的运算,因为获取不同数据的运算结果,代码出现了重复。
为了提高代码的复用性,对代码进行抽取。
讲这个部分定义成一个独立的功能,方便日后使用。
java中对功能的定义是通过函数的形式来体现的。
需要定义的功能:完成一个整数的*3+5运算。

根据java函数的格式完成该函数的的定义:
*/

public static int getResult(int x)
{
return x*3+5;
}
}
3、特点:
a.定义函数可以将功能代码进行封装
b.便于该功能进行复写
c.函数只有被调用才会被执行
d.函数的出现提高了代码的复用性
对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return如果在最后一句则可以不写
<*>注意:
*函数中只能调用函数,不可以在函数内部定义函数。
*定义函数时,函数的结果应该返回给调用者,交由调用者处理
4、如何定义一个函数?
a.既然函数是一个独立的功能,那么该功能的运算结果是什么先明确。
b.在明确定义该功能的过程中是否需要未知的内容参与运算。
例如在上例中:a.功能的结果是:x*3+5的结果
 b.在该功能的过程中是否有未知内容参与运算:有x
那么这两点就明确的函数的定义:
a.明确函数的返回值类型
b.明确函数的参数列表(参数类型int和参数的个数x)(int x)
练习:
/*定义一个动能用于打印矩形
思路:
1.确定结果:没有,因为直接打印,所以返回值类型为void
2.有未知内容吗?有,两个,因为矩形的行和列不确定
*/

class FunctionDemo2
{
public statc void main(String[] args)
{
draw(3,4);
}

public static void draw(int row,int col)
{
for(int x=0;x<row;x++)
{
for(int y=0;y<col;y++)
{
System.out.print("*");
}
//换行
System.out.println();
}
}
}
5、 函数的重载(overload)
概念:在同一个类中允许存在一个以上的同名函数,只要他们的参数个数或者在参数类型不同即可。
特点:与返回值类型无关,只看参数列表。
好处:方便与阅读,优化了程序
重载的示例:
//返回两个整数的和:int add(int x,in y){return x+y}
//返回两个整数的和:int add(int x,in y,int z){return x+y+z}
//返回两个小数整数的和:double add(double x,double y){return x+y}
什么时候用重载?
定义的功能
相同 时,但是运算的未知 内容不同。
那么,这时就定义一个函数名称以表示该功能,方便阅读,而通过参数列表的不同来区分多个同名函数。
示例:
/*
打印99乘法表
*/
class FunctionOverLoad
{
public static void main(String[] args)
{
print99();
print99(4);
}
//指定数的乘法表
public static void print99(int num)
{
for(int x=1;x<=num;x++)
{
for(int y=1;y<=x;y++)
{
System.out.print(y+"*"+x+"+"+y*x+"\t");
}
System.out.println();
}

}
public static void print99()
{
//因为代码相同,所以调用该函数即可,增加复用性
print99(9);
/*
for(int x=1;x<=9;x++)
{
for(int y=1;y<=x;y++)
{
System.out.print(y+"*"+x+"+"+y*x+"\t");
}
System.out.println();
}
*/
}
}
二、内存结构
java程序在运行时,需要在内存中的分配空间。为了提高运算效率,有时空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
1、栈内存
用于存储局部变量,当数据使用完,所占用空间自动释放。
2、堆内存
a.数组和对象,通过new建立的实例都存放在堆内存中。
b.每一个实体都有内存地址值
c.实体中的变量都有默认初始化值
d.实体不再被使用,会在不确定时间内被垃圾回收器回收
三、数组
1、概念:同一种数据类型的集合,其实数组就是一个容器。
2、好处:可以自动给数组中的元素从0开始编号,方便操作这些元素。
3、a.格式1:
元素类型[] 数组名 = new 元素类型[元素个数或者数组长度];
new:用来在内存中产生一个容器实体。
示例:int[] arr = new int[5];---arr:数组类型<引用数据类型>
3、b.格式2:
元素类型[] 数组名 = new 元素类型[]{元素,元素,元素,....};
示例:int[] arr = new int[]{3,5,1,7};
       int[] arr = {3,5,1,7};
4、数组容易出现的异常为:
a.ArrayIndexOutOfBoundsException:3:角标越界,访问到了不存在的角标
如:int[] arr = new int[3];访问int[3];
b.NullPointerException:空指针异常,
当引用没有任何指向值为null的情况,该引用还在用于操作实体arr = null;还访问arr[1]就会出现该异常
5、数组的操作:
a.获取数组中的元素。通常会用到遍历。
数组中有一个属性可以直接获取到数组元素个数。length.
使用方式:数组名称.length =个数
示例:
class ArrayDemo{
public static void main(String[] args)
{
int[] arr = {3,6,5,7,1,2};
//打印数组的长度
System.out.println("length:"+arr.length);

int sum = 0;
//根据数组的长度确认循环次数
for(int x=0;x<arr.length;x++)
{
sum = sum+arr[x];
}
}
}
<**>在上例中,如果不小心直接打印了数组,如:System.out.println(arr);这时打印的结果会是一个数组的 引用地址:[I@659e0bfd
"["代表数组,"I"代表Integer类型,@分割,659e0bfd数组在内存中的引用地址。
b.获取最值
在给定的数组中获取最大值、最小值。
思路
:<1>.获取最值需要进行比较。每一次比较都会有一个较大的值,因为该值不确定。通过一个变量进行 临时存储。
<2>.让数组中的每一个元素都和这个变量中的值进行比较。如果大于变量中的值,则用变量记录较 大值。
<3
>.当所有的元素都比较完成,那么该变量中存储的就是数组中的最大值了。
步骤
:<1>.定义变量,初始化为数组中的一个元素即可。
<2
>.通过循环语句岁数组进行遍历。
<3
>.在遍历过程中定义判断语句,如果遍历到的元素大于变量中的元素,就赋值给该变量
示例:
/*
给定一个数组{5,1,6,4,2,8,9}
*/
class ArrayTest
{
public static void main(String[] args)
{

int[] arr = {5,1,6,4,2,8,9};
int max = getMax(arr);

System.out.println("max:"+max);

}
//为提高复用性,定义成函数,求最大值
public static int getMax(int[] arr)
{
int max = arr[0];

for(int x=1;x<arr.length;x++)
{
if(arr[x]>max)
max=arr[x];
}
return max;
}
}
c、对给定数据进行排序
<1>、选择排序 
将数组中的元素每个都进行一次比较
class ArrayTest2
{
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])
{
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
}
public static void main(String[] args)
{
int[] arr = {5,1,6,4,2,8,9};

selectSort(arr);
for(int x=0;x<arr.length;x++)
{
//最后打印顺序为从小到大
System.out.println(arr[x]);
}
}
}
< 2> 、冒泡排序
相邻的两个元素进行比较,如果符合条件换位

class ArrayTest2{
public static void selectSort(int[] arr)
{
for(int x=0;x<arr.length-1;x++)
{
for(int y=0;y<arr.length-x-1;y++)
//-x:让每一次比较次数减少,-1:避免角标越界
{
if(arr[y]>arr[y+1])
{
int temp = arr[y];
arr[y] = arr[y+1];
arr[y+1] = temp;
}
}
}
}
public static void main(String[] args)
{
int[] arr = {5,1,6,4,2,8,9};

selectSort(arr);
for(int x=0;x<arr.length;x++)
{
System.out.println(arr[x]);
}
}
}
d、查找
<1>普通查找
class ArrayTest3
{
public static void main(String[] args)
{
int[] arr = {5,1,6,4,2,8,9};
int x = getIndex(arr,2);
System.out.println("index:"+x);
}



//普通查找:获取key第一次出现的角标,返回-1,则代表鼠族中不包括key。
public static int getIndex(int[] arr,int key)
{
for(int x=0;x<arr.length;x+)
{
if(arr[x]==key)
return x;
}
return -1
}
}
<2>、折半查找
前提:该数组必须有序。
class ArrayTest3
{
public static void main(String[] args)
{
int[] arr = {2,4,5,7,19,32,45};

int x = halfSearch(arr,32);
System.out.println("index:"+x);
}
//折半查找方式一
public static int halfSearch(int[] arr,int key)
{
int min = 0;
int max = arr.length-1;
int mid =(min+max)/2
while(arr[mid]!=key)
{
if(key>arr[mid])
{
min=mid+1;
}
else if(key<arr[mid])
{
max=mid-1;
}

if(min>max)
return -1;
mid = (max + min)/2;
}
return mid;
}
//折半查找方式二
public static int halfSearch_2(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 -1;
}
}
当想向有序的数组中插入一个元素时,通过折半查找,只要将返回值mid改成min即可,min返回的数值 就是所要插入元素的角标位置。
<*>StringBuffer sb =new StringBuffer();中的reverse()具有反转功能。
e、进制转换
class ArrayTest4
{
public static void main(String[] args)
{
//十--->二
trans(6,1,1);
//十--->八
trans(60,7,3);
//十--->十六
trans(60,15,4);
}
public static void trans(int num,int base,int offset)
{ //将转换后对应的进制数放入数组中
char[] chs =

{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

//定义存放转换后的字符数组
char[] arr = new char[32];
//定义指针
int pos = arr.length;
//定义循环,对要转换的数进行每一位的转换
while(num!=0)
{ //要求转换进制的基数
int temp = num&base;

arr[--pos] = chs[temp];
//偏移指定数
num = num>>>offset;
}
for(int x=pos;x<arr.length;x++)
{
System.out.print(arr[x]);
}

}

}
6.二维数组
int[][] y;int y[][];int[] y[];三种定义方式都可以
int[] x,y[];其中x是一维,y是二维。