【Java基础整理】java数组详解

Java数组详解

1. 数组概述

数组是同一种类型数据的集合,用来存储同类型数据的容器。我们将容器中的数据称为元素。

数组的特点

  1. 数组没有API:数组不是对象,而是一堆数据的集合容器,因此没有可查阅的API文档。

  2. 唯一的length属性 :数组只有一个length属性(注意不是length()方法)。数组的长度在初始化时就固定了,无法改变。

  3. 没有内置方法 :数组本身没有任何方法,但我们可以使用Arrays工具类来操作数组。该类提供了数组相关的一系列静态方法。

2. 数组定义

定义方式一:指定长度

java 复制代码
元素类型[] 数组名 = new 元素类型[元素个数或者数组长度];

示例:

java 复制代码
int[] arr = new int[4];

定义方式二:直接初始化

java 复制代码
元素类型[] 数组名 = new 元素类型[]{元素1, 元素2, ......};

示例:

java 复制代码
int[] arr = new int[]{3, 4, 2, 8};

简化写法:

java 复制代码
int[] arr = {3, 4, 2, 8};

3. 数组常用操作

访问和修改元素

java 复制代码
数组名[角标位置]    // 获得角标位置上的元素

获取完该元素后,也可以将同类型的指定元素赋值给此元素,来改变数组内容。

获取数组长度

java 复制代码
数组名.length      // 获取数组长度

4. Arrays工具类详解

概述

Arrays类位于java.util包中,专门用于数组操作。该类只包含静态方法。

主要功能

为了扩展数组的应用,可以调用Arrays.asList()方法将数组转换成List集合,使用集合的思想和方法来操作数组元素。

常用方法

方法名 功能描述
binarySearch() 折半查找
copyOf() 复制数组
copyOfRange() 复制指定范围的数组
equals() 比较两个数组中的元素是否相同
deepEquals() 深度比较
fill() 替换值
hashCode() 获取哈希值
sort() 对数组进行升序排序
toString() 转换为字符串表示
asList(T... a) 将数组转换为List集合

**注意:**集合转数组使用toArray()方法。

Arrays.asList()使用注意事项

⚠️ 重要提醒:

  1. 不能使用增删方法 :将数组变成集合后,不能使用集合的增删方法,因为数组长度固定。如果尝试增删会抛出UnsupportedOperationException异常。

  2. 对象数组转换:如果数组中的元素都是对象,数组中的元素会直接转成集合中的元素。

  3. 基本数据类型数组转换:如果数组中的元素都是基本数据类型,那么该数组作为集合中的元素存入。

5. 数组排序算法

以下是常见的数组排序算法实现:

完整示例代码

java 复制代码
public class SortDemo {
    int array[] = {11, 22, 55, 44, 33, 4, 5, 6, 2, 43, 64, 7};
    int index = array.length;

    public static void main(String[] args) {
        SortDemo sd = new SortDemo();
        
        // 选择要使用的排序算法
        // sd.bubbleSort();     // 1、冒泡排序
        // sd.selectionSort();  // 2、选择排序
        // sd.insertionSort();  // 3、插入排序
        sd.mergeSort();         // 4、归并排序
        // sd.shellSort();      // 5、希尔排序
        // sd.quickSort();      // 6、快速排序

        // 输出结果
        for (int i = 0; i < sd.array.length; i++) {
            System.out.print(sd.array[i] + " ");
        }
    }

    // 交换两个元素位置的工具方法
    public void swap(int index1, int index2) {
        int temp = array[index1];
        array[index1] = array[index2];
        array[index2] = temp;
    }
}

1. 冒泡排序(Bubble Sort)

算法原理:

  • 逐次比较两个相邻数据的大小并交换位置
  • 每次比较都找出当前范围内的最大项
  • 时间复杂度:O(N²)
java 复制代码
public void bubbleSort() {
    int out, in;
    for (out = index - 1; out > 1; --out) {
        for (in = 0; in < out; ++in) {
            if (array[in] > array[in + 1]) {
                swap(in, in + 1);
            }
        }
    }
}

2. 选择排序(Selection Sort)

算法原理:

  • 对冒泡排序的优化版本
  • 每次遍历记录最小值位置,遍历结束后再交换
  • 减少了交换次数,只需要N次交换
  • 时间复杂度:O(N²)
java 复制代码
public void selectionSort() {
    int out, in;
    for (out = 0; out < index - 1; ++out) {
        int temp = out;
        for (in = out + 1; in < index; ++in) {
            if (array[in] < array[temp]) {
                temp = in;
            }
        }
        swap(out, temp);
    }
}

3. 插入排序(Insertion Sort)

算法原理:

  • 充分利用已排列好的数据
  • 将未排序的数据插入到已排序队列的正确位置
  • 每插入一个数据,已排序队列增加一个成员
java 复制代码
public void insertionSort() {
    int out, in;
    for (out = 1; out < index; ++out) {
        int temp = array[out];
        in = out;
        while (in > 0 && temp < array[in - 1]) {
            array[in] = array[in - 1];
            --in;
        }
        array[in] = temp;
    }
}

4. 归并排序(Merge Sort)

算法原理:

  • 将两个有序数组合并为一个有序数组
  • 结合二分法递归地将数组依次归并
  • 时间复杂度:O(N log N)
  • 空间复杂度:需要额外开辟一倍的存储空间
java 复制代码
public void mergeSort() {
    int[] newArray = new int[index];
    recMergeSort(newArray, 0, index - 1);
}

private void recMergeSort(int[] data, int low, int upper) {
    if (low == upper) {
        return;
    }
    int mid = (low + upper) / 2;
    recMergeSort(data, mid + 1, upper);
    recMergeSort(data, low, mid);
    merge(data, low, mid + 1, upper);
}

private void merge(int[] data, int lowStart, int highStart, int upperBound) {
    int j = 0;
    int lowBound = lowStart;
    int mid = highStart - 1;
    int num = upperBound - lowStart + 1;

    while (lowStart <= mid && highStart <= upperBound) {
        if (array[lowStart] < array[highStart]) {
            data[j++] = array[lowStart++];
        } else {
            data[j++] = array[highStart++];
        }
    }

    while (lowStart <= mid) {
        data[j++] = array[lowStart++];
    }

    while (highStart <= upperBound) {
        data[j++] = array[highStart++];
    }

    for (j = 0; j < num; j++) {
        array[lowBound + j] = data[j];
    }
}

5. 希尔排序(Shell Sort)

算法原理:

  • 插入排序的高级版本
  • 将每次比较的间隔扩大,让数据在大范围内移动
  • 逐渐缩小间隔,最终完成排序
  • 使用Knuth间隔序列:h = h * 3 + 1
java 复制代码
public void shellSort() {
    int in, out;
    int h = 1;
    int temp;
    
    // 计算最大间隔
    while (h < index / 3) {
        h = h * 3 + 1;
    }
    
    while (h > 0) {
        for (out = h; out < index; ++out) {
            temp = array[out];
            in = out;
            while (in > h - 1 && array[in - h] > temp) {
                array[in] = array[in - h];
                in -= h;
            }
            array[in] = temp;
        }
        h = (h - 1) / 3;
    }
}

6. 快速排序(Quick Sort)

算法原理:

  • 选择一个基准值(pivot)
  • 将小于pivot的数据放在左侧,大于pivot的放在右侧
  • 对左右两侧分别递归执行相同策略
  • 平均时间复杂度:O(N log N)
java 复制代码
public void quickSort() {
    recQuickSort(0, index - 1);
}

private void recQuickSort(int left, int right) {
    int size = right - left + 1;
    if (size <= 3) {
        manualSort(left, right);
    } else {
        int pivot = median(left, right);
        int partition = partition(left, right, pivot);
        recQuickSort(left, partition - 1);
        recQuickSort(partition + 1, right);
    }
}

private int partition(int left, int right, int pivot) {
    int leftPtr = left;
    int rightPtr = right - 1;
    
    while (true) {
        while (array[++leftPtr] < pivot);
        while (array[--rightPtr] > pivot);
        
        if (leftPtr >= rightPtr) {
            break;
        } else {
            swap(leftPtr, rightPtr);
        }
    }
    swap(leftPtr, right - 1);
    return leftPtr;
}

private int median(int left, int right) {
    int center = (left + right) / 2;
    if (array[left] > array[center]) {
        swap(left, center);
    }
    if (array[left] > array[right]) {
        swap(left, right);
    }
    if (array[center] > array[right]) {
        swap(center, right);
    }
    swap(center, right - 1);
    return array[right - 1];
}

private void manualSort(int left, int right) {
    int size = right - left + 1;
    if (size <= 1) return;
    
    if (size == 2) {
        if (array[left] > array[right])
            swap(left, right);
    } else {
        if (array[left] > array[right - 1])
            swap(left, right - 1);
        if (array[left] > array[right])
            swap(left, right);
        if (array[right - 1] > array[right])
            swap(right - 1, right);
    }
}

6. 常见异常

ArrayIndexOutOfBoundsException

角标越界异常

  • 原因: 操作数组时访问了数组中不存在的索引位置
  • 解决: 确保访问的索引在 0 到 array.length-1 的范围内

NullPointerException

空指针异常

  • 原因: 当引用没有指向任何对象(值为null)时,仍然尝试使用该引用操作实体
  • 解决: 在使用数组前先判断是否为null

总结

数组是Java中最基础的数据结构之一,掌握数组的操作和各种排序算法对提升编程能力非常重要。在实际开发中:

  1. 优先使用Arrays工具类进行数组操作
  2. 根据数据规模选择合适的排序算法
  3. 注意数组越界和空指针异常的防范
  4. 合理使用数组转集合的功能,但要注意其限制

本文整理了Java数组的核心知识点,包括基本概念、常用操作、工具类使用和各种排序算法的实现,希望对Java学习者有所帮助。

相关推荐
爆更小哇8 小时前
Selenium自动化测试函数全解析(二)
java·selenium·测试工具·自动化
C雨后彩虹8 小时前
计算误码率
java·数据结构·算法·华为·面试
fanruitian8 小时前
Springboot项目父子工程
java·数据库·spring boot
小肖爱笑不爱笑8 小时前
SpringBoot Web
java·http协议·分层解耦·web后端
柒.梧.8 小时前
Spring核心知识全解析:从入门实战到进阶
java·后端·spring
乌日尼乐8 小时前
【Java基础整理】Java字符串处理,String、StringBuffer、StringBuilder
java·后端
qwepoilkjasd8 小时前
DMC发送M-SEARCH请求,DMR响应流程
后端
全栈独立开发者8 小时前
点餐系统装上了“DeepSeek大脑”:基于 Spring AI + PgVector 的 RAG 落地指南
java·人工智能·spring
dmonstererer8 小时前
【k8s设置污点/容忍】
java·容器·kubernetes
super_lzb8 小时前
mybatis拦截器ParameterHandler详解
java·数据库·spring boot·spring·mybatis