一、函数概述
1.函数
(1). 函数就是定义在类中的具有特定功能的小程序块,也称为方法。
(2). 函数的定义格式
修饰符 返回值类型 函数名 (参数类型 形式参数1,参数类型 形式参数2)
{
执行语句
返回值
}
函数示例:
public static int function(int x;int y)
{
return x+y;
}
(3).函数的特点Ø 函数可以把代码进行封装,在使用的时候直接调用,提高了代码的复用性。
Ø 函数只能在函数里调用,而不能在函数里定义。
Ø 函数在没有没有具体返回值时,可以用将返回值类型定义为void,并且可以省略return语句。(比如函数用于打印图形时)
Ø 函数的名称可以自己定义,只要是合法的标识符即可,但由于函数主要是用来调用,所以必须做到见名知意。
(4).定义函数的注意事项
Ø 定义函数之前明确函数是否有结果也就是返回值?有,返回值类型。
Ø 定义函数之前明确函数是否有未知的内容参与? 有,几个、数据类型。
Ø 定义函数的功能尽量单一,不要一堆代码都封装进去,以提高阅读型。
(5).函数的调用
既然我们为了实现功能定了函数,那我当然得来调用这个功能实现函数了。
函数调用的格式:
函数名 (实参1,实参2…);
函数调用示例:
class functionDemo
{
public static void main(String[] args)
{
int x=1,y=2;
//调用函数
int sum=function(1,2);
System.out.println("x+y="+sum);
}
//定义函数
public static int function(int x ,int y )
{
//返回x+y的值
return x+y;
}
}
PS:有的朋友可能会迷惑什么是实参和形参?其实LZ之前有一段时间分不清,不过好在现在清楚了,跟大家分享一下我的理解:形参:形参全称是形式参数,就是定义的需要传递的值,是一个不确定的值。
实参:实参全称是实际参数 ,就是我们在使用过程中给形参传递的具体的值。
这样就很好理解了,形参可以理解成一个变量,而实参就是给形参这个变量赋值。
2.函数重载
(1).什么是函数重载?
所谓的重载就是在一个类里边可以定义多个相同名字的函数,只要参数类型或个数不一样就行。
(2).函数重载的特点:
函数重载只看参数列表,与返回值列表什么的都无关,一样不一样无所谓。
函数的重载主要用于优化代码。
(3).函数重载示例
//定义两个函数,一个实现x+y功能,一个实现x+y+z的功能
public static int functionDeno(int x,int y){
return x+y;
}
public static int functionDeno(int x,int y,int z){
return x+y+z;
}
(4).重载函数的应用重载函数主要应用于函数功能相同但是,参数个数或类型不同的情况,当我调用函数时,Java虚拟机会造函数中需找对应参数类型和个数的函数执行。
二、数组概述
1. 什么是数组?
数组就是一个相同类型数据的集合,可以说是一个容器,用来存储数据。
其实我们可以把数组看成一个杯子,把数据看成水,而杯子的功能就是盛水,也就是存储数据。
2. 数组的有什么好处?
数组最大的好处就是可以自动给数组中的元素由0开始编号,操作方便。
数组的操作的实际上就是操作数组的角标。
3.数组的定义格式
格式1:
元素类型[] 数组名 = new 元素类型{数组长度}
Int[] shuzu = new int[]{15};
格式2:
元素类型[] 数组名 = new 元素类型{元素,元素。。。}
Int[]shuzu = new int[]{1,2,3}
或者 int[] shuzu = {1,2,3}
总结:数组的定义有好几种,具体怎么定义,还要看情况而定,建议初学者规范格式,可以提高阅读性。
4. 数组的内存结构
Java的内存区域划分为五部分,分别为堆内存、栈内存、寄存器、方法区、本地方法区。
定义数组会涉及到堆内存和栈内存
栈内存: 存储的都是局部变量
1. 栈内存存储的局部变量在使用完之后会自动释放内存。
2. 所谓的局部变量就是我们之前说过的变量的作用域的问题,如在函数里定义的变量、参数,在函数执行完之后,存储的变量申请的内存都会被回收。
堆内存 存储的都是实体
1. 堆内存中的实体都有一个内存地址值
2. 堆内存中的实体都有一个默认初始化变量
3. 堆内存中的实体如果没有被任何一个引用变量引用,就会视为垃圾,在不定的时间内会被垃圾回收机制回收,释放内存。
4. 只要是被new的对象都会被存放在堆内存中,new就是实例化对象,数组和对象都会被存放在堆内存中。
定义数组时的内存示意图:
5. 操作数组是容易遇到的两个问题
1. 数组角标越界异常(ArrayIndexOutOfBoundsException):操作数组时,访问到了数组中没有的角标。
2. 空指针异常(NullPointerException):当引用没有任何指向值为null的情况,该引用还在用于操作实体。
6.数组的常见操作
1. 获取数组中的元素
数组就是让我们来操作的,所以会经常用到数组的中的元素,那么我该怎么获取数组中的元素呢,一般的时候我们都会用到遍历。
下面就做一个小程序,来获取数组中元素,并打印到屏幕上。
/*
需求:获取数组中元素,并打印到屏幕上
思路:1.定义一个数组
2.获取数组中的元素,数组操作全是通过角标操作
3.获取是一个重复动作,可以用循环实现
4.把数组元素打印到屏幕上
*/
class ArrDemo
{
public static void main(String[] args)
{
//定义数组
int[] arr={1,2,3,4,5,6};
System.out.print("arr"+"[");
//获取数组中长度 arr.length是获取数组的长度
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.print("]");
}
}
2. 获取数组中的最值
/*
需求:获取数组中的最值
思路:刚学习了函数,我们就借花献佛来用函数来定义一个获取数组最值的函数
两个明确:
1.明确函数是否有具体的结果。有,最值
2.明确数组否有未知内容参与。有 数组
*/
class ArrDemo1
{
public static void main(String[] args)
{
int[] arr={1,3,4,5,6};
//调用获取数组最小值的函数
int min = arrMin(arr);
System.out.println("min="+min);
//调用获取数组最大值的函数
int max = arrMax(arr);
System.out.println("max="+max);
}
//定义获取数组最小值的函数
public static int arrMin(int[] arr)
{
int min=0;
//遍历数组
for(int x=0;x<arr.length;x++)
{
//数组的每一个元素与第一个元素比较,如果比他小,就将小的值赋给min
if(arr[x]<arr[min])
min=x;
}
return arr[min];
}
//定义获取数组最大值的函数
public static int arrMax(int[] arr)
{
int max=0;
//遍历数组
for(int x=0;x<arr.length;x++)
{
//数组的每一个元素与第一个元素比较,如果比他大,就将小的值赋给max
if(arr[x]>arr[max])
max=x;
}
return arr[max];
}
}
3. 数的排序
数组的排序还有很多种,现在我们简单介绍一下选择排序和冒泡排序。
选择排序:
/*
需求:将数组进行选择排序
思路:什么是选择排序?
选择排序就是将数组的一个元素和其他元素都比较一遍,如果大/小则互换位置,
每个元素都要比较一遍。
定义一个函数来实现冒泡排序的功能
1.明确是否有结果。无 用void
2.明确是否有未知参与者。 有 数组
*/
class ArrDemo2
{
public static void main(String[] args)
{
int[] arr={1,4,3,5,6,2,22,44};
arrB(arr);
//调用选择排序的函数
arrXuan(arr);
System.out.println();
//遍历数组
arrB(arr);
}
//定义函数选择排序的功能
public static void arrXuan(int[] arr)
{
//遍历数组
for(int x=0;x<arr.length;x++)
{
int max ;
for(int y=0;y<arr.length;y++)
//比较数组中元素的大小 然后互换位置
if(arr[x]>arr[y])
{
max = arr[y];
arr[y] = arr[x];
arr[x] = max;
}
}
}
//定义遍历数组输出的函数
public static void arrB(int[] arr)
{
System.out.print("arr"+"[");
//获取数组中长度 arr.length是获取数组的长度
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.print("]");
}
}
冒泡排序:
冒泡排序就是相邻的元素两两比较,然后互换位置。
/*
需求:对数组进行冒泡排序
思路:
冒泡排序就是将数组中相邻的两个元素比较大小,然后互换位置。
*/
class ArrBu
{
public static void main(String[] args)
{
int[] arr={1,6,3,9,4,7,22,44};
arrB(arr);
ArrBu(arr);
System.out.println();
arrB(arr);
}
//定义冒泡排序的函数
public static void ArrBu(int[] arr)
{
int max;
for(int x=0;x<arr.length;x++)
{
//length-x-1是因为比较的元素会随着次数增加而减少
for(int y=x;y<arr.length-x-1;y++)
{
//相互比较互换位置
if(arr[y]>arr[y+1])
{
max=arr[y];
arr[y]=arr[y+1];
arr[y+1]=max;
}
}
}
}
//定义遍历数组输出的函数
public static void arrB(int[] arr)
{
System.out.print("arr"+"[");
//获取数组中长度 arr.length是获取数组的长度
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.print("]");
}
}
4. 数组的查找
数组既然是用来存储数据的,那其中数据就免不了被拿来用,而查找又是一个经常要使用的操作,那么数组该怎么查找呢?
下面就介绍一下 折半查找
/*
需求:对数组进行折半查找 输入一个元素 找到在数组中存储中的位置 也就是角标
思路:折半查找就是不对对数组进行切割成两半查找,数组必须是一个有序数组
将数组折半需要得到数组的长度,由于是不断变化,所以可以用数组的尾角标-减数组的头角标
实现
*/
class ArrDemo3
{
public static void main(String[] args)
{
int[] arr = {1,2,4};
int x=arrBan(arr,1);
System.out.println("index="+x);
int y=arrBan1(arr,2);
System.out.println("index="+y);
}
//定义功能对数组进行对半查找,如果存在数组中返回角标,不存在则返回-1
public static int arrBan(int[] arr,int key)
{
int min = 0;
int max = arr.length-1;
int mid =(max-min)/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 arrBan1(int[] arr,int key)
{
int min =0;
int max =arr.length-1;
int mid =(max-min)/2;
while(min<=mid)
{
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
return mid;
}
return -1;
}
}
面试题:
有一个有序的数组,想要将一个元素插入到该数组中,还要保证该数组是有序的。如何获取该元素在数组中的位置。
/*
需求: 有一个有序的数组,想要将一个元素插入到该数组中,还要保证该数组是有序的。如何获取该元素在数组中的位置。
思路: 采用折半查找 查找插入元素位置 如果有就返回元素位置 如果没有就返回插入的最小位置 这就是插入元素插入的位置
*/
class ArrDemo4
{
public static void main(String[] args)
{
int[] arr = {1,2,4};
int x=arrBan(arr,3);
System.out.println("index="+x);
}
public static int arrBan1(int[] arr,int key)
{
int min =0;
int max =arr.length-1;
int mid =(max-min)/2;
while(min<=mid)
{
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
return mid;
}
return min;
}
}
5. Java中操作数组的arrays工具类
在Java中,封装了很多的类,其中arrays就是Java中操作数组的工具类,里边有很多方法我们都可以直接拿来用,不用再自己编写函数。
Arrays类包含的函数:
排序:Arrays.sort( arr );直接传递数组即可
二分查找:Arrays.binarySearch(arr, key);也叫折半查找,就是将数组不断的对半分割同一个定值key比较,但前提数数组必须是有序数组。
复制指定的数组:Arrays.copyOf(arr, newLength);复制完会返回新数组,长度不足则填充响应值。
复制指定范围的数组:Arrays.copyOfRange(arr,from,end);含头不含尾
toString: Arrays.toString(arr); 返回数组的字符串形式
6. 用数组进行进制间的转换进制间的转换都大同小异,以十进制转示例进制为例
/*
需求:将十进制转成十六进制
*/
class ArrDemo4
{
public static void main(String[] args)
{
toHex(60);
}
public static void toHex(int num)
{
//查表法
char[] chs = {'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-1;
while(num!=0)
{
int temp = num & 15;
arr[--pos]=chs[temp];
num=num>>>4;
}
//遍历数组
for(int x=pos;x<arr.length;x++)
System.out.print(arr[x]);
}
}
7. 二维数组
1)什么是二维数组?
二维数组简单的说就是多个一维数组的集合
2)二维数组定义的格式
元素类型 [][ ] 数组名 = new 元素类型[ ][ ];
元素类型 数组名[ ][ ] = new元素类型[ ][ ];
元素类型[ ] 数组名[ ]= new 元素类型[ ][ ];
3) 二维数组的初始化
二维数组的初始化可以省略一维数组的长度,但不允许省略二维数组的长度。例如:int[ ][ ] arr=new int[2][ ];
二维数组中的一维数组也可不对称,可以如下赋值:
int[ ][ ] arr={{1,3,5},{1,3},{1,4,5,6}};
int[ ][ ] arr_1=new int[2][ ];
int[0] ={1,3,5};
int[1]= {1,3};
int[2]= {1,4,5,6};
二维数组的单个元素赋值
int[0][1]=1;
4)二维数组的遍历和求最值
由于二维数组的最值也需要用遍历,所以就不再单独写代码,以求最小值为例。
class ArrDemo5
{
public static void main(String[] args)
{
int[][] arr={{1,3,4},{2,5,6},{9,8,6}};
//定义一个变量存储最小值
int min=arr[0][0];
//开始遍历数组
for(int x=0;x<arr.length;x++){
for(int y=0;y<arr[x].length;y++)
//将数组中的每个元素都与数组的第一个元素比较,如果比它还小,将它之赋给min
if(arr[x][y]<min)
min = arr[x][y];
}
System.out.println("min="+min);
}
}