07 Java数组与数组操作(定义+遍历+排序+增删改查)(下)

简介: 07 Java数组与数组操作(定义+遍历+排序+增删改查)

07 Java数组与数组操作(定义+遍历+排序+增删改查)(上):https://developer.aliyun.com/article/1580194

7.7.2 选择排序

选择排序升序思路:

  • 1、将当前这个数,与他后面每一个数字比较,选择最小的那个数,交换到当前位置
  • 2、循环选择当前位置上的数
public static int[] sort1(int[] arr) {
    for (int j = 0; j < arr.length-1; j++) {
        //选择下标为0的位置
        int min = j;
        //将当前这个数与后面的每一个数进行比较
        for (int i = j+1; i < arr.length; i++) {
            if(arr[min] > arr[i]) {
                min = i;
            }
        }
        //arr[j]   arr[min]
        if(min != j) {
            int temp = arr[j];
            arr[j] = arr[min];
            arr[min] = temp;
        }
    }
    return arr;
}

细分示例:

public class newArray {
    //选择排序
    public static void selectSort(int[] arr){
        //外层循环控制轮数
        for (int i = 0; i < arr.length-1; i++) {
            int min=i;//保存最小元素的下标
            for (int j = i+1; j < arr.length; j++) {
                if(arr[j]<arr[min]){
                    min=j;//最小的下标
                }
            }
            if(min!=i){
                int t=arr[i];
                arr[i]=arr[min];
                arr[min]=t;
            }
        }
    } 
}
7.7.3 Arrays工具类排序方法
public class Demo03 {
  //Arrays类提供的数组排序的方法
  public static void main(String[] args) {
    int[] arr = {11,22,33,31,41,15};
    
    //Arrays类提供的数组排序的方法     快速排序
    Arrays.sort(arr);
    
    for (int i = 0; i < arr.length; i++) {
      System.out.println(arr[i]);
    }
    System.out.println("==============================================");
    String[] names = {"cxk","rose","lihua","lilei","zhaosi"};
    
    Arrays.sort(names);

    for (int i = 0; i < names.length; i++) {
      System.out.print(names[i]+"\t");
    }
    
  }
}

API 工具类

Arrays工具类的使用

public class Demo {
    public static void main(String[] args) {
        int[] nums={15,10,3,20,13,1,20,35,39,28,18,22};
        //1 排序 Arrays.sort();
        Arrays.sort(nums);
        //2 字符串形式 Arrays.toString();
        String s=Arrays.toString(nums);
        System.out.println(s);
        //3 二分查找
        int pos=Arrays.binarySearch(nums,1);
        System.out.println(pos>=0?"找到了":"没有找到");
        //4 复制数组
        int[] newArr=Arrays.copyOf(nums,nums.length*2);
        System.out.println(Arrays.toString(newArr));
        //截取数组前num项
        int[] newArr= Arrays.copyOf(nums,5);
        System.out.println(Arrays.toString(newArr));
        //5 填充,fill
        Arrays.fill(nums,100);
        System.out.println(Arrays.toString(nums));
    }
}
补充 JDK API 1.6
7.8 二分查找法

二分查找法(折半查找法)

  • 前提:数组中的元素是有序的
  • 思路
  • 首先找到数组中的中间的元素,与要查找元素进行比较,如果相等,那么就直接找到了
  • 如果比中间的元素大,那么表示查找元素在中间值的右边。所以最小值的下标等于中间值的下标+1
  • 如果比中间的元素小,那么表示查找元素在中间值的左边。所以最大值的下标等于中间值的下标-1
//二分查找法
public static int search2(int[] arr,int num) {
    //1、获取最小、大值的下标
    int min = 0;
    int max = arr.length -1;

    while(min <= max) {
        //2、获取中间值的下标
        int middle = (min + max) / 2;

        //3、将要查找的数字与中间值做比较
        if(num > arr[middle]) {
            min = middle +1;
        }else if(num < arr[middle]) {
            max = middle -1;
        }else {
            return middle;
        }
    }
    return -1;
}

对比:顺序查找与二分查找

import java.util.Scanner;
public class Demo {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        System.out.println("请输入您要查找的元素");
        int n=input.nextInt();
        //int pos=sequenceSearch(n);
        int pos=binarySearch(n);
        System.out.println(pos>=0?"找到了":"没有找到");
    }
    //顺序查找:从第一个元素遍历到最后一个元素,查找符合要求的。
    public static int sequenceSearch(int key){
        int[] arr=new int[]{15,2,8,20,3,28,30,16,22};
        for (int i = 0; i < arr.length; i++) {
            if(key==arr[i]){
                return i;
            }
        }
        return -1;
    }
    //二分查找:二分查找前提,数组是有序的。
    //每次从中间开始查找,如果比中间数字小,在左边查找,如果比中间数字大,在右边查找,依次再进行二分查找,直到找到为止。
    public static int binarySearch(int key){
        int[] arr=new int[]{1,3,5,8,10,15,22,23,25,30,35,50,55,60};
        int low=0;
        int upper=arr.length-1;
        while(low<=upper){
            int mid=(low+upper)>>>1;
            if(key<arr[mid]){
                upper=mid-1;
            }else if(key>arr[mid]){
                low=mid+1;
            }else{
                return mid;
            }
        }
        return -1;
    }
 
}
7.9 二维数组
  • 一维数组中的每一个元素,存储的是一个数据
  • 二维数组中的每一个元素,存储的是一个一维数组
public class newArray {
    public static void main(String[] args) {
        //声明二维数组
        int[][] nums1=new int[][]{ {10,20,30},{40,50,60} };
        int[][] nums2=new int[2][3];// 第一维数组长度是2, 第二维数组长度是3

        nums2[0][0]=100;
        nums2[0][1]=200;
        nums2[0][2]=300;
        nums2[1][0]=400;
        nums2[1][1]=500;
        nums2[1][2]=600;

        //输出数组长度
        System.out.println(nums2.length);
        System.out.println(nums2[0].length);
        System.out.println(nums2[1].length);

        //遍历二维数组
        for (int i = 0; i < nums2.length; i++) {    //第一维数组
            for (int j = 0; j < nums2[i].length; j++) {     //第二维数组
                System.out.print(nums2[i][j]+"\t");
            }
            System.out.println();
        }
        //创建不规则的二维数组
        int[][] nums3=new int[][]{{5,6,10},{3,20,22,50,80}};
        int[][] nums4=new int[2][]; //第一维长度是2, 每个元素null
        nums4[0]=new int[]{5,6,10};
        nums4[1]=new int[]{3,20,22,50,80};

    }
}

//        2
//        3
//        3
//        100 200 300
//        400 500 600
7.9.1 创建二维数组

静态初始化:

  • 语法1:数据类型[][] 数组名 = {{元素1,元素2,…},{元素1,元素2,…},…};
  • 语法2:数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2,…},{元素1,元素2,…},…};

动态初始化

  • 语法:数据类型[][] 数组名 = new 数据类型[ 二维数组的长度] [一维数组的长度];
  • 注意:二维数组的长度必须要定义,一维数组的长度可以暂时不定义
7.9.2 二维数组的使用
int[][] arr = new int[3][];  
//操作数组  存储或者获取
//注意:在使用之前必须先要对一维数组进行初始化
//arr[0][0] = 11;错误
arr[0] = new int[2];
arr[0][0] = 11;
arr[0][1] = 22;

arr[1] = new int[1];
arr[1][0] = 33;

arr[2] = new int[3];
arr[2][0] = 44;
arr[2][1] = 55;
arr[2][2] = 66;

//获取二维数组的长度
System.out.println(arr.length);
7.9.3 二维数组的遍历
//二维数组的遍历
for (int i = 0; i < arr.length; i++) {
    for (int j = 0; j < arr[i].length; j++) {
        System.out.println(arr[i][j]);
    }
}
7.9.4 二维数组的应用

用二维数组实现杨辉三角

// 使用二维数组实现杨辉三角
public class Demo {
    public static void main(String[] args) {
        rectangle();
    }
    public static void rectangle(){
        int[][] arr=new int[5][];
        for (int i = 0; i < arr.length; i++) {
            arr[i]=new int[i+1];//第二维数组初始化
            //空格 %s System.out.printf()
            //元素赋值
            for (int j = 0; j < arr[i].length; j++) {
                if(j==0||i==j){
                    arr[i][j]=1;
                }else{
                    arr[i][j]=arr[i-1][j-1]+arr[i-1][j];
                }
                System.out.print(arr[i][j]);//输出
            }
            System.out.println();
        }
    }
}
7.10 可变参数

可变参数:jdk1.5之后的新语法

语法: 数据类型… 参数名

特点:

  • 1、带有可变参数方法的调用的时候,实参个数,可以是0个或者是多个
  • 2、可变参数只能放在参数列表的最后(一个方法只能有一个可变参数)
  • 3、可变参数可以当做数组来使用,也可以将数组作为参数

场景:不确定参数个数的时候

案例:根据用户传入的数字,进行求和,数字个不确定

//案例:根据用户传入的数字,进行求和,数字个不确定
public static int sum(int... arr) {
    int sum = 0;
    for (int i = 0; i < arr.length; i++) {
        sum = sum + arr[i];
    }
    return sum;
}

可变长参数

public class newArray {
    public static void main(String[] args) {
        //传递数组元素
        printArry(100,22,33,44,55,66);
    }
    //可变长参数:可接收多个同类型实参,个数不限,使用方式与数组相同。
  //优点:比数组更加灵活
  //要求:只能方法参数列表最后,只能有一个
    public static void printArry(int x,int ...arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
    }
}
//22  33  44  55  66
7.10.1 可变参数方法的定义
public static void m1(int... a) {
    System.out.println(a[0]);
    System.out.println(a[1]);
}
7.10.2 带有可变参数方法的调用
//方式1
m1(1,2,3,4,5);
//方式2:
int[] arr = {1,2,3};
m1(arr);
7.11 值传递和应用传递

值传递和引用传递

  • 值传递:传递的是值,所以原来的值本身不会改变,所有的基本类型+String都属于值传递
  • 引用传递:传递的是地址,所以会对原来的内容有影响,所有引用数据类型都属于引用传递
public class Demo {
    public static void main(String[] args) {
        /*
        int x=10,y=20;
        swap(x,y);
        System.out.println("x:"+x+" y:"+y);
        */
        int[] nums={80,82,85,79,75};
        printArray(nums);
        System.out.println("--------------");
        for (int num : nums) {
            System.out.println(num);
        }
    }
    //基本类型作为方法的参数
    public static void swap(int a,int b){
        System.out.println("交换前 a:"+a+" b:"+b);
        a=a^b;
        b=a^b;
        a=a^b;
        System.out.println("交换后 a:"+a+" b:"+b);
    }
    //数组作为方法的参数
    public static void printArray(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            arr[i]=arr[i]+5;
            System.out.println(arr[i]);
        }
    }
}

public class newArray {
    public static void main(String[] args) {
        int [] arr= {89,85,92,85,84,88};
        arr = expand(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");  //89  85  92  85  84  88  0 0 0 0 0 0
        }
    }
    //数组类型作为方法的返回值,数组扩容
    public static int[] expand(int[] old){
        //1.创建一个长度大于原数组的新数组
        int[] newArray =new int[old.length*2];
        //2.复制原数组数据
        for (int i = 0; i < old.length; i++) {
            newArray[i]=old[i];
        }
        //3.返回新数组地址
        return newArray;
    }
}
//调用基本类型返回值的方法时,方法执行后,返回的是数据;
//
//调用引用类型返回值的方法时,方法执行后,返回的是地址
public class Demo {
  public static void main(String[] args) {
        //通过方法形式的传递
//    int a = 10;
//    System.out.println("传递之前a的值为:"+a);
//    m1(a);
//    System.out.println("传递之后a的值为:"+a);
//    
//    String s = "hello";
//    System.out.println("传递之前s的值为:"+s);
//    m2(s);
//    System.out.println("传递之后s的值为:"+s);
//    
//    double[] d = {1,2,3};
//    System.out.println("传递之前d[0]的值为:"+d[0]);
//    m3(d);
//    System.out.println("传递之后d[0]的值为:"+d[0]);
    
    
        //通过变量形式的传递
    int a = 10;
    int b = a; 
    b = 20;
    System.out.println(a);
    
    String s = "a";
    String s1 = s;
    s1 = "b";
    System.out.println(s);
    
    
    int[] arr1 = {1,2,3};
    int[] arr2 = arr1;
    arr2[0] = 100;
    System.out.println(arr1[0]);
    
    
  }
  public static void m1(int a) {
    a = 20;
  }
  public static void m2(String s) {
    s = "world";
  }
  public static void m3(double[] d) {
    d[0] = 100;
  }
}
7.12 数组的增删改查
7.12.1 增加数据

增加数据分为两种添加方式“一种叫做静态添加和一种叫做动态添加”

  • 一般静态添加使用较少,它的操作还就是在数组的时候,直接数组中存储数据
int[] arr = new int[]{1,2,3,4,5,6,7};
int[] arr2 = {1,2,3,4,5,5,6,7};


动态添加,键盘输入数据、随机数、文件读取内容之后存储、数据库操作之后存储

键盘输入和随机数据使用较多

import java.util.Scanner;

/**
 * @author yinying
 * @date 2023/1/10 12:21
 * @poject JavaDemo
 */
public class newArray {
    public static void main(String[] args) {
        //定义一个int类型数组,数组的长度为10
        int[] arr = new int[10];
        //1.随机数赋值
        for(int i = 0 ; i<arr.length;i++){
            arr[i] = (int)(Math.random()*100);
        }
        //或者
        //2.通过控制台输入
        Scanner input = new Scanner(System.in);
        for(int i = 0 ; i<arr.length;i++){
            arr[i] = input.nextInt();
        }
    }
}
7.12.2 查找和修改数据(转7.7.2)

数组中查找某个元素是否存在,一共有两种方式“线性(顺序)查找 和 二分(折半)查找”

单从效率而言“二分查找远远高于线性查找”,从书写代码而言“线性查找要远远简单于二分查找”线性(顺序)查找执行原理:就是从数组第一个元素逐一向后查找每一个元素

线性查找最优解 1次 【数组第一个元素就是要查找的元素】

线性查找最坏解 数组长度次数 【数组最后一个元素是要查找的元素】

线性查找最坏解 数组长度次数 【数组最后一个元素是要查找的元素】

线性查找最大有点就是简单易用,效率确实不高

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author yinying
 * @date 2023/1/10 17:11
 * @poject JavaDemo
 */
public class newArray {
    public static void main(String[] args) {
        //1.提供一个int类型数组,数组长度10
        int[] arr = new int[10];
        //2.通过随机数向数组中进行赋值操作
        for(int i = 0 ; i<arr.length;i++) {
            arr[i] = (int) (Math.random() * 100);
        }
        System.out.print("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]+"]");
            }
        }
        System.out.println("请输入您要在arr数组中要查找的数据:");
        Scanner input = new Scanner(System.in);
        int num = input.nextInt();
        //提供线性(顺序)查找,判断要查找数据是否存在在当前的数组中
        for(int i = 0 ;i<arr.length;i++){
            if(arr[i] == num){
            //提供修改
            // arr[i] = 10000;
            //提示找到了数据
                System.out.println("您输入数据是在数组中存储的下标为:"+i);
                return;
            }
        }
        System.out.println("没有找到数据");
    }
}
7.12.3 删除

在没有使用数组的“减容”之前,数组中是没有真正删除的

“减容”—根据删除元素个数动态缩小数组容量(大小/长度)

如何在数组中执行删除操作?

根据中存储元素类型来决定,如果数组中存储的是基本数据类型,采用后一个数据覆盖前一位数据的方式进行删除,并记录删除个数以便在打印时,可以不输出多余数据【这个操作不是”减容“,数组长度不会改变】,如果数组中存储的是引用数据类型,依旧会采用后一个数据覆盖前一个数据方式,会在最后一个数据位置添加 null值,或者直接要删除的赋值为null,并记录删除个数以便在打印中,不输出多余的数据。

package priv.yinying.javademo;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author yinying
 * @date 2023/1/10 19:33
 * @poject JavaDemo
 */
public class newArray {
    public static void main(String[] args) {
        //1.提供一个int类型数存储10个元素
        int[] arr = new int [10];
        //2.提供动态赋值同时打印数组中数据
        System.out.print("arr数组中存储的数据[");
        for(int i = 0 ; i<arr.length;i++){
            arr[i] = (int)(Math.random()*100);
            if(i != arr.length-1){
                System.out.print(arr[i]+",");
            }else{
                System.out.println(arr[i]+"]");
            }
        }
        System.out.println("删除之前arr数组的长度:"+arr.length);
        //3.提供外界输入的数据进行删除操作
        System.out.println("请输入您要删除的数据:");
        Scanner input = new Scanner(System.in);
        int num = input.nextInt();
        //提供一个变量存储删除数据的个数
        int count = 0;
        //3.1提供一个循环遍历数组寻找要删除数据
        for(int i = 0; i<arr.length;i++){
            if(arr[i] == num){
        //如果if语句成立就证明数组中是存在要删除的数据的
        //3.2在提供一个循环使用删除数据位置的后一个数据向前覆盖操作
                for(int j = i;j<arr.length-1;j++){
                    arr[j] = arr[j+1];
                }
                //循环结束之后就证明删除完成,统计计数
                count++;
            }
        }
        //真删除【减容】
        //在创建一个数组存储删除之后的数据
        /* int[] temp = new int[arr.length-count];
        for(int i = 0 ; i<arr.length-count;i++){
        temp[i] = arr[i];
        }
        //将存储着真删除数据的数据引用赋值给arr
        arr = temp;
        temp = null; //删除temp与堆中关联
        //在打印arr数组就是真删除,长度也改变了
        System.out.println("真删除之后arr数组的长度:"+arr.length);*/
        //4.提供打印操作
        System.out.print("删除数组中数之后arr数组中元素:[");
        for(int i = 0 ; i<arr.length-count;i++){
            if(i != arr.length-1-count){
                System.out.print(arr[i]+",");
            }else{
                System.out.println(arr[i]+"]");
            }
        }
        System.out.println("删除之后arr数组的长度:"+arr.length);
    }
}

(补充)调试技巧

使用IDEA的调试技巧,帮助开发人员理解程序执行过程,需要两个步骤:


添加断点

单步执行

快捷键:


F7单步进入

Step Into F8单步跳过

Step OverF9继续执行 Resume

查看变量窗口、断点窗口


插入排序和快速排序 (后续扩展补充)

目录
相关文章
|
2月前
|
Java 编译器
Java重复定义变量详解
这段对话讨论了Java中变量作用域和重复定义的问题。学生提问为何不能重复定义变量导致编译错误,老师通过多个示例解释了编译器如何区分不同作用域内的变量,包括局部变量、成员变量和静态变量,并说明了使用`this`关键字和类名来区分变量的方法。最终,学生理解了编译器在逻辑层面检查变量定义的问题。
Java重复定义变量详解
|
3月前
|
存储 缓存 算法
Java 数组
【10月更文挑战第19天】Java 数组是一种非常实用的数据结构,它为我们提供了一种简单而有效的方式来存储和管理数据。通过合理地使用数组,我们能够提高程序的运行效率和代码的可读性。更加深入地了解和掌握 Java 数组的特性和应用,为我们的编程之旅增添更多的精彩。
39 4
|
3月前
|
存储 缓存 算法
提高 Java 数组性能的方法
【10月更文挑战第19天】深入探讨了提高 Java 数组性能的多种方法。通过合理运用这些策略,我们可以在处理数组时获得更好的性能表现,提升程序的运行效率。
45 2
|
2月前
|
Java
在Java中定义一个不做事且没有参数的构造方法的作用
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
|
3月前
|
存储 Java
Java“(array) <X> Not Initialized” (数组未初始化)错误解决
在Java中,遇到“(array) &lt;X&gt; Not Initialized”(数组未初始化)错误时,表示数组变量已被声明但尚未初始化。解决方法是在使用数组之前,通过指定数组的大小和类型来初始化数组,例如:`int[] arr = new int[5];` 或 `String[] strArr = new String[10];`。
104 2
|
5月前
|
搜索推荐 算法 Java
|
5月前
|
搜索推荐 算法 Java
经典排序算法之-----选择排序(Java实现)
这篇文章通过Java代码示例详细解释了选择排序算法的实现过程,包括算法的基本思想、核心代码、辅助函数以及测试结果,展示了如何通过选择排序对数组进行升序排列。
经典排序算法之-----选择排序(Java实现)
|
7月前
|
存储 搜索推荐 算法
十大排序算法(java实现)(二)
十大排序算法(java实现)(二)
|
7月前
|
搜索推荐 算法 Java
十大排序算法(java实现)(一)
十大排序算法(java实现)(一)
|
8月前
|
搜索推荐 算法 Java
排序算法及java实现
排序算法及java实现
43 0