Hutool之ArrayUtil:解锁数组操作的新境界

一、概述

1.1 工具简介

  ArrayUtil(数组工具类)是 Hutool 针对原始类型数组和泛型数组相关方法进行封装,解决对象数组(包括包装类型数组)和原始类型数组使用方法不统一的问题,提供了对数组的常用操作。它最大的价值在于消除对象数组与原始类型数组 API 不一致的痛点,用同一套方法处理任意数组,例如数组的判空、数组的合并、数组的截取等。

1.2 引入依赖

  在使用 Hutool 工具之前,需要将 Hutool 添加到项目的依赖中。如果使用 Maven 构建项目,可以在 pom.xml 文件中添加以下依赖:

xml 复制代码
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>${hutool.version}</version>
</dependency>

  Hutool-all 是一个 Hutool 的集成打包产品,由于考虑到"懒人"用户及分不清各个模块作用的用户,"无脑"引入 hutool-all 模块是快速开始和深入应用的最佳方式。如果你想像 SpringBoot 一样引入 Hutool,再由子模块决定用到哪些模块,你可以在父模块中加入:

xml 复制代码
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-bom</artifactId>
            <version>${hutool.version}</version>
            <type>pom</type>
            <!-- 注意这里是import -->
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

  然后再在子模块中就可以引入自己需要的模块了:

xml 复制代码
<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-core</artifactId>
    </dependency>
</dependencies>

二、基础操作:判空与创建

原生数组的判空和泛型创建比较麻烦,ArrayUtil 提供了标准的解决方法。

2.1 判空与校验

数组的"空"有两种不同层次的含义,ArrayUtil 提供了对应的判断方法:

graph LR A[&#34;数组判空&#34;] A-->A1[&#34;null 判断:数组本身为 null 或元素含 null&#34;] A-->A2[&#34;empty 判断:数组为 null 或长度为 0&#34;]

null 相关判断

方法 说明
hasNull(array) 判断数组中是否包含 null 元素,数组本身为 null 时也返回 true
isAllNull(array) 判断数组中所有元素是否全部为 null
isAllNotNull(array) 判断数组中所有元素是否全部不为 null
firstNonNull(array) 查找并返回数组中第一个非 null 元素
java 复制代码
String[] a = {"a", null, "b"};
System.out.println("判断数组中是否包含 null 元素:" + ArrayUtil.hasNull(a));

String[] b = {null, null, null};
System.out.println("判断数组是否所有元素都为 null:" + ArrayUtil.isAllNull(b));

String[] c = {"a", "b", "c"};
System.out.println("判断数组是否所有元素都不为 null:" + ArrayUtil.isAllNotNull(c));

String[] d = {null, null, "first", null, "second"};
System.out.println("获取数组中第一个非 null 元素:" + ArrayUtil.firstNonNull(d));

empty 判断

ArrayUtil 判断规则:null 或者数组长度为 0 → 为空,它同时支持原始类型(如 int\[\])和泛型数组,避免了手动写 array == null || array.length == 0

方法 说明
isEmpty(array) 判断数组是否为空(null 或长度为 0)
isNotEmpty(array) 判断数组是否非空,与 isEmpty 互为反操作
hasEmpty(array) 判断数组中是否包含空元素,覆盖 null、空集合、空 Map、空数组等
isAllEmpty(array) 是否全都为 null 或空对象
isAllNotEmpty(array) 是否全都不为 null 或空对象
defaultIfEmpty(array, defaultArray) 如果给定数组为空,返回默认数组
emptyCount(array) 计算数组中空元素的个数
java 复制代码
int[] a = {};
System.out.println("判断数组是否为空(null 或长度为 0):" + ArrayUtil.isEmpty(a));
int[] b = null;
System.out.println("判断数组是否为空(null 或长度为 0):" + ArrayUtil.isEmpty(b));
String[] c = {"a", "b"};
System.out.println("判断数组是否为空(null 或长度为 0):" + ArrayUtil.isEmpty(c));

int[] d = {1, 2, 3};
System.out.println("判断数组是否不为空(不为 null 且长度大于 0):" + ArrayUtil.isNotEmpty(d));

String[] e = {"", "a", "b"};
System.out.println("判断数组是否包含空值:" + ArrayUtil.hasEmpty(e));
Object[] f = {"a", new ArrayList<>()};
System.out.println("判断数组是否包含空值:" + ArrayUtil.hasEmpty(f));

System.out.println("是否存都为null或空对象:" + ArrayUtil.isAllEmpty(e));
System.out.println("是否存都为null或空对象:" + ArrayUtil.isAllNotEmpty(e));

String[] result = ArrayUtil.defaultIfEmpty(new String[0], new String[]{"default"});
System.out.println("给定数组为空,返回默认数组" + ArrayUtil.toString(result));

Object[] arr = {"a", new ArrayList<>(), new HashMap<>(), new int[0]};
System.out.println("统计数组中空值的数量:" + ArrayUtil.emptyCount(arr));

2.2 数组创建与初始化

方法 说明
newArray(componentType, length) 创建指定类型和长度的泛型数组,封装了 JDK 的 Array.newInstance 方法
range(start, end, step) 生成有序整数数组,支持步进参数
getArrayType(array) 根据数组元素类型,获取数组的类型
getComponentType(componentType) 获取数组对象的元素类型
cast(type,arrayObj) 强转数组类型,前提是元素类型可被强制转换,会生成新数组
java 复制代码
String[] arr = ArrayUtil.newArray(String.class, 3);
System.out.println("创建 String 数组:" + Arrays.toString(arr));
Object[] arr2 = ArrayUtil.newArray(5);
System.out.println("创建 Object 数组:" + Arrays.toString(arr2));

int[] a = ArrayUtil.range(5);
System.out.println("创建 int 数组:" + Arrays.toString(a));
int[] b = ArrayUtil.range(2, 7);
System.out.println("创建 int 数组:" + Arrays.toString(b));
int[] c = ArrayUtil.range(0, 10, 2);
System.out.println("创建 int 数组:" + Arrays.toString(c));

三、元素基本操作

3.1 获取元素

方法 说明
get(array, index) 获取指定位置的元素,支持负数索引(-1 表示最后一个元素)。 如果数组下标越界,返回null
getAny(array, indexes) 获取数组中指定多个下标的元素,组成新数组返回
java 复制代码
String[] arr = {"a", "b", "c", "d"};

Object first = ArrayUtil.get(arr, 0);
System.out.println("获取第一个元素:" + first);

Object last = ArrayUtil.get(arr, -1);
System.out.println("获取最后一个元素:" + last);

Object secondLast = ArrayUtil.get(arr, -2);
System.out.println("获取倒数第二个元素:" + secondLast);

String[] result01 = ArrayUtil.getAny(arr, 10);
System.out.println("获取第10个元素:" + ArrayUtil.toString(result01));

String[] result02 = ArrayUtil.getAny(arr, 0, 2, 4);
System.out.println("获取第0个、第2个、第4个元素:" + ArrayUtil.toString(result02));

3.2 追加元素

方法 说明
append(array, elements) 将新元素追加到已有数组末尾,生成新数组,不影响原数组
java 复制代码
String[] a = {"1", "2", "3"};
String[] result = ArrayUtil.append(a, "4", "5");
System.out.println(ArrayUtil.toString(result));

3.3 设置与替换

方法 说明
setOrAppend(array, index, value) 设置指定位置的元素值。如果 index 大于等于数组长度,则追加元素
setOrPadding(array, index, value) 强制设置指定位置的元素值,超出部分用默认值填充
replace(array, index, values) 从指定位置开始,用新元素替换旧元素。 index < 0 时在头部插入,index>= 长度时在尾部追加。 index + 新元素数 > 长度时生成新数组,否则在原数组中替换并返回
java 复制代码
int[] arr = {1, 2, 3};
int[] result = ArrayUtil.setOrAppend(arr, 1, 99);
int[] result2 = ArrayUtil.setOrAppend(arr, 5, 99);

String[] arr = new String[0];
String[] result = ArrayUtil.setOrPadding(arr, 2, "Good");
String[] result2 = ArrayUtil.setOrPadding(arr, 2, "Good", "pad");

String[] a = {"1", "2", "3", "4"};
String[] b = {"a", "b", "c"};

ArrayUtil.replace(a, 0, b);  // ["a", "b", "c", "4"]
ArrayUtil.replace(a, 1, b);  // ["1", "a", "b", "c"]
ArrayUtil.replace(a, 2, b);  // ["1", "2", "a", "b", "c"]
ArrayUtil.replace(a, 4, b);  // ["1", "2", "3", "4", "a", "b", "c"]
ArrayUtil.replace(a, -1, b); // ["a", "b", "c", "1", "2", "3", "4"]

3.4 插入元素

方法 说明
insert(array, index, values) 在指定位置插入元素,返回新数组,不影响原数组。 index 为负数则从后向前计数,大于数组长度则空白处用 null 填充
java 复制代码
String[] a = {"1", "2", "3", "4"};
String[] b = {"x", "y"};
System.out.println("原数组:" + ArrayUtil.toString(a));
System.out.println("从头部插入结果:" + ArrayUtil.toString(ArrayUtil.insert(a, 2, b)));
System.out.println("从尾部插入结果:" + ArrayUtil.toString(ArrayUtil.insert(a, -3, b)));
System.out.println("指定位置插入结果:" + ArrayUtil.toString(ArrayUtil.insert(a, 9, "9")));

3.5 移除元素

方法 说明
remove(array, index) 移除数组中指定位置的元素,生成新数组,原数组不变
removeEle(array, element) 移除数组中指定的元素,生成新数组。如有多个匹配,只移除第一个
removeBlank(T\[\] array) 批量移除数组中的 null 或者 "" 或者空白字符串元素,生成新数组
removeEmpty(T\[\] array) 批量移除数组中的 null或者 "" 元素,生成新数组
removeNull(T\[\] array) 批量移除数组中的 null 元素,生成新数组
java 复制代码
String[] arr01 = {"a", "b", "c", "d"};
String[] result01 = ArrayUtil.remove(arr01, 1);

Integer[] arr02 = {1, 2, 3, 2, 4};
Integer[] result02 = ArrayUtil.removeEle(arr02, 2);

3.6 调整大小

方法 说明
resize(array, newSize) 重新调整数组大小,生成新数组 。 新数组大小小于原数组时截断,大于时用默认值 0 填充。
java 复制代码
String[] stringArr = ArrayUtil.newArray(String.class, 3);
String[] bigger = ArrayUtil.resize(stringArr, 5);
System.out.println("原数组长度:" + stringArr.length + ",新数组长度:" + bigger.length);

3.7 替换元素

方法 说明
replace(array, index, newElements) 从指定位置开始,用新元素替换旧元素。 位置为负数时在头部插入,超出长度时在尾部追加
nullToEmpty 将数组元素中的 null 转换为空字符串 ""
java 复制代码
String[] a = {"1", "2", "3", "4"};
String[] b = {"x", "y", "z"};

// 从位置 1 开始替换
String[] result = ArrayUtil.replace(a, 1, b);
// ["1", "x", "y", "z"]

// 位置为负,相当于头部插入
String[] result2 = ArrayUtil.replace(a, -1, b);
// ["x", "y", "z", "1", "2", "3", "4"]

四、查找与判断

4.1 查找与索引

方法 说明
indexOf(array, value) 查找指定元素在数组中第一次出现的位置,未找到返回 -1
indexOf(array, value, beginIndexInclude) 指定元素在数组中 beginIndexInclude 以后第一次出现的位置
lastIndexOf(array, value) 查找指定元素在数组中最后一次出现的位置,未找到返回 -1
matchIndex(predicate, array) 查找满足条件的第一个元素的索引位置,未找到返回 null
firstMatch(predicate, array) 查找满足条件的第一个元素并返回,未找到返回 null
indexOfIgnoreCase 返回数组中指定元素所在位置,忽略大小写
java 复制代码
Integer[] arr = {1, 2, 3, 4, 3, 6};

int index01 = ArrayUtil.indexOf(arr, 3);
System.out.println("查找指定元素在数组中第一次出现的位置:" + index01);

int index02 = ArrayUtil.lastIndexOf(arr, 3);
System.out.println("查找指定元素在数组中最后一次出现的位置:" + index02);

int index03 = ArrayUtil.matchIndex(v -> v > 3, arr);
System.out.println("查找第一个符合条件的元素的索引:" + index03);

Integer result = ArrayUtil.firstMatch(v -> v > 15, arr);
System.out.println("查找第一个符合条件的元素:" + result);

4.2 包含与判断

方法 说明
contains(array, value) 通过 equals 方法判断数组中是否包含指定元素
containsAny(array, values) 通过 equals 方法判断数组中是否包含指定元素中的任意一个
containsAll(array, values) 通过 equals 方法判断数组中是否包含所有指定元素
containsIgnoreCase(array, value) 判断字符串数组中是否包含指定元素,忽略大小写
equals(array1, array2) 判断两个数组是否相等,判断依据包括数组长度和每个元素都相等。 自动识别类型,无需强制转换
isArray(obj) 判断对象是否为数组对象
java 复制代码
Integer[] arr = {1, 2, 3, 4, 5};

boolean result = ArrayUtil.contains(arr, 3);
System.out.println("数组中是否包含指定元素:" + result);

boolean containsAnyResult = ArrayUtil.containsAny(arr, 4, 10, 40);
System.out.println("数组中是否包含指定元素中的任意一个:" + containsAnyResult);

boolean containsAllResult = ArrayUtil.containsAll(arr, 2, 4, 5);
System.out.println("数组中是否包含指定元素中的所有:" + containsAllResult);

String[] keys = {"a", "B", "c"};
boolean containsIgnoreCaseResult = ArrayUtil.containsIgnoreCase(keys, "b");
System.out.println("数组中是否包含指定元素b(忽略大小写):" + containsIgnoreCaseResult);

boolean equalsResult = ArrayUtil.equals(new int[]{1, 2, 3}, new int[]{1, 2, 3});
System.out.println("数组是否相等:" + equalsResult);

boolean isArrayResult = ArrayUtil.isArray(new int[]{1, 2, 3}); // true
System.out.println("是否为数组:" + isArrayResult);

boolean isArrayResult2 = ArrayUtil.isArray("hello"); // false
System.out.println("是否为数组:" + isArrayResult2);

五、过滤、编辑与转换

5.1 过滤与编辑

方法 说明
edit(array, editor) 对数组元素进行编辑,返回新数组。 通过 Editor 函数处理每个元素,返回 null 则过滤掉该元素
filter(array, filter) 使用 Filter 接口过滤数组元素,返回 true 表示保留
java 复制代码
Integer[] arr = {1, 2, 3, 4, 5, 6};
// 偶数乘以 10,奇数不变
Integer[] result = ArrayUtil.edit(arr, t -> (t % 2 == 0) ? t * 10 : t);
// 只保留偶数
Integer[] even = ArrayUtil.edit(arr, t -> (t % 2 == 0) ? t : null);

// 只保留偶数
Integer[] even = ArrayUtil.filter(arr, t -> t % 2 == 0);

Editor 是 Hutool 提供的函数式接口,接收一个参数并返回修改后的值,返回 null 表示过滤掉该元素,在 Java 8+ 中可以直接使用 Lambda 表达式。

5.2 类型转换

拆装箱

方法 说明
wrap(primitiveArray) 将原始类型数组转换为包装类型数组,如 int\[\] → Integer\[\]
unWrap(wrapperArray) 将包装类型数组转换为原始类型数组,如 Integer\[\] → int\[\]
java 复制代码
int[] primitive = {1, 2, 3, 4};
Integer[] wrapped = ArrayUtil.wrap(primitive);

Integer[] wrapped = {1, 2, 3, 4};
int[] primitive = ArrayUtil.unWrap(wrapped);

map 转换

方法 说明
map(array, targetType, mapper) 将数组元素转换为其他类型,支持自定义转换规则。 参数为 Object,支持原始类型数组
mapToArray(array, mapper, generator) 按照指定规则,将泛型数组的元素转换为另一种类型的数组
mapToList(array, mapper) 按照指定规则,将数组元素转换后收集为 List
mapToSet(array, mapper) 按照指定规则,将数组元素转换后收集为 Set(自动去重)
java 复制代码
int[] arr = {1, 2, 3};
Integer[] result = ArrayUtil.map(arr, Integer.class, t -> (int) t * 2);
System.out.println(ArrayUtil.toString(result));

String[] keys = {"a", "bb", "ccc"};
Integer[] lengths = ArrayUtil.mapToArray(keys, String::length, Integer[]::new);

String[] keys = {"a", "bb", "ccc"};
List<Integer> lengths = ArrayUtil.mapToList(keys, String::length);

String[] keys = {"a", "bb", "c"};
Set<Integer> lengths = ArrayUtil.mapToSet(keys, String::length);

集合转数组

方法 说明
toArray(collection, componentType) 集合转数组。 注意:返回的 List 是固定大小数组列表,不能添加、移除元素。
java 复制代码
List<String> list = List.of("a", "b");
String[] arr = ArrayUtil.toArray(list, String.class);
System.out.println("集合转数组:" + ArrayUtil.toString(arr));

5.3 字符串与输出

方法 说明
toString(array) 将数组转换为字符串。 自动识别原始类型和对象类型,避免打印出哈希码
join(array, conjunction) 使用指定分隔符将数组元素拼接为字符串
join(array, conjunction, prefix, suffix) 使用分隔符、前缀、后缀将数组元素拼接为字符串
join(array, conjunction, editor) 先对每个元素进行转换,再用分隔符拼接
java 复制代码
int[] intArr = {1, 3, 56, 6, 7};
String[] strArr = {"aa", "bb", "cc"};

String str = ArrayUtil.toString(intArr);
System.out.println("将数组转换为字符串: " + str);

String result01 = ArrayUtil.join(intArr, ",");
System.out.println("使用指定分隔符将数组元素拼接为字符串: " + result01);

String result02 = ArrayUtil.join(strArr, ",", "[", "]");
System.out.println("使用分隔符、前缀、后缀将数组元素拼接为字符串: " + result02);

String result03 = ArrayUtil.join(strArr, " -> ", String::toUpperCase);
System.out.println("先对每个元素进行转换,再用分隔符拼接: " + result03);

六、其他常用方法

6.1 数组去重

方法 说明
distinct(array) 通过 equals 方法判断去重,生成新的数组,原数组不变
distinct(array, keyGenerator, override) 通过自定义 key 生成器去重。 override 为 true 时保留后面的值,为 false 时保留前面的值
java 复制代码
String[] arr01 = {"aa", "bb", "cc", "dd", "bb", "dd"};
String[] result01 = ArrayUtil.distinct(arr01);
System.out.println("数组去重结果:" + ArrayUtil.toString(result01));

String[] arr02 = {"aa", "Aa", "BB", "bb"};
System.out.println("原数组:" + ArrayUtil.toString(arr02));
String[] r01 = ArrayUtil.distinct(arr02, String::toLowerCase, true);
System.out.println("忽略大小写去重,保留后面的值(覆盖模式):" + ArrayUtil.toString(r01));
String[] r02 = ArrayUtil.distinct(arr02, String::toLowerCase, false);
System.out.println("忽略大小写去重,保留前面的值(忽略模式):" + ArrayUtil.toString(r02));

6.2 合并与拆分

方法 说明
addAll(arrays) 将多个数组合并为一个数组,返回新数组,原数组不变
split(array, len) 将 byte 数组按指定长度平均拆分成多个子数组,常用于消息拆分
zip(keys, values, isOrder) 将两个数组(keys 和 values)按位置对应合并为 Map
java 复制代码
String[] a = {"1", "2"};
String[] b = {"3", "4"};
String[] c = {"5", "6"};
String[] result = ArrayUtil.addAll(a, b, c);
System.out.println(ArrayUtil.toString(result));

byte[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
byte[][] result = ArrayUtil.split(arr, 3);

String[] keys = {"a", "b", "c"};
Integer[] values = {1, 2, 3};
Map<String, Integer> map = ArrayUtil.zip(keys, values, true);

6.3 克隆与复制

方法 说明
clone(array) 克隆数组,支持原始类型数组和对象数组。返回新数组,与原数组互不影响
copy(src, dest) 将源数组的元素复制到目标数组
copy(src, dest, length) 指定拷贝元素的个数
java 复制代码
int[] a = {1, 2, 3};
int[] cloneA = ArrayUtil.clone(a);
Integer[] b = {1, 2, 3};
Integer[] cloneB = ArrayUtil.clone(b);

String[] src = {"a", "b", "c"};
String[] dest = new String[3];
ArrayUtil.copy(src, dest);

String[] src = {"a", "b", "c"};
String[] dest = new String[3];
ArrayUtil.copy(src, dest, 1);

6.4 最大值与最小值

方法 说明
max(array / values) 查找数组中的最大值。支持基本类型、对象数组,支持自定义比较器
min(array / values) 查找数组中的最小值。支持基本类型、对象数组,支持自定义比较器
java 复制代码
System.out.println("查找数组中的最大值:" + ArrayUtil.max(1, 2, 13, 4, 5));
System.out.println("查找数组中的最小值:" + ArrayUtil.min(1, 2, 13, 4, 5));

Integer[] arr = {5, 2, 8, 1, 9};
System.out.println("查找数组中的最大值:" + ArrayUtil.max(arr));
System.out.println("查找数组中的最小值:" + ArrayUtil.min(arr));

BigDecimal[] nums = {new BigDecimal("2.0"), new BigDecimal("1.00"), new BigDecimal("3")};
BigDecimal minScale = ArrayUtil.min(nums, Comparator.comparingInt(BigDecimal::scale));
System.out.println("自定义比较器查找数组中的最小值:" + minScale);
BigDecimal maxScale = ArrayUtil.max(nums, Comparator.comparingInt(BigDecimal::scale));
System.out.println("自定义比较器查找数组中的最大值:" + maxScale);

6.5 数组排序

方法 说明
isSorted 检查数组是否有序
isSortedASC 检查数组是否升序
isSortedDESC 检查数组是否降序

6.6 数组反转

方法 说明
reverse(array) 反转数组,会变更原数组
shuffle(array) 打乱数组顺序,会变更原数组
swap(array, index1, index2) 交换数组中两个位置的值
java 复制代码
int[] a = {1, 2, 3};
System.out.println("反转前的原数组:" + Arrays.toString(a));
ArrayUtil.reverse(a);
System.out.println("反转后的数组:" + Arrays.toString(a));

int[] b = {1, 2, 3};
System.out.println("打乱前的原数组:" + Arrays.toString(b));
ArrayUtil.shuffle(b);
System.out.println("打乱后的数组:" + Arrays.toString(b));

int[] c = {1, 2, 3};
System.out.println("交换前的原数组:" + Arrays.toString(c));
ArrayUtil.swap(c, 0, 2);
System.out.println("交换后的数组:" + Arrays.toString(c));

6.7 子数组

方法 说明
indexOfSub(array,subArray) 查找子数组在主数组中的位置
indexOfSub(array, beginInclude,subArray)
isSub(array, subArray) 判断是否为子数组
lastIndexOfSub 查找子数组在主数组中的最后位置
sub(array, start, end) 获取子数组,左闭右开,支持负数倒数
java 复制代码
Integer[] a = {0, 1, 2, 3, 4};
Integer[] subResult = ArrayUtil.sub(a, 1, 3);
System.out.println("获取子数组,左闭右开:" + Arrays.toString(subResult));

七、总结

  Hutool 不仅仅只有这一种工具类,还包含了其他许多工具类。在这里我作为一名Hutool的用户,我感谢Hutool的创作者和维护者们为我们带来如此强大便捷的工具库,希望Hutool功能越来越完善,为我们的开发工作带来更多的便利。同时也祝愿所有开发者没有BUG困扰,能够愉快地编写出高效、功能完善的程序。

相关推荐
杨运交1 小时前
[074][示例]基于Redisson的分布式锁在定时任务中的实践与异常模拟
java·后端·spring
步行cgn1 小时前
Spring 中完整的 Scope 选项详解
java·后端·spring
LEE2 小时前
前端转型全栈 03:接口失败也返回 200,OpenAPI 契约与错误码怎么定
前端·后端·全栈
打工仔折腾 AI2 小时前
用 Docker 部署 Excalidraw 手绘白板并配置固定公网访问的完整实践
人工智能·后端·python
山岚的运维笔记2 小时前
mysql 专业笔记 -- 第 36 章:MySQL 管理
运维·数据库·笔记·后端·mysql·oracle·dba
掘金者阿豪2 小时前
Oracle 迁移金仓,50 个存储过程到底要改多少?聊聊实际改造中的几个问题
后端
大白803 小时前
iOS 内存深度解析:ARC 到底是怎么管理对象生命周期的
后端
焦玉全3 小时前
Redis Lua 脚本实战:从入门到精通(Java 版)
后端
知识的搬运工旺仔3 小时前
唯一索引与 NULL 值:PostgreSQL 主键约束与 NULLS NOT DISTINCT
数据库·后端·sql·postgresql