入门JAVA第五天 方法与数组

目录

一、方法

1.1概念

1.2方法的定义

 案例1: 定义出一个静态方法功能,求任何两个整数的和

 案例2 : 定义出一个方法功能, 比较两个浮点类型数据是否相等

案例3 : 定义出一个方法功能, 打印1-n整数(1-n任意整数打印, n为正整数 Scanner)

1.3 方法调用

1.4 形参与实参

1.5 方法定义注意事项

1.6 方法内存理解

1.7 方法练习

1.8 方法重载

 1.9 方法课堂练习

二、数组

2.1 基础

(1)基本概念

 (2)数组的动态初始化

(3)数组的访问格式  

(4)数组的静态初始化

2.2 数组的异常

2.3 数组的内存分析

(1)Java的内存划分和作用

 (2)数据在内存中的存储

 2.4 数组的常见操作

(1)遍历数组元素

(2)数组获最值

 (3)数组元素交换

 (4)冒泡排序  (重点!)

2.5数组的拓容(拓展内容)


一、方法

        在学习方法前我们先要了解类,一个类又是由什么组成的呢?

        类的组成:属性(数据)、方法(函数)、构造器(.class文件中,而且是三者中的必有项)

1.1概念

        具有某种特定功能的代码段.某段代码功能经常使用,因此使用{}花括号,将这段代码包起来,起个名字,以后就使用这个名字来代替这段代码。

高内聚低耦合
public class Day0504 {
 
     //代码块
     {
     int i = 0;
     System.out.println("上课玩手机的同学注意了!");
     }
 
     //方法定义的三要素:返回值 名字 参数
     static void show(){
     int i = 0;
     System.out.println("上课玩手机的同学注意了123!");
     }
     //静态方法
     public static void main(String[] args) {
     show();
     }
}




类 class的基本组成 属性+方法
属性是什么? 常量、变量(全局变量+局部变量)
方法是什么? 方法就是给定名字的作用域,可以公共调用。
# 做一个两个数的求和
public class Day0505 {
 
     //静态方法
     public static void main(String[] args) {
     
     //两个数求和
     //....
     //System.out.println("两个数求和");
     //方法调用
     int ax = sum(50,10); //谁用谁传参。
     System.out.println(ax);
     System.out.println(sum(50,10));
     //10个数的平均数
     // ...
     //System.out.println("10个数的平均数");
     }
     //两个数求和
     static int sum(int a,int b){
     return a+b;
     }
     //10个数的平均数
     static int avg(int[] a){
     return 0;
     }
}
# 为了方便会将两个数的求和定义出一个单独的方法, 以后求和直接调用即可。
        举例: Scanner类中的nextInt()方法功能,nextInt为方法名,每次需要通过键盘录入一个整数,调用
nextInt方法即可.如若没有nextInt方法的封装,那么每次键盘录入数据,逻辑需要重新实现。
        方法好处:
               1)提高了代码的 复用性 (反复使用)
               2)提高了代码的 封装性 ,大括号中的内容,其他调用者看不到也无法直接访问
               3)简化了软件设计的思维难度

1.2方法的定义

        方法定义的格式:

# 方法定义 返回值-名字-参数(这三个一个不能少的)
# 完全定义:访问修饰符 [static / final ] 返回值 方法名(小驼峰) (参数...) {}
# 一般方法 / 普通方法 / 非静态方法
修饰符 返回值类型 方法名称 ( 参数列表 ) {
方法体语句 ;
return 语句 ;
}
# 静态方法
修饰符 static 返回值类型 方法名称 ( 参数列表 ) {
方法体语句 ;
return 语句 ;
}

        特殊方法(格式不可修改) :

 //主函数 主方法 程序执行入口方法

public static void main1(String[] args)

        定义详解: 
1 ) 修饰符 : 目前全都写成 public staitc
2 ) 返回值类型 : 表示方法运行结果的数据类型 . 当方法功能运行完毕 , 有会有产出 , 就需要将产出的数据类型
返回给方法调用者 . 如果不需要返回结果 , 使用关键字 void , 表示方法没有任何返回值类型 .
3 ) 方法名称 : 给这段代码起的名字 , 只要是一个合法的标识符即可 . 第一个单词的首字母小写 , 从第二个单词
4 ) 参数列表 : 这段代码要完成功能 , 可能会需要一些资源 . 在参数列表中 , 需要定义一些变量 , 内存中表示为容
在调用本方法的时候 , 会由外界传入数据 , 存储到这些变量容器中 . 使用变量符号 , 表示那些将来可能传入
5 ) 方法体语句 : 真正要完成该方法功能的执行逻辑 . {} 作用域
6 ) return 语句 : 最终生产出来的结果 , 要返回给调用者 , 使用 return 语句返回 . 如果没有任何生产内容 ,
可以不写 return 或者写 return; 用于表示方法结束。

        代码实例:

public class S0501 {
     //主函数 程序的入口 - 上帝
     public static void main(String[] args) {
 
     //两个整数求和 90 80 -- 得到的数在main中打印
     int s = sum2(90,80);
     System.out.println("s:"+s);
 
     }
     //方法级别的功能 两个整数求和
     public static void sum1(int a , int b){
     System.out.println(a+b);
     }
     public static int sum2(int a , int b){
     return a+b;
     }
     //普通方法定义-无返回值
     public static void show1(){
     System.out.println("我是show1");
     }
     //普通方法定义-有返回值
     public String show2(){
     return "我是返回值";
     }
     //普通方法定义-有参数
     public void show3(int a,int b){
 
     }
     //普通方法定义-无参数
     public void show4(){
 
     }
}

 案例1: 定义出一个静态方法功能,求任何两个整数的和

public class S0502 {
     public static void main(String[] args) {
 
     //System.out.print(sum(12,10));
     int result = sum(12,10);
     System.out.print(result);
 
     }
 
     //求和的方法
     public static int sum(int m,int n){
     //int sum1 = m + n;
     //return sum1;
     return m + n;
     }
 
}

 案例2 : 定义出一个方法功能, 比较两个浮点类型数据是否相等

public class Day0506 {
 
     public static void main(String[] args) {
 
     //调用
     twoFloatIsEq(5.5F,5.5F);
     //结果返回给调用者
     System.out.println(twoFloatIsEq3(5.5F,5.1F));
     boolean b = twoFloatIsEq3(5.5F,5.1F);
     System.out.println(b);
     }
 
     //第一种形式 - 一颗星(公用)
     //问题:结果不要写在方法里,结果应该给调用者操作
     public static void twoFloatIsEq(float a, float b){
     if(a == b){
     System.out.println("相等");
     }else{
     System.out.println("不相等");
     }
     }

 //第二种形式 三颗星
     public static boolean twoFloatIsEq1(float a, float b){
     if(a == b){
     return true;
     }else{
     return false;
     }
     }

 //第三种形式 四颗星
     public static boolean twoFloatIsEq2(float a, float b){
     if(a == b){
     return true;
     }
     return false;
     }
     //第四种形式 五颗星
     public static boolean twoFloatIsEq3(float a, float b){
     return a == b ? true : false ;
     }
}

案例3 : 定义出一个方法功能, 打印1-n整数(1-n任意整数打印, n为正整数 Scanner)

import java.util.Scanner;
public class S0503{
 
     public static void main(String[] args) {
 
     Scanner sc = new Scanner(System.in);
     System.out.println("请输入一个整数:");
     int n = sc.nextInt();
     //方法调用
     printInt(n);
 
     }
     //定义出一个方法功能, 打印1-n整数(1-n任意整数打印, n为正整数 Scanner)
     public static void printInt(int n){
     //循环
     for(int i = 1; i <= n;i++){
     System.out.println(i);
     }
     }
    }
    public static void printNumber(){
     Scanner sc = new Scanner(System.in);
     int max = sc.nextInt();
     //判断max范围
     if(max <= 0){
     System.out.println("请输出正确的数字");
     }else{
     //正确的
     for (int i = 1; i <= max ; i++) {
     System.out.println("i = " + i);
     }
     }
}

1.3 方法调用

        格式: 方法名称(实际参数);
调用格式详解:
方法调用的三种形式:

方法调用总体特点: 方法不调用,就不执行。
当程序加载一个类到 JVM 虚拟机 ( 加载 . class 到方法区中 ) 的时候,首先出初始化全局的静态的常量、全局的静态变量,值的位置就直接存储在方法区中,方法是一种特殊的,只有调用的时候才会执行 ( main 方法除外 ) ,所有的方法执行都通过栈 ( 专门执行方法用的),如果方法中有局部的变量,那么方法执行的时候,会直接在栈中初始化。

1.4 形参与实参

形参:形式参数
实参:实际参数
方法调用者一定传递的是实际参数,具体执行的方法中的参数是形式参数。  

代码实例: 

1.5 方法定义注意事项

1. 方法定义注意事项 :
1 ) 方法不能嵌套定义 , 每一个方法都是独立的
2 ) 方法的先后没有区别 , 都是平级关系
3 ) 方法可以嵌套调用 , 甚至可以自己调用自己 ( 递归 )
2 参数列表 1 ) 形式参数 : 在定义方法时使用 , 需要加上数据类型的参数 , 也就是对于变量进行声明 . 各个变量之间 ,
2 ) 实际参数 : 在方法调用时使用 , 不能加上数据类型的参数 , 也就是对于变量进行赋值 . 各个实际参数之
也使用逗号分隔 , 顺序必须和定义的方法的形式参数的顺序一致 .
3.return 语句 :
1 ) return 语句表示方法结束了 , 也同时表示方法的产出内容 .
2 ) 如果方法没有具体的返回内容 , 可以写成 return; 此时的 return 语句可以省略 , 返回值类型必须写成void
3 ) 如果方法有具体的返回内容 , 那么 return 后面就需要加上返回具体数据 , 返回值类型必须和 return 语句后面的数据类型一致
4 ) 谁来调用当前方法 , return 语句就将当前方法的数据结果返回给谁

1.6 方法内存理解

(1)栈内存概念:
        JVM虚拟机运行代码: JVM虚拟机就是运行Java代码的容器,JVM本身就是个软件,运行时就需要在内存中开辟空间。JVM将其占有的内存空间划分区域,其中一块空间,称为栈内存。
        
(2)栈内存:
        需要在栈内存中 代码中的方法运行, 开辟空间运行; 方法调用时进入栈内存中开辟空间, 方
法运行完毕, 出栈内存, 占有空间释放(方法弹栈死亡)

1.7 方法练习

案例1: (钱就表示参数, 酒表示返回值结果)
    1)王老头去第一次买酒,到商店发现没有带钱,那就没有买回酒.输出:钱都没有买个锤子.
    2)王老头去第二次买酒,到商店发现没有带钱,但是老板娘是熟人,一番沟通,带回了一瓶二锅头.
    3)王老头去第三次买酒,刚发了工资,到商店,给钱之后,老板见钱眼开,拿钱跑路,只留老头一人凌乱.
    4)王老头去第四次买酒,到商店给钱之后,老板给王老头一瓶江小白.
package com.xja;

import java.util.Scanner;

/**
 * <p>
 *
 * </p>
 *
 * @描述:
 * @author: xiuxian323
 * @since:2023/2/2 8:53
 * @version:
 */
public class D04 {
    public static void main(String[] args){
        
    }
    //第一种情况
    public static void Wang1(){  //无参表示没钱
        System.out.println("钱都没有,买个锤子");
    } 
    public static String Wang2(){  //无参表示没钱
        return "老板娘是熟人,带回一瓶二锅头";
    }
    public static void Wang3(int a){  //无参表示没钱
        System.out.println("钱都没有,买个锤子");
    }
    public static String Wang4(int a){  //无参表示没钱
        return "江小白";
    }
        


}

1.8 方法重载

方法的重载: 超载Overload单词
方法重载的概念记住 : 有时笔试题中, 会出现 “ 什么是Overload(重载), 什么是Override(重写)
在同一个类中,方法名相同,参数列表不同的多个方法,称为重载(与返回值类型无关)。
举例: 客户要求定义出几个方法:
1)要求做两个任意整数求和
2)要求做三个整数求和
3)要求做2个double浮点类型求和
场景: 在功能上类似的三个求和方法,每个方法都有自己的方法名,不便于记忆,如果让类似功能具有
相同方法名, 通过参数列表不同区分多个方法,如此也可以实现,这就是方法重载.
代码实例:
class S0505 {
     public static void main(String[] args) {
     System.out.println(add(33,8));
     System.out.println(add(33,8,4));
     System.out.println(add(33.3f,8.6f));
     }
     //要求做两个任意整数求和
     public static int add(int m, int n){
     return m+n;
     }
     //要求做三个整数求和
     public static int add(int a, int b, int c){
     return a+b+c;
     }
     //要求做2个double浮点类型求和
     public static float add(float a, float b){
     return a+b;
     }
}
参数形式不同的情况:
        参数类型不同;参数个数不同;参数类型的顺序不同;
方法重载的好处:
1 ) 没有重载的时候 , 相同逻辑相同功能的代码 , 需要定义很多个方法名称 . 调用者在记忆方法名称的时候 , 就会变的很复杂。
2 ) 有重载之后 , 相同功能逻辑的方法 , 只需要记忆一个名字。

Java中重载和重写的区别【面试题】 

重载: overload 发生在同一个类中,有相同的方法名,但是参数列表不同,我们叫方法重载(和返回无关)
重写: override 发生在继承关系和接口和实现类关系中,表示子类 / 实现类重写一个父类 / 接口中的方法,要求方法名、参数、返回值,必须一致。

 1.9 方法课堂练习

        使用方法重载的方式实现 一个和尚挑水吃,两个和尚抬水吃,三个和尚没水吃。 参数:和尚
/**
* 和尚挑水 悟空 悟能 悟净
*/
    public static void drink(String name){
         System.out.println(name + "一个人挑水喝");
    }
    public static void drink(String name1,String name2){
         System.out.println(name1 + "和" + name2 + "两个人抬水喝");
    }
    public static void drink(String name1,String name2,String name3){
         System.out.println("三个和尚没水喝");
    }
    public static void main(String[] args) {
         drink("悟空","悟净","悟能");
    }
        定义重载的方法并调用,方法名为computed, 三个方法分别接收一个int参数,两个int参数,一个 double参数。 分别执行平方运算,并打印结果。
    /**
     * 定义重载的方法并调用,方法名为computed, 三个方法分别接收1个int参数,两个int参数,一个double参数。 分别执行平方运算,并打印结果。
     */
    public static void computed(int i){
        System.out.println(i*i);
    }
    public static void computed(int m,int n){
        System.out.println(m*m + n*n);
    }
    public static void computed(double x){
        System.out.println(x * x);
    }

    public static void main(String[] args) {
        computed(2,3);
    }
        如果想定义两个重载的方法,分别执行int类型(不限个数)的值相加和double类型(不限个数)的值相加,怎么办?
    /**
     * 不限制个数的参数 ...可变的参数序列
     * 语法:数据类型... 名字
     */
    public static void add(double... array){
        double sum = 0;
        for (int j = 0; j < array.length; j++) {
            sum += array[j];
        }
        System.out.println("sum = " + sum);
    }

    public static void main(String[] args) {
        add(1,2,3,4,6);
    }

可变参数:

        格式:数据类型... 参数名

可变的参数序列在一个方法的参数内只能有一个,且必须放在最后。

二、数组

        同学统计:通过Scanner录入10个学生,录入成功之后将所有的学员传递给printStudent方法
中,输出所有的学员信息。
public class S05S {
 public static void main(String[] args) {
     Scanner scanner = new Scanner(System.in);
     //数组 集合
     String[] studentNames = new String[10]; //10 容量
     for (int i = 0; i < 10; i++) {
         System.out.println("请输入第"+(i+1)+"个学生姓名:");
         studentNames[i] = scanner.next();
     }
     //调用
     printStudent(studentNames);
 }
 public static void printStudent(String[] names){
     for (int i = 0; i < names.length; i++) {
         System.out.println("名称:"+ names[i]);
         }
     }
}

2.1 基础

(1)基本概念

集中存储相同类型数据的容器叫做数组

应用举例 :
现在需要统计某公司员工的工资情况 , 假设该公司有 50 名员工 , 例如计算平均工资、找到最高工资等 .
[ 8000 , 222 , 222222 , 1122...... ]
a: 没有数组 , 首先需要声明 50 个变量来分别记住每位员工的工资 , 然后再进行操作 , 变量的数量会极其庞大,而且容易出错。
b: 有数组 , 可以将 50 个员工的工资全部存储在数组中 , 给这个容器起名 , 而数组中的每一个数据都有对应的顺序编号,根据存入的顺序编号从0 开始 , 依此类推 , 通过 " 容器名 + 数据编号 " , 可以定位每一个数据 , 从而更快更准确的寻找数据。

数组的特点

 1)存储数据长度固定的容器(数组的长度一旦定义不可变!!), 数组是一个定长容器, 当定义一个数组时,它的长度就不再可以改变。

2 ) 存储数据的数据类型要一致。

 体验案例

public class Day0510 {
 
 public static void main(String[] args) {
     int zhangsan = 2500;
     int lisi = 7500;
     int wangwu = 12500;
     int zhaoliu = 82500;
     int tianqi = 12500;
     int[] arr = new int[5];
     //索引
     arr[0] = 2500;
     arr[1] = 7500;
     arr[2] = 12500;
     arr[3] = 82500;
     arr[4] = 12500;
 
     System.out.println(arr[2]);
 }
}

 (2)数组的动态初始化

1. 含义 : 只指定数组长度和类型不指定数组元素值 .
2. 数组的定义 :
        数据类型 [] 数组名称 = new 数据类型 [ 数组长度 ] ; // 更常见
        数据类型 数组名称 [] = new 数据类型 [ 数组长度 ] ;
3. 详细解释 :
        数据类型: 创建的数组容器可以存储什么数据类型 基本数据类型 8 个、 String
        [] : 表示数组 ( 参数 ) [ 数组 ] { 作用域 } < 泛型 >
        数组名称: 数组本身也是一个变量,用于存储数组的地址的变量名
        = : 赋值符号 , 将数组的地址 , 赋值给数组名称
        new: 关键字 , 创建数组使用的关键字 , 用于在堆内存中给数组开辟存储数据的空间
        数据类型: 和前面的数据类型保持一致 数组长度 : 表示数组容器中可以存储多少个元素
4. 举例 :
        int [] arr = new int [ 3 ] ;
        定义出一个数组 , 数组名 arr , 数组中可以存储 3 int 类型整数

实例代码: 

public class S0508{
 public static void main(String[] args) {
 
 //数据类型[] 数组名称 = new 数据类型[数组长度];
 int[] arr = new int[10];
 
 //取数据 第五个值 index索引 01234
 System.out.println(arr[4]);
 //添数据
 arr[4] = 10086;
 
 System.out.println(arr[4]);
 //new 实例化 - 初始化 - 创建 - 在堆内存中开辟空间
 
 }
}

 内存图:

 代码执行顺序:

 输出的解释

// [ I@15db9742 : 表示数组 arr 在内存中的地址值 ( 位置 )
// [ : 表示一维数组
// I : 大写字母 i , 表示数组中存储的数据类型为 int , 首字母大写 BSILFDC
// @ : 没有任何含义 , 只做前后的分隔
// 15db9742 : 十六进制数 , 就是数组在内存中的地址,可以定义多种类型数组测试

(3)数组的访问格式  

1. 索引 : 每一个存储到数组的元素 , 都会自动的拥有一个编号 , 0 开始 , 这个自动编号称为数组索引 ( index
可以通过数组的索引访问到数组中的元素 . 索引的范围 : 0 --- 数组长度 -1 .
: 索引也称为下标 , 角标 , 脚标
2. 索引访问数组中的元素 :
数组名 [ 索引 ] = 数值 ; // 为数组中的元素赋值
变量 = 数组名 [ 索引 ] ; // 获取出数组中的元素
3. 扩展 :
当定义出一个数组时 , JVM 虚拟机会默认为数组中的每一个元素进行默认的赋初值动作 , 根据不同数组中
整数 : 0
浮点类型 : 0.0
char 类型 : ‘ ’
boolean 类型 : false
引用数据类型 : null , null 表示引用数据类型为空

(4)数组的静态初始化

1. 含义 : 在创建数组时 , 直接将元素确定的定义方式
2. 格式 :
        数据类型 [] 数组名 = new 数据类型 []{ 元素 1 , 元素 2 , ..., 元素 n } ;
注意事项:
        1 ) 在第二个方括号中 , 不能写数组元素个数
        2 ) 元素值的罗列 , 元素和元素之间 , 使用逗号分隔
        3 ) 罗列出来的元素值 , 数据类型必须和声明数组时数据类型一致
        3. 简化格式 :
数据类型 [] 数组名 = { 元素 1 , 元素 2 , ..., 元素 n } ;
注意事项 : 不能分成两行写,测试:先定义后赋值!不符合 Java 中定义数组的语法结构
class S0507 {
 public static void main(String[] args) {
 
     //int[] arr0 = new int[]{334,11,67,11,0,3};
     int[] arr0 = {334,11,67,11,0,3};
 
     //通过循环取值
 for(int i = 0; i < arr0.length; i++){
     System.out.println(arr0[i]);
     }
 }
}

2.2 数组的异常

(1)索引越界

1. 索引越界异常(数组下标越界) :
        ArrayIndexOutOfBoundsException
        数组 索引 超出 边界 异常
2. 发生索引越界异常原因 :
        使用的索引在数组中不存在
3. 代码分析 :
        观察一下代码 , 运行后会出现什么结果
        public static void main ( String [] args ) {
        int [] arr = { 1 , 2 , 3 } ;
        System out println ( arr [ 3 ]) ;
        }
        创建数组 , 赋值 3 个元素 , 数组的索引就是 0 , 1 , 2 , 没有 3 索引 , 因此我们不能访问数组中不存在的索引 , 程序将会抛出 ArrayIndexOutOfBoundsException 数组越界异常 . 在开发中 , 数组的越界异常是不能出现
4. 越界异常避免方案
        不要访问不存在的索引 , 使用索引时 , 验证索引在 "0-- 数组长度 -1" 范围
5. 数组的长度属性 : 每个数组都具有长度 , Java 中赋予了数组一个属性 , 用于获取数组的长度 , 语句为 数组.length

(2)空指针异常

1. 空指针异常
        NullPointerException
        空 指针 异常
2. 发生空指针异常原因 :
        当引用数据类型值设置为null ( 前提 ), 证明这个变量引用没有指向任何堆内存地址 , 但仍然想通过这个
: null , 即为空 , 用于表示在栈内存的引用中 , 不记录任何堆内存的地址
3. 代码分析 :
        观察一下代码,运行后会出现什么结果
        public static void main ( String [] args ) {
                int [] arr = { 1 , 2 , 3 } ;
                arr = null;
                System . out . println ( arr [ 0 ]) ;
        }
        arr = null 这行代码 , 意味着变量 arr 将不会再保存数组的内存地址 , 也就不允许再操作数组了 , 因此运行的时候会抛出NullPointerException 空指针异常 . 在开发中 , 数组的越界异常是不能出现的 , 一旦出现,就必须修改代码来修正它。
4. 空指针异常避免方案
        在使用引用之前 , 先判断该引用的值是否为 null , 不为 null 再去访问

2.3 数组的内存分析

(1)Java的内存划分和作用

1. 内存概念 : 内存是计算机中的重要原件 , 临时存储区域 , 作用是运行程序 . 我们编写的程序是存放在硬盘中是不会运行的,必须放进内存中才能运行 , 运行完毕后会清空内存 .
2.Java 虚拟机的内存划分
        Java虚拟机要运行程序 , 对空间进行了不同区域的划分 , 因为每一片区域都有特定的处理数据方式和内存管理方式
        类比一处房子 , 房子中有厨房 , 专门进行做饭 ; 有卧室 , 专门进行休息 ; 有书房 , 专门进行学习和工作 ... 因次内存中的空间要像房子一样分门别类进行空间划分。

 (2)数据在内存中的存储

一个数组的内存图
        数组引用的输出的结果是地址 , 是数组在内存中的地址 . new 出来的内容 , 都是在堆内存中存储的 , 而方法中的arr是保存数组的地址

        两个数组的内存图

引用数据类型每次 new , 都在内存中开辟新的空间地址 .

多个引用指向同一个数组空间
 任意一个引用修改了数组中的内容,其他引用访问到的就是修改后的数据
 
 
public class Day0512 {
 
 public static void main(String[] args) {
 
 //属于同一个地址存在多个引用,任意一个引用改变值,全局都变。
 int[] arr1 = {100,200};
 //打印数组第一个值
 System.out.println(arr1[0]); //100
 //定义一个新的引用,等于arr1
 int[] arr2 = arr1;
 //打印arr第一个值
 System.out.println(arr2[0]); //100
 //arr2 改变第一个值
 arr2[0] = 1000;
 //测试是否改变
 System.out.println(arr2[0]); //1000
 //看看arr1的值有没有变化
System.out.println(arr1[0]); //1000
 }
}

 2.4 数组的常见操作

(1)遍历数组元素

1. 数组遍历 : 就是将数组中的每个元素分别获取出来 , 这就是遍历 .
2. 分析思路 :
        通过循环 , 访问到数组中所有元素的索引 , 0 lenght-1
        通过索引 , 访问到对应元素 , 数组名 [ 索引 ]

(2)数组获最值

public class Day0512 {
 
 public static void main(String[] args) {
 
 int[] arr = {1000,200,30,4000,500};
 
 int temp = arr[0];
 for(int i = 0; i < arr.length; i++ ){
 temp = temp > arr[i]?temp:arr[i];
 
 }
 System.out.println(temp);
 
 }
}
1. 给定一个数组 , 求出数组的最大值
2. 分析思路 ( 擂台思想 ) :
        1 ) 定义变量 , 保存数组 0 索引上的元素
        2 ) 遍历数组 , 获取出数组中的每个元素
        3 ) 将遍历到的元素和保存数组 0 索引上值的变量进行比较
        4 ) 如果数组元素的值大于了变量的值 , 变量记录住新的值
        5 ) 数组循环遍历结束 , 变量保存的就是数组中的最大值
示例:int [] arr = { 23 , 14 , 66 , 7 , 88 , 0 }

        图示: 

 演示代码:

class S0511 {
 public static void main(String[] args) {
     //读取最大值
     int [] arr = {23,14,66,7,88,0};
     //最大值
     int max = 0;
     //循环
     for(int i = 0; i < arr.length; i++){
         //每一个值都和max做比较,只要比max大。max=当前值
         if(arr[i] > max){
             max = arr[i];
         }
     }
     System.out.println(max);
 
 }
}

 (3)数组元素交换

        分析过程:

1. 将数组中指定索引的两个元素交换位置 .
        要求:把66 0 交换一下位置 打印数组
        int [] arr = { 23 , 14 , 66 , 7 , 88 , 0 } ;
2. 分析思路 :
        1 ) 将两个索引位置对应的元素值获取到
        2 ) 设计一个临时变量 , 先存储小索引元素的原值
        3 ) 大索引元素值赋值给小索引元素位置
        4 ) 临时变量值赋值给大索引元素位置

         实现代码:

import java.util.Arrays;
public class Day0512 {
 
 public static void main(String[] args) {
 
 int [] arr = {23,14,66,7,88,0};
 
 
 int temp;
 //2 5
 temp = arr[5]; //0
 //将arr[5]的值 换成arr[2]
 arr[5] = arr[2];
 arr[2] = temp;
 
 
 /*
 arr[2] = arr[2]^arr[5];
 arr[5] = arr[5]^arr[2];
 arr[2] = arr[2]^arr[5];
 */
 System.out.println(Arrays.toString(arr));
 }
}

         实现代码:

import java.util.Arrays;public class Day0512 {

public static void main(String[] args) {

int [] arr = {23,14,66,7,88,0};


int temp;
//2 5
temp = arr[5]; //0
//将arr[5]的值 换成arr[2]
arr[5] = arr[2];
arr[2] = temp;


/*
arr[2] = arr[2]^arr[5];
arr[5] = arr[5]^arr[2];
arr[2] = arr[2]^arr[5];
*/
//异或运算,如果需要了解可以自行查看位运算了解原理。
System.out.println(Arrays.toString(arr));
}
}

 (4)冒泡排序  (重点!)

        实现思想:

int [] arr = { 6 , 9 , 2 , 7 } ;
两种排序 结果
int [] arr = { 9 , 7 , 6 , 2 } ; // 降序
int [] arr = { 2 , 6 , 7 , 9 } ; // 升序 --- 有限实现
# 动态初始化
int [] 标识符 = new int [ 3 ] ; 标识符 [ index ] = | 标识符 [ index ]
# 静态初始化
int [] 标识符 = new int []{ , } ;
int [] 标识符 = { , } ;
1. 目标 : 通过冒泡排序算法将数组中的元素进行升序排序 | 降序
2. 原理 : 比较两个相邻的元素 , 将值大的元素交换至右端
3. 思路 ( 升序 ) :
        依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1 个和第 2 个数,将小数放前,大数放后。然后比较第2 个数和第 3 个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。
        在第二趟:仍从第一对数开始比较(因为可能由于 第一轮 时第2 个数和第 3 个数的交换,使得 第二轮 1 个数不再小于第2个数。
        一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到第二大的数。
如此下去,重复以上过程,直至最终完成排序。
...
4. 代码思路
用二重循环实现,外循环变量设为 i ,内循环变量设为 j 。假如有 n 个数需要进行排序,则外循环重复 n-1次,内循环则重复n-1-i次,每次进行比较的两个元素都是与内循环j 有关的,它们可以分别用 a [ j ] a [ j + 1 ] 标识, i 的值依次为 1

        内存图示:

         代码示例:

import java.util.Arrays;

public class Day0601 {
 public static void main(String[] args) {
 
 //静态
 double[] array = {9.9 , 0 , 3.9 , 3.14 , 7 , 100 ,6.4 };
 //原理:相邻的两个数进行比较 整体循环6次即可。
 // 0 3.9 3.14 7 9.9 6.4 100
 // 0 3.14 3.9 7 6.6 9.9 
 // 0 3.14 3.9 6.6 7
 // 0 3.14 3.9 6.6
 // 0 3.14 3.9
 // 0 3.14
 
 double temp = 0.0; 
 //外循环控制循环?轮 length - 1 少循环一轮
 for(int w = 0; w < array.length - 1; w++){
 //内循环排序 length - 1 少循环一次
 for(int y = 0; y < array.length - 1 - w; y++){
 //核心 交换数据
 if(array[y] < array[y+1]){
 temp = array[y+1];
 array[y+1] = array[y];
 array[y] = temp;
 }
 }
 }
 
 System.out.println(Arrays.toString(array));
 }
}

         降序版本:

int [] arr = {226,91,2,7,22,122,0,12,6};
import java.util.Arrays;
public class S0510 {
 public static void main(String[] args) {
 
 //冒泡-降序
 int [] arr = {226,91,2,7,22,122,0,12,6};
 int temp = 0;
 for(int k = 0; k < arr.length -1; k++){
 for(int i = 0; i < arr.length -1 -k; i++){
 //判断
 if(arr[i] < arr[i+1]){
 //交换
 temp = arr[i];
 arr[i] = arr[i+1];
 arr[i+1] = temp;
 }
 }
 }
 System.out.println(Arrays.toString(arr));
 }
}

2.5数组的拓容(拓展内容)

# 定义完成的数组是不能再这个数组 的基础上进行扩容的。数组一旦定义长度固定!!!!!!
# int [] arr = {6,9,2,7};
# 问题: arr 这个数组的基础之上,再存?个数。怎么办?
# 真实问题:原来的数组的数据不变,能不能再这个基础上再增加一个数据。!!
Java 数组扩容的原理
1 Java 数组对象的大小是固定不变的,数组对象是不能改变容量大小的。
2 )利用数组复制方法可以变通的实现数组扩容。
3 System . arraycopy () 可以复制数组。
4 Arrays . copyOf () 可以简便的创建数组副本。 --- 可以查阅源码分析
5 )创建数组副本的同时将数组长度增加就变通的实现了数组的扩容。

         案例代码:

import java.util.Arrays;
public class Day0602 {
 public static void main(String[] args) {
 
 int[] arr = {3,5};
 System.out.println(arr);
 //希望变成 arr = {3,5,10,20};
 //arr[2] = 10; //越界异常。
 //原理,定义一个新的数组,长度制定为3 把原来旧的值放进来
 //当前旧数组的引用指向新的地址空间。
 arr = Arrays.copyOf(arr,arr.length +2);
 System.out.println(arr);
 arr[2] = 10;
 arr[3] = 20;
 System.out.println(Arrays.toString(arr));
 }
}

        

import java.util.Arrays;
/** 数组变长算法!
* 数组对象长度不可改变
* 但是很多实际应用需要长度可变的数组
* 可以采用复制为容量更大的新数组, 替换原数组, 实现变长操作
* */
public class ArrayExpand {
 public static void main(String[] args) {
 //数组变长(扩容)算法!
 int[] ary={1,2,3};
 ary=Arrays.copyOf(ary, ary.length+1);
 ary[ary.length-1]=4;
 System.out.println(Arrays.toString(ary));//[1, 2, 3, 4]
 //字符串连接原理
 char[] chs = { '中', '国' };
 chs = Arrays.copyOf(chs, chs.length + 1);
 chs[chs.length - 1] = '北';
 chs = Arrays.copyOf(chs, chs.length + 1);
 chs[chs.length - 1] = '京';
 //字符数组按照字符串打印
 System.out.println(chs);//中国北京
 //其他数组按照对象打印
 System.out.println(ary);//[I@4f1d0d
 }
}

        数组拓容使用案例:

统计一个字符在字符串中的所有位置 .
字符串 : 统计一个字符在字符串中的所有位置
字符 : ' '
返回 : { 4 , 7 } // 使用数组扩容的理念完成 初始化 int [] count ={ 4 , 7 } ;

         难点:如何循环读取一个字符串

charAt(i);

         实现代码: 

import java.util.Arrays;
class S0515 {
 /**
 统计一个字符在字符串中的所有位置.
 字符串: 统计一个字符在字符串中的所有位置
 字符: '字'
 返回: {4,7} //使用数组扩容的理念完成 初始化 int[] count={4,7};
 **/
 public static void main(String[] args) {
 int[] count= {};
 String str = "统计一个字符在字符串中的所有位置";
 //数组长度 arr.length; 属性
 //字符串去长度,str.length(); 调用的是方法
 for(int i = 0 ; i < str.length(); i ++){
 if('字' == str.charAt(i)){
 //记录索引
 count = Arrays.copyOf(count,count.length+1);
 //把当前索引记录到数据组,索引的最大值count.length-1
 count[count.length-1] = i;
 }
 }
 System.out.println(Arrays.toString(count));
 }
}

        使用案例:

public class Day0603 {
 public static void main(String[] args) {
 //希望 将字符串分割成字符数组
 String str = "今天天气非常冷";
 //获取长度 字符串长度length()方法,数组length属性
 System.out.println(str.length());
 //创建定长的字符数组
 char[] c = new char[str.length()];
 //将字符串的字摘出来放进数组中
 for(int i = 0 ; i <str.length(); i++){
 //charAt() 专门从字符串中读取字符
 System.out.println(str.charAt(i));
 //动态赋值
 c[i] = str.charAt(i);
 }
 System.out.println(Arrays.toString(c));
 }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

修贤323

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值