方法
Java是面向对象的语言,对象都会有一些方法,方法其实就是这些类可以做的事情,也称为函数
方法中,一般都会写一些执行了某些功能的代码
将来可以调用这个方法,从而去完成某些想要的功能
方法一般单独声明于类中,方法不可以写在main方法里,否则会报错
语法:
修饰符 返回值类型 方法名 (参数列表){
代码块;
return 返回值;
}
修饰符 : 暂时的写法 public static
返回值类型 :可以是void ,表示没有返回值 ,也可以是数据类型(基本类型和引用类型)
方法名 : 自己取的名字,遵循标识符命名规范
参数列表 :将来调用这个方法时候,是否需要传入值进行运算,如果不需要,可以不写
参数的定义方式 : 数据类型 变量名
代码块 : 将来方法中执行的功能
return :跟返回值类型挂钩
如果有返回值类型,那么就需要return 对应类型的值,
如果没有返回值类型,return可以省略
形参 :定义在方法体的括号中的参数
实参 :调用方法的时候,传入的实际的内容
案例代码如下
public class MethodDemo {
//写一个方法,调用之后,可以传入2个整数,并完成两个整数的计算求和后返回
public static int add(int a,int b){
int sum = a + b; //拿到传入的参数,并计算和
return sum; //把求和的结果返回
}
public static void main(String[] args) {
//调用方法,
//也可以将整个方法的表达式参与运算
System.out.println(add(10, 20));
// 可以声明一个变量,接收返回的值
int result = add(10,20);
System.out.println(result);
}
}
//方法的其他用法
public class MethodDemo02 {
public static void main(String[] args) {
//修饰符 返回值 方法名 (参数列表){
// 代码块;
// return;
// }
add();
//调用方法,传入参数的类型不能有错
add("hello","world");
//调用有返回值的方法
//1,要么将方法结果返回给一个变量
//2,要么将返回值结果,拿过来做运算
String s = addString();
System.out.println(addString());
//调用有参数有返回值的方法
String s3 = addString("你好", "世界");
String s1 = "你好";
String s2 = "世界";
String s4 = addString(s1, s2);
System.out.println(s3);
System.out.println(s4);
}
// 没有返回值的方法,一般在方法中,会把要做的事情处理完
//1,没有返回值,没有参数 ,某些固定的功能,不需要改变的时候使用这种
public static void add(){
String s1 = "hello";
String s2 = "world";
System.out.println(s1 + s2);
}
//2,没有返回值,有参数的情况,一般会根据用户传入的内容,执行对应的功能
public static void add(String s1,String s2){
System.out.println(s1 + s2);
}
//3,有返回值,没有参数的情况
public static String addString(){
//只要有返回值,必须对应有return
String s1 = "hello";
String s2 = "world";
//返回字符串的拼接
return s1+s2;
}
//4,有返回值,有参数的情况
public static String addString(String s1,String s2){
return s1 + s2;
}
//形参 :定义在方法体的括号中的参数
// 实参 :调用方法的时候,传入的实际的内容
}
下面是综合案例展示
public class MethodDemo02 {
public static void main(String[] args) {
add();
String s = methodString("nihao", "shijie");//这里的"nihao", "shijie"是实参,而方法里的s1,s2是形参
System.out.println(s);
}
//修饰符 返回值 方法名 (参数列表){
// 代码块;
// return;
// }
//方法定义不能放在main方法中,不然会报错
//没有返回值的方法,一般在方法中,会把要做的事情全部处理完
//没有返回值和参数的无参方法
public static void add(){
String s1 ="hello";
System.out.println(s1);
}
//没有返回值,有传入参数的有参方法
//只要有返回值,就有return
//return的返回值必须跟方法的返回值类型对应(定义一个string类型的方法,返回值如果有则必须为string类型)
//调用有返回值类型的方法时,要么将方法结果返回给一个定义的变量
//要么将返回值结果,拿过来做计算
//返回值结果可以继续参与运算
//有返回值参数定义新的变量接收可以使用alt+回车
//有返回值,有参数的有参方法
public static String methodString (String s1,String s2){
//定义在方法体中的参数(括号中的)叫形参,即形式参数,不管外界定义了什么参数,
// 被带入方法体中后就会变成对应的形参s1,s2
//参与方法体中运算
//而实参是用户放方法里存入的实际内容,比如要往方法里存入"你好","世界"
String s3 = s1+s2;
System.out.println("methodString成功执行,返回两个字符串拼接结果");
return s3;//将s3字符串作为结果返回
}
}
方法传参调用小练习(实现输入两个数字进行交换,并输出返回结果(不需要返回值,只需要打印结果))
//定义一个方法,实现传入 a=? b=?交换之后的a=? b=?
public static void exchange(int a,int b){
System.out.println("交换之前的a="+a+" "+"b="+b);
int temp;
temp = a;
a = b;
b = temp;
System.out.println("交换过后的a="+a+" "+"b="+b);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int b = scanner.nextInt();
exchange(a,b);
}
方法递归(重点)
方法递归其实就是方法在自己的方法体中调用自身
递归在调用的时候,可能会产生栈溢出错误,使用的时候要注意控制递归的次数,而且将来要去指定递归结束的条件
方法递归使用案例如下
//方法递归的使用
public class MethodDemo03 {
public static void main(String[] args) {
//方法递归
//method01();
int sum = sum01(100);
System.out.println(sum);
int sum02 = sum02(100);
System.out.println(sum02);
}
//public static void method01(){
// int i = 1;
// System.out.println(++i);
// method01();
//}
//定义一个方法,传入参数n,可以返回1-n之间数值的和
//普通循环求法
public static int sum01(int n){
int sum = 0;
for (int i = 0; i <= n; i++) {
sum += i;
}
return sum;
}
//递归的写法 1+2+3+4+5+...+n
public static int sum02(int n){
if (n == 1){
return 1;
}
return n + sum02(n-1);
}
// n = 1 sum = 1
// n = 2 2 + sum02(1) ==> 2 + 1
// n = 3 3 + sum02(2) => 3 + 2 + 1
//..
}
递归小练习:青蛙跳级
题目要求如下
一只青蛙一次可以跳上1级台阶,也可以跳上2级。
求该青蛙跳上一个 n 级的台阶总共有多少种跳法(先后次序不同算不同的结果)
实例代码如下(总结下来每一次青蛙跳级的方法种类数量呈斐波那契数列排序:1,2,3,5,8........)
public static void main(String[] args) {
int n=jump(5);
System.out.println(n);
}
public static int jump(int n) {
if (n == 1||n == 2) {
return n;
}
return jump(n-1)+jump(n-2);
}
/*分析:
一级 1种 1 1
二级 2种 1+1 、2 2
三级 3种 1+1+1、2+1、1+2 1+2=3
四级 5种 1+1+1+1/1+2+1/1+1+2/2+1+1 2+3=5
五级 8种 3+5=8
............ .........
n级 f(n-1)+f(n-2)
**/
类似常见递归还有求数的阶乘以及一系列斐波那契数列问题(青蛙跳级,兔子繁殖等等)
数组
数组是java学习中一个非常重要的知识点,因此必须要牢牢掌握相关知识。
数组的定义
数组其实也是声明一个变量,跟普通的变量不同的是,可以存储相同数据类型的一组数据
数组是一个长度固定的数据结构
数据也是一个引用数据类型(对象)
数组的声明方式
语法:
步骤一:先声明数组
1、数据类型 变量名[];
2、数据类型[] 变量名;
步骤二:给数组声明空间
数组名 = new 数据类型[数组长度]
示例:
int[] array; 或者 int array[]; //推荐使用前一种
array = new int [10];
合并写法:
int[] array=new int[10];
步骤三:给数组的空间赋值,分配空间,根据数组的索引(对应下标)找到对应的空间
array[0]=10;
数组定义并赋值:(已经确定数组内的元素值与数量)
int [] array={2,5,3,2,6,4}
详细的数组定义赋值代码如下
//数组的声明
public class Demo01 {
public static void main(String[] args) {
//数组声明:
// 写法1
//创建数组,并声明空间,赋值给变量arr
int[] arr = new int[5];
//给数组空间赋值
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
//写法2:已知数组的内容。可以简写
int[] arr1 = new int[]{10,20,30,40,50};
//写法3 : 再简写
int[] arr2 = {10,20,30,40,50};
//使用写法1,声明一个String类型的数组,数组中有5个空间,内容随便写
String[] strArray = new String[5];
strArray[0] = "hello";
strArray[1] = "world";
strArray[2] = "java";
strArray[3] = "mysql";
strArray[4] = "linux";
//使用写法3,声明一个char类型的数组,数组有5个char类型的值
char[] charArray = {'a','b','c','d','e'};
}
}
数组的特征(长度、索引)
长度固定,索引下标从0开始 ,下标的值是 从 0 ~ 长度-1
数组的遍历(循环进行遍历)
public class Demo02 {
public static void main(String[] args) {
int[] arr = {10,20,30,40,50};
//直接输出数组,输出的是数组变量的引用地址
System.out.println(arr);
//通过数组下标,将它的值输出
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
System.out.println("------------------------");
//使用for循环遍历
//循环的次数 : 跟数组的长度一致
for (int i = 0; i < 5; i++) {
System.out.println(arr[i]);
}
System.out.println("------------------------");
//数组中,有一个length属性,可以返回数组的长度
System.out.println(arr.length); //5
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//增强for循环完成数组的遍历
//for(数据类型 变量 : 数据集合){
//}
System.out.println("------------------------");
for (int i :arr){
System.out.println(i);
}
//快捷键 :itar
for (int i = 0; i < arr.length; i++) {
int i1 = arr[i];
System.out.println(i1);
}
//iter
for (int i : arr) {
System.out.println(i);
}
}
//定义一个方法,调用方法的时候,可以传入一个数组,
// 然后这个方法可以将数组的内容输出
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
练习
循环录入5个学生的成绩到数组中
录完之后,将5个人的成绩输出,并输出其中的最高分
public static void createGetArray(){
//循环录入五个学生的成绩到数组中,录入之后,将五个人的成绩输出,并输出最高分
int [] arr3 =new int[5];
//创建输入对象
Scanner scanner = new Scanner(System.in);
//定义一个最高分,用以一会循环赋值后进行比较,获取最高分(需要定义在循环外面)
int max=0;
for (int i = 0; i < arr3.length; i++) {
System.out.println("请输入第"+i+"个学生的成绩:");
//通过数组下标获取出入的值
arr3[i]=scanner.nextInt();
max= max> arr3[i] ? max:arr3[i];//获取最高分
}
System.out.println("五个学生的成绩是:");
ArrayDemo01.printarr(arr3);
System.out.println("最高分是:"+max);
}
public static void main(String[] args) {
createGetArray();
}
数组的内存分配
1,int[] arr = new int[5] : 表示在内存的堆区申请一个空间,这个空间有5个位置,每个位置的默认值是0,然后将这个区域在内存中的地址,指向变量 arr
2,arr[0] = 10 ; 表示通过 arr对应的地址引用,找到内存中数组的位置空间,通过下标0,找到这个空间中对应下标的值,然后将10 替换掉原有的默认值
二维数组的创建和遍历
二维数组指的是,在数组中,继续存放数组的一种形式(二维数组的每一行就是一个一维数组)
练习
循环录入5个班的成绩(每个班里定义为有五名学生)到数组中
录完之后,将这五个班里每个班的学生总成绩依次输出。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//定义一个二维数组
int[][] array =new int[5][5];
//使用for循环完成成绩录入
//i班级,j学生
for (int i = 0; i < 5; i++) {
System.out.println("这是第"+(i+1)+"个班级");
for (int j = 0; j < 5; j++) {
System.out.println("第"+(j+1)+"个学生的成绩:");
array[i][j]= scanner.nextInt();
}
}
//统计每个班的总成绩
int sumgrade=0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
sumgrade+=array[i][j];
}
System.out.println("第"+(i+1)+"个班的总成绩为:"+sumgrade);
sumgrade=0;//总成绩要清零,不然输出的总分结果是累加了前面计算的班级的总分
}
}
冒泡排序
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
- 针对所有的元素重复以上的步骤,除了最后一个;
- 重复步骤1~3,直到排序完成
/*
冒泡排序
*/
public class BubbleSort {
public static void main(String[] args) {
//声明一个数组,
//排序是为了将数组中的数据按照顺序从小到大排列
int[] arr = {25,36,11,5,2};
System.out.println("排序前");
printArray(arr);
/* //第一次排序
for (int i = 0; i < arr.length - 1; i++) {
//将数组的值做两两比较
if (arr[i] > arr[i+1]){
//交换
int temp= arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println("第一次排序完:");
printArray(arr);
//第二次排序 25 11 5 2 36
for (int i = 0; i < arr.length-1-1 ; i++) {
//将数组的值做两两比较
if (arr[i] > arr[i+1]){
//交换
int temp= arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println("第二次排序完:");
printArray(arr);
//第三次排序
for (int i = 0; i < arr.length-1-1-1 ; i++) {
//将数组的值做两两比较
if (arr[i] > arr[i+1]){
//交换
int temp= arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println("第三次排序完:");
printArray(arr);
//第四次排序
for (int i = 0; i < arr.length-1-1-1-1 ; i++) {
//将数组的值做两两比较
if (arr[i] > arr[i+1]){
//交换
int temp= arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println("第四次排序完:");
printArray(arr);
for (int i = 0; i < arr.length -1 ; i++) { //外层循环控制总次数
for (int j = 0; j < arr.length-i-1 ; j++) {
if (arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}*/
bubbleSort(arr);
System.out.println("排序完:");
printArray(arr);
}
//定义一个冒泡排序的方法:
public static void bubbleSort(int[] arr){
for (int i = 0; i < arr.length -1 ; i++) { //外层循环控制总次数
for (int j = 0; j < arr.length-i-1 ; j++) {
if (arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
选择排序
n条数据,经过n-1趟排序,得到有序结果
- 开始排序之前,划分一个有序区域,和无序区域
- 第一次排序开始的时候, 从无序区一个个去寻找最小值,每次找到小的值就做标记,所有数据找完之后,
找到了无序区最小的值,把它移动最前面,作为有序区
- 继续在无序区找小的值,每一轮都找到一个无序区的最小值,把这个值,依次往有序区的后面排放(
其实是将最小值的位置,和有序区的后一个位置的值做交换)
- 重复以上第3步
public class SelectSort {
public static void main(String[] args) {
int[] arr = {33,12,4,56,23,44,74,3};
System.out.println("排序前:");
printArray(arr);
selectSort(arr);
System.out.println("排序完:");
printArray(arr);
}
//输出方法
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
//写一个选择排序方法
public static void selectSort(int[] arr){
//存在一个有序区和无序区
//排序开始之前,有序区没有内容
//第一次排序的时候,将第一个数值标记为有序的第一个值
for (int i = 0; i < arr.length - 1; i++) {
//指定一个最小数值的索引
int minIndex = i;
//从有序区的后面的第一个(i+1)开始遍历
for (int j = i+1; j < arr.length ; j++) {
//找到最小的值
if (arr[j] < arr[minIndex]){
//将最小值的下标做交换
minIndex = j;
}
}
//循环之后,做数据交换
if (i != minIndex){
int temp = arr[i] ;
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
}
插入排序
- 从第一个元素开始,该元素可以认为已经被排序;
- 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 如果该元素(已排序)大于新元素,将该元素移到下一位置;
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
- 将新元素插入到该位置后;
- 重复步骤2~5。
插入排序案例:
public static void main(String[] args) {
int[] arr ={10,36,5,48,20};
System.out.println("排序前的数组结果为");
printArr(arr);
insertSort(arr);
}
//插入排序方法
public static void insertSort(int[] arr){
//1.将数组中第一个数当做已经排好的有序区里的一个元素,同时定义一个需要插入的数
int insert_number;
//从第二个元素开始(i=1开始 即arr[1])
for (int i = 1; i <arr.length ; i++) {
insert_number=arr[i];
int g=i-1;
while (g>=0 && insert_number<arr[g]){//插入的数比他前面一个数要小
//就把前面区域比他小的数字的下标往后移一位(arr[g+1]与arr[g]数值交换)
arr[g+1]=arr[g];
//然后g--(从后往前循环对比,把已排序好的区域里的数据从后往前的分别跟目标插入值进行比较
// 如果满足while循环,即已排好的里面有值比需要插入的大,则将这个数字往后移动一个)
//同时g减一,继续下一个循环(找到下一个在排列有序区里并且比插入值小的数值元素)
//因为是从后往前比,所以是g--
g--;
}
//然后把插入的值赋值给arr[g+1]//将需要插入的数插入到指定位置
arr[g+1]=insert_number;
}
printArr(arr);//调用下面自定义的打印数组函数printArr
}
public static void printArr( int [] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();//换行
System.out.println("-------------------------");
}
了解各个排序的时间复杂度和空间复杂度(各个算法)
快速排序(速度最快的)
public class QuickSort {
//写一个快速排序的方法
public static void quickSort(int[] arr,int left , int right){
//提前声明需要使用的变量
int i,j,temp,t;
//递归结束条件
if (left > right){
return;
}
//开始排序
i = left;
j = right;
temp = arr[left]; //中间值
//循环判断
while (i < j){
//如果j下标的值,比中间值大,j做--操作
while (temp <= arr[j] && i < j){
j--;
}
//如果i下标的值,比中间值小,i做++操作
while (temp >= arr[i] && i < j){
i++;
}
//如果上面两个条件不满足,i 和 j 交换
if(i < j){
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
//最后需要将中间值和 j的值做交换
arr[left] = arr[j];
arr[j] = temp;
//递归调用左边
quickSort(arr,left,j-1);
//递归调用右边
quickSort(arr,j+1,right);
}
//输出方法
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
int[] arr = {10,31,43,2,34,12,4};
System.out.println("排序前");
printArray(arr);
//调用排序方法
quickSort(arr,0,arr.length-1);
System.out.println("排序后");
printArray(arr);
}
}
排序速度对比
public static void main(String[] args) {
Random random = new Random();
//声明一个长度为100000的数组(10万大小)
int[] arr =new int[10000];
for (int i = 0; i < arr.length; i++) {
//向数组里存入随机的小于10000的数
arr[i]=random.nextInt(10000);
}
//System.currentTimeMillis()可以返回当前时间的毫秒值
long start = System.currentTimeMillis();
System.out.println("排序前");
//调用各个排序方法
// BubbleSort.boboSort(arr);//14729 -10w 144 -1w
// InsertSort.insertSort(arr);//1028 -10w 14 -1w
// SelectSort.selectSort(arr);//4048 -10w 58 -1w
QuickSort.quickSort(arr,0, arr.length-1);//25 -10w 2 -1w
System.out.println("排序后");
long end = System.currentTimeMillis();
long time = end -start;
System.out.println("排序花费时长为"+time+"毫秒");
}