文章目录
- 函数
- 定义
- 练习
- 误区
- 重载(overload)
- 重载选择题练习
- 函数的内存调用问题
- 数组
- 定义
- 数组的内存图解
- 数组的常见问题
- 应用
- 求和
- 最大值
- 将数组转成字符串
- 查表法
- 转十六进制
- 查表版(十六进制终极版)
- 十进制转二进制
- 进制转换(通用版)
- 选择排序
- 冒泡排序
- 普通查找方式
- 二分查找方式
- 数组中的数组[][]
- 格式1
- 格式2
- 格式3
- 数组的练习
- 数组反转
- 获取插入点
函数
定义
函数就是定义在类中的具有特定功能的一段独立小程序。函数在java中也称为方法。
格式
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,…)
{
执行语句;
return 返回值;//return关键字是用于结束该功能。并将运算后的具体结果返回给调用者。
//必须有return语句
}
//注意:函数的返回类型如果是void时,return语句可以省略不写。return;
void表示的是没有返回值的情况。
返回值类型:函数运行后的结果的数据类型。
参数类型:是形式参数的数据类型。
形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数。
实际参数:传递给形式参数的具体数值。
return:用于结束函数。
返回值:该函数运算后的结果,该结果会返回给调用者。
举例:
public static void main(String[] args) {
for(int i=0;i<4;i++) {
for(int j=0;j<5;j++) {
System.out.print(j+"*"+i+"="+j*i+"\t" );
}
System.out.println();
}
}
输出:
*****
*****
*****
*****
问题:要画矩形,需要不断使用该for嵌套代码,造成代码复用性差。
解决:定义一个功能用于画矩形,每次只要使用该功能即可。这样提高复用性。
如何定义一个功能呢?
1.它应该是一个封闭的区间,就是大括号。
2.它需要有名称。
3.需要有参与运算的数据
4.需要定义该功能的结果类型。
在主方法中调用自定义的方法
public static void main(String[] args) {
draw(4,5);
}
static void draw(int row,int col ) {
if(row<0)
return;//如果row的值<0,直接结束。
for(int i=0;i<row;i++) {
for(int j=0;j<col;j++) {
System.out.print("*");
}
System.out.println();
}
}
总结:
函数就是一个功能。
功能就需要两个部分:
1.结果;2.未知内容。
明确1:这个功能的结果是什么?其实就是明确返回值类型。
明确2:这个功能需要未知内容是什么?其实就是明确参数列表。
练习
需求:需要一个方法,进行加法运算,获取两个整数的和。
明确1:功能的结果是什么?是一个和,和是整数。返回值的类型是int。
明确2:功能的未知内容有么?有,加数和被加数。都是int类型,这就是参数列表。
public static void main(String[] args) {
int sum=add(4,5);
System.out.println(sum);
}
public static int add(int a,int b) {
return a+b;
}
误区
功能内只定义所需的内容,不需要的不定义。
重载(overload)
定义:在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可。
特点:与返回值类型无关,只看参数列表。
优点:方便于阅读,优化了程序设计。
//函数名定义就是为了描述该功能。
//两个整数求和的功能
public static int add(int a,int b) {
return a+b;
}
//三个整数求和
public static int add(int a,int b,int c) {
return a+b+c;
}
//两个小数的和
public static double add(double a,double b) {
return a+b;
}
//九九乘法表的重载
public static void printCFB() {
for(int i=1;i<=9;i++) {
for(int j=1;j<=9;j++) {
System.out.print(j+"*"+i+j*i+"\t");
}
System.out.println();
}
}
public static void printCFB(int num) {
for(int i=1;i<=num;i++) {
for(int j=1;j<=num;j++) {
System.out.print(j+"*"+i+j*i+"\t");
}
System.out.println();
}
}
重载选择题练习
只要函数名相同,参数列表不同:顺序、个数、类型不同的都算重载。
给定void show(int a,float b,char c){}
下列哪些函数和给定函数重载了。
a.int show(int x,float y,char z){}
//没有重载,这个函数不允许和给定函数存在于同一个类中,因为会产生调用的不确定性。
b.void show(float b,int a,char c){}
//重载了,参数列表不同,顺序不同
c.void show(int c,float a,char b){}
//没有重载,和给定函数,不允许存在
d.void show(int a,int b,int c){}
//重载了,因为类型不同
e.double show(){}
//重载了,因为个数不同
函数的内存调用问题
举例:
public static void main(String[] args) {
int sum=add(4,5);
System.out.println(sum);
}
public static int add(int a,int b) {
return a+b;
}
栈:先进栈的后出栈
进栈(压栈) 出栈(弹栈)
数组
定义
概念:同一种类型数据的集合。其实数组就是一个容器。
优点:数组可以存储多个数据,可以自动给数组中的元素从0开始编号,方便通过编号(索引)操作这些元素。
数组中的元素默认为0。
格式1:
//元素类型[] 数组名=new 元素类型[元素个数或数组长度];
//示例如下:
int[] arr=new int[5];//通过new关键字创建了一个长度为5,元素类型为int的数组实体
格式2:
//元素类型[] 数组名=new 元素类型[]元素,元素,……];
//示例如下:
int[] arr=new int[]{3,5,1,7};
int[] arr={3,5,1,7};
int[] arr= {34,56,78,12,25,46};
for(int i=0;i<arr.length;i++)//arr.length是数组的长度
System.out.println("arr["+i+"]="+arr[i]);
数组的内存图解
java对内存空间的划分,分为五部分:
栈、堆、方法区、本地方法区、寄存器。
栈内存:
存储的都是局部变量,只要是在方法中定义的变量都是局部变量。
一旦变量的生命周期结束,该变量就被释放。
堆内存:
存储的都是实体(对象)能被new创建的,
每一个实体都有一个首地址值。
堆内存的变量都有默认初始化值。
不同类型不一样.int:0;double:0.0;boolean:false;char:’\u000’
堆把首地址告诉栈即可,arr是引用型变量,当不想把arr指向实体时,只要将arr=null;
当实体不再使用时,就会被垃圾回收机制处理。
数组的常见问题
1.Array Index out of Bounds Exception数组角标溢出异常//访问到了数组不存在的索引时,会发生该异常。
2.Null Pointer Exception空指针异常//当使用没有任何实体指向的引用变量操作实体时,运行会发生该异常。
应用
数组常见操作
1.获取最值(最大值,最小值)
2.排序(选择排序,冒泡排序)
3.折半查找(二分查找)
求和
需求:获取多个数的和的功能。
明确1:结果?int
明确2:参数?多个数,定义多个参数合适吗?既然是一组数,数组。
步骤:
1.定义变量,记录和
2.通过循环对数组进行遍历
public static void main(String[] args) {
int[] arr=new int[] {23,44,1,23,56,78};
add(arr);
}
public static int add(int[] arr) {
int sum=0;
for(int i=0;i<arr.length;i++) {
sum+=arr[i];
}
return sum;
}
最大值
需求:获取多个整数中最大值。
思路:
1.数据多了,为了便于操作,需要容器,用数组。
2.多个数据需要进行比较,每次都有较大的数,需要记录下来和下一个数比较。
3.将数组中的元素都比一遍。最后,就有了最大值。
步骤:
1.需要数组。
2.定义一个变量记录住较大的数。
3.对数组进行遍历,让元素和较大的值进行比较。
如果元素大于较大的数,用变量记录该元素。
4.遍历完成后,变量中记录就是最大值。
//定义功能。
明确1:结果?最大值。
明确2:参数?int[].
public static void main(String[] args) {
int[] arr=new int[] {23,44,1,23,56,78};
int max=getMax(arr);
System.out.println("max="+max);
}
public static int getMax(int[] arr) {
int max=arr[0];
for(int i=1;i<arr.length;i++) {
if (max<arr[i])
max=arr[i];
}
return max;
}
另一种把public static int getMax(int[] arr){ }中的内容替换为
public static int getMax_2(int[] arr) {
int max=0;//初始化为数组中的任意一个角标
for(int i=1;i<arr.length;i++) {
if (arr[max]<arr[i])
max=i;
}
return arr[max];
}
将数组转成字符串
需求1:定义功能,将[34,12,67]数组中的元素转成字符串“[34,12,67]”
明确1:结果?字符串。
明确2:参数?数组。
思路:简单的方式就是利用了字符串和任何数据相加都是相连接。
步骤:
1.定义字符串变量
2.遍历数组。将每一个数组的元素和字符串相连接。
3.将连接后的字符串返回。
public static void main(String[] args) {
int[] arr=new int[] {23,44,1,23,56,78};
String str=toString(arr);
System.out.println("string="+str);
}
public static String toString(int[] arr) {
String temp="[";//初始化为[字符串
for(int i=0;i<arr.length;i++) {
if (i!=arr.length-1)
temp=temp+arr[i]+",";
else
temp=temp+arr[i]+"]";
}
return temp;
}
结果:
string=[23,44,1,23,56,78]
查表法
数组使用的核心思想:
容器特点:1.固定长度;2.元素都有索引。
什么时候使用容器呢?数据多了,必须先进行存储,然后进行操作。
对于数组容器什么时候用呢?数据多,个数确定,而且有对应关系。
在分析需求时:
1.需求中的数据是否有对应的有序编号?
2.需求中的数据是否需要有序的编号。
如果有,就用数据存储。
例1:一组数:34 89 12 78 45 要对他们进行操作。需要编号,操作更容易。
例2:根据用户输入的数据,显示对应的星期。
思路:
1.星期有多个,个数固定。
2.星期对应的有序编号,有序的编号就可以作为索引。
所以可以使用数组这种结构进行存储。
需求:
定义一个功能,根据给定的数据获取对应的星期。
查表法:数据之间存在对应关系,通过关系中一方查询另一方。
当对应关系存在,但没有一方是有序编号时,使用另一个容器map。
步骤:
1.定义一个数组,存储固定的星期数。这个称之为一个存储了对应关系的表。
public static void main(String[] args) {
int num=7;
String week=getWeek(num);
System.out.println(num+"对应的星期为"+week);
}
public static String getWeek(int num) {
String[] weeks = new String[]{"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};//其实就是根据制定的索引在查表
if (num>7||num<1)
return num+"没有对应的星期";//throw new RuntimeException("没有对应的星期");抛出异常,return结束当前功能,抛出异常是结束当前程序
else
return weeks[num];
}
转十六进制
需求:十进制—>十六进制
&15 >>>4 循环
原本:
public static void main(String[] args) {
int num=60;
for(int i=0;i<8;i++) {//4个8位
int temp=num&15;
if (temp>9)
System.out.println((char)(temp-10+'A'));
else
System.out.println(temp);
num=num>>>4;
}
}
解决问题:
1.顺序反了。2.去除多余的0.
解决方式:
1.每运算出一位,不要打印,先存储,需要容器。
2.去除零?需要转换的数据会不断地右移,如果右移后剩余的二进制都是0,也就是没有有效位,就不需要进行&运算了。也就是不需要再往数组中存储了。
public static void main(String[] args) {
int num=60;
String str_hex=toHex(num);
System.out.println(str_hex);
}
public static String toHex(int num) {
//1.定义容器,存储的是字符,长度位8,一个整数最多8个16进制位。
char[] chas=new char[8];
//2.定义一个用于操作数组的索引。
//int index=chas.length-1;
int index=chas.length;
//for(int i=0;num!=0&&i<8;i++) {
//for(;num!=0;) {
while(num!=0) {
int temp=num&15;
if (temp>9)
// chas[index]=((char)(temp-10+'A'));
chas[--index]=((char)(temp-10+'A'));
else
// chas[--index]=((char)(temp+'0'));
chas[--index]=((char)(temp+'0'));
//3.让角标自增。
// index--;
num=num>>>4;
}
/*
// 4.遍历数组。
for(int i=0;i<chas.length;i++) {
System.out.print(chas[i]+",");
}
*/
System.out.println("index="+index);
return "0x"+toString(chas,index);
}
//定义一个功能,将字符数组转成字符串
public static String toString(char[] arr,int index){
String temp="";
for(int i=index;i<arr.length;i++) {
temp=temp+arr[i];
}
return temp;
}
查表版(十六进制终极版)
思路:
十进制转成十六进制的每一位都是十六进制元素中的某一个。
十六进制中的元素有很多固定个数,而且还有对应的编号。
所以可以使用传说中的查表法。
public static void main(String[] args) {
int num=60;
String str_hex=toHex(num);
System.out.println(str_hex);
}
public static String toHex(int num) {
//1.建立表。
char[] chs= {'0','1','2','3',
'4','5','6','7',
'8','9','A','B',
'C','D','E','F'};
//2.创建临时容器。
char[] arr=new char[8];
//创建操作临时容器的索引。
int index=arr.length;
//4.通过循环对num进行& >>>等运算
while(num!=0) {
//5.对num进行&运算。
int temp=num&15;
//根据&运算后的结果作为角标查表,获取对应字符,并将字符存储放到临时容器中。
arr[--index]=chs[temp];
//7.对num进行右移。
num=num>>>4;
}
return "0x"+toString(arr,index);
}
public static String toString(char[] arr,int index){
String temp="";
for(int i=index;i<arr.length;i++) {
temp=temp+arr[i];
}
return temp;
}
十进制转二进制
public static void main(String[] args) {
int num=60;
String binary=toBina(num);
System.out.println(hex);
}
//将输出的数字存储在数组中,返回类型为char,输入的参数列表为int
public static String toBina(int num) {
//查表
char[] binary= {'0','1'};
//建立新的存储容器
char[] arr=new char[32];
//建立索引
int index=arr.length;
while(num!=0) {
int temp=num&1;
arr[--index]=hex[temp];
num=num>>>1;
}
return toString(arr,index);
}
public static String toString(char[] arr,int index) {
String temp="";
for(int i=index;i<arr.length;i++) {
temp=temp+arr[i];
}
return temp;
}
进制转换(通用版)
public static void main(String[] args) {
int num=60;
String str_hex=toHex(num);
String str_binary=toBinary(num);
String str_oct=toOctal(num);
System.out.println(num+"的十六进制为"+str_hex);
System.out.println(num+"的二进制为"+str_binary);
System.out.println(num+"的八进制为"+str_oct);
}
//十进制-->十六进制
public static String toHex(int num) {
return "0x"+trans(num,15,4);
}
//十进制-->二进制
public static String toBinary(int num) {
return trans(num,1,1);
}
//十进制-->八进制
public static String toOctal(int num) {
return "0"+trans(num,7,3);
}
//用于进制转换
public static String trans(int num,int base,int offset) {
//1.建立表。
char[] chs= {'0','1','2','3',
'4','5','6','7',
'8','9','A','B',
'C','D','E','F'};
//2.创建临时容器。
char[] arr=new char[32];
//创建操作临时容器的索引。
int index=arr.length;
//4.通过循环对num进行& >>>等运算
while(num!=0) {
//5.对num进行&运算。
int temp=num&base;
//根据&运算后的结果作为角标查表,获取对应字符,并将字符存储放到临时容器中。
arr[--index]=chs[temp];
//7.对num进行右移。
num=num>>>offset; //偏移量
}
return toString(arr,index);
}
public static String toString(char[] arr,int index){
String temp="";
for(int i=index;i<arr.length;i++) {
temp=temp+arr[i];
}
return temp;
}
总结:java有一种帮助文档,里面封装了很多函数。
包括进制转换:
//java已提供的功能
System.out.println(Integer.toBinaryString(28));
System.out.println(Integer.toOctalString(28));
System.out.println(Integer.toHexString(28));
选择排序
数组的排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
外循环:不同起点
内循环:同起点的不同箭头
确定头(最小)
public static void main(String[] args) {
int[] arr=new int[] {12,9,23,77,6,34};
printArray(arr);
selectSort(arr);
printArray(arr);
}
//打印数组的方法
public static void printArray(int[] arr) {
for(int i=0;i<arr.length;i++) {
if(i!=arr.length-1)
System.out.print (arr[i]+",");
else
System.out.println (arr[i]);
}
}
//数组的排序,选择排序
public static void selectSort(int[] arr) {
for(int i=0;i<arr.length-1;i++) {
for(int j=i+1;j<arr.length;j++) {
if(arr[i]>arr[j]) {
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
冒泡排序
确定尾(最大)
public static void main(String[] args) {
int[] arr=new int[] {12,9,23,77,6,34};
printArray(arr);
bubbleSort(arr);
printArray(arr);
}
//打印数组的方法
public static void printArray(int[] arr) {
for(int i=0;i<arr.length;i++) {
if(i!=arr.length-1)
System.out.print (arr[i]+",");
else
System.out.println (arr[i]);
}
}
//数组的排序,冒泡排序
public static void bubbleSort(int[] arr) {
for(int i=0;i<arr.length-1;i++) {
for(int j=0;j<arr.length-1-i;j++) {
if(arr[j]>arr[j+1]) {
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
java中也有直接的包
import java.util.Arrays;
public class Myclass1 {
public static void main(String[] args) {
int[] arr=new int[] {12,9,23,77,6,34};
printArray(arr);
Arrays.sort(arr);//开发时用该调优。
printArray(arr);
}
//打印数组的方法
public static void printArray(int[] arr) {
for(int i=0;i<arr.length;i++) {
if(i!=arr.length-1)
System.out.print (arr[i]+",");
else
System.out.println (arr[i]);
}
}
发现排序方法,位置置换代码重复,进行抽取。
public static void main(String[] args) {
int[] arr=new int[] {12,9,23,77,6,34};
printArray(arr);
selectSort(arr);
//Arrays.sort(arr);
printArray(arr);
bubbleSort(arr);
//Arrays.sort(arr);
printArray(arr);
}
//打印数组的方法
public static void printArray(int[] arr) {
for(int i=0;i<arr.length;i++) {
if(i!=arr.length-1)
System.out.print (arr[i]+",");
else
System.out.println (arr[i]);
}
}
//数组的排序,选择排序
public static void selectSort(int[] arr) {
for(int i=0;i<arr.length-1;i++) {
for(int j=i+1;j<arr.length;j++) {
if(arr[i]>arr[j]) {
swap(arr,i,j);
}
}
}
}
//数组的排序,冒泡排序
public static void bubbleSort(int[] arr) {
for(int i=0;i<arr.length-1;i++) {
for(int j=0;j<arr.length-1-i;j++) {
if(arr[j]>arr[j+1]) {
swap(arr,j,j+1);
}
}
}
}
public static void swap(int[] arr,int a,int b) {//角标要先有数组
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
普通查找方式
需求:查找一个元素在数组中的第一次出现的位置。
public static void main(String[] args) {
int[] arr=new int[] {12,9,23,77,6,34};
int x=searchKey(arr,77);
System.out.println(x);
}
//打印数组的方法
public static int searchKey(int[] arr,int key) {
//遍历查找
for(int i=0;i<arr.length;i++) {
if(arr[i]==key)
return i;
}
//数组中不存在的角标,为-1
return -1;//代表角标不存在的情况
}
二分查找方式
前提:数组必须是有序(递增或递减)的。
思路:
1.通过角标先获取中间角标上元素。
2.让该元素和要找的数据比较。
3.如果要找的数大了,缩小范围,要找的范围应该是 中间的角标+1-----尾角标。
4.如果要找的小了,缩小范围,要找的范围应该是 头角标-----中间的角标+1。
5.不断如此重复,就可以找到元素对应的角标。
public static void main(String[] args) {
int[] arr=new int[] {9,12,15,24,36,41,59,68};
int index=binarySearch(arr,41);
System.out.println("index="+index);
}
public static int binarySearch(int[] arr,int key) {
//1.定义三个变量,记录头角标、尾角标、中间角标
int min,max,mid;
min=0;
max=arr.length-1;
mid=(min+max)>>1;
while(arr[mid]!=key) {
if(arr[mid]>key)
max=mid-1;
else
min=mid+1;
//判断元素是否存在
if (max<min)
return -1;
mid=(min+max)>>1;
}
return mid;
}
还有一种是把 public static int binarySearch(int[] arr,int key) { }中的内容换成
public static int binarySearch(int[] arr,int key) {
//1.定义三个变量,记录头角标、尾角标、中间角标
int min,max,mid;
min=0;
max=arr.length-1;
while(min<=max) {
mid=(min+max)>>1;
if(key<arr[mid])
max=mid-1;
else if(key>arr[mid])
min=mid+1;
else
return mid;
}
return -1;
数组中的数组[][]
开发时并不常用
比如说俄罗斯方块的坐标点
格式1
int[][] arr=new int[3][2];
定义了名称为arr的二维数组;
二维数组中有3个一维数组;
每一个一维数组中有2个元素;
一维数组的名称分别为arr[0],arr[1],arr[2];
给第一个一维数组1脚标位赋值为78写法为:arr[0][1]=78。
二维数组分布情况:
int[][] arr=new int[3][2];
System.out.println(arr);
//输出为[[I@15db9742//二位数组实体。//@右边为哈希值,实体在内存中存放的位置;@左边[是数组,[[是而二维数组,I是类型int.
System.out.println(arr[0]);//输出为[I@6d06d69c//一维数组实体。
System.out.println(arr[0][0]);//一维数组中的元素。
格式2
int[][] arr=int[3][];
二维数组中有3个一维数组;
每个一维数组都是默认初始值null;
可以对这个三个一维数组分别进行初始化
arr[0]=new int[3];
arr[1]=new int[1];
arr[2]=new int[2];
二维数组分布情况:
定义一维数组后的分布:
int[][] array=new int[3][];//明确了二维数组的长度,没有明确具体的一维数组。
System.out.println(array);//输出为[[I@15db9742
System.out.println(array[0]);//null
System.out.println(array[0][0]);//NullPointerException空指针
格式3
int[][] arr= {{23,17,11},{88,11,33,90},{11,78,34}};
//求和
int sum=0;
for(int i=0;i<arr.length;i++) {//遍历二维数组
for(int j=0;j<arr[i].length;j++)
sum+=arr[i][j];
}
System.out.println(sum);
数组的练习
数组反转
需求:对一个给定的数组进行反转。
[23,14,88,5]–>
[5,88,14,23]
public static void main(String[] args) {
int[]arr= new int[] {23,14,88,5};
reverse(arr);
}
public static void reverse(int[] arr) {
for(int start=0,end=arr.length-1;start<end;start++,end--) {
swap(arr,start,end);
}
}
public static void swap(int[] arr,int a,int b) {
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
获取插入点
需求:如果往有序的数组中插入一个元素并继续保持有序,问如何获取该位置?
思路:
1.既然是有序的数组,而且是找位置,必须要想到二分查找法。
public static void main(String[] args) {
int[]arr= new int[] {9,13,17,22,31,46,58,77};
int index=binarySearch(arr,7);
System.out.println("index="+index);
}
public static int binarySearch(int[] arr,int key) {
int min,max,mid;
min=0;
max=arr.length-1;
while(min<=max) {
mid=(min+max)>>1;
if(key<arr[mid])
max=mid-1;
else if(key>arr[mid])
min=mid+1;
else
return mid;
}
return min;
}
或者直接用java里的封装函数
import java.util.Arrays;
public class Myclass1 {
public static void main(String[] args) {
int[]arr= new int[] {9,13,17,22,31,46,58,77};
int index=binarySearch(arr,7);
System.out.println("index1="+index);
int index2=Arrays.binarySearch(arr,7);
System.out.println("index2="+index2);
}
public static int binarySearch(int[] arr,int key) {
int min,max,mid;
min=0;
max=arr.length-1;
while(min<=max) {
mid=(min+max)>>1;
if(key<arr[mid])
max=mid-1;
else if(key>arr[mid])
min=mid+1;
else
return mid;
}
return -(min+1);//如果该数不存在,用负数告诉该值不存在且插入值在哪里。还可以避免-0.
}
}