Guava——基本类型工具类(一)

1、Bytes

Guava 中的 Bytes(属于 com.google.common.primitives 包)是针对原生 byte 类型以及 byte[] 数组操作的静态工具类。

由于 Java 标准库中的 java.util.Arrays 对原生数组的支持较为基础,Bytes 补充了大量的查找、拼接、转换与判定功能。

1.1、核心API

Bytes 的所有 API 均为静态方法,主要分为以下五大类:

分类核心 API 方法说明
查找与判定contains, indexOf, lastIndexOf查找单个字节或子数组(byte[])的位置
数组拼接concat将多个 byte[] 数组合并为一个新数组
大小与扩容ensureCapacity确保数组具备最小长度,不足时自动扩容填充 0
类型与集合转换asList, toArray原生 byte[] 与包装对象列表 List<Byte> 的双向转换
比较lexicographicalComparator获取字节数组的字典序比较器(Lexicographical Comparator)

1.2、使用示例

1.2.1、元素与子数组查找

除了查找单个 byte,Bytes 极具特色的一点是直接支持查找连续的子字节数组(Target Subarray)。

import com.google.common.primitives.Bytes;

public class BytesSearchDemo {
    public static void main(String[] args) {
        byte[] array = {0x01, 0x02, 0x03, 0x04, 0x02, 0x03};

        // 1. 查找单个 byte
        boolean hasThree = Bytes.contains(array, (byte) 0x03); // true
        int firstIdx = Bytes.indexOf(array, (byte) 0x02);      // 1
        int lastIdx = Bytes.lastIndexOf(array, (byte) 0x02);  // 4

        // 2. 查找子数组 (Target Subarray) 在原数组中的匹配起始位置
        byte[] target = {0x02, 0x03};
        int targetIdx = Bytes.indexOf(array, target);          // 1

        System.out.println("包含 0x03: " + hasThree);
        System.out.println("子数组 {0x02, 0x03} 匹配索引: " + targetIdx);
    }
}
包含 0x03: true
子数组 {0x02, 0x03} 匹配索引: 1
1.2.2、数组合并

将多个独立的 byte[] 组合成一个新的单一 byte[],避免手动创建新数组和多次调用 System.arraycopy。

import com.google.common.primitives.Bytes;

public class BytesConcatDemo {
    public static void main(String[] args) {
        byte[] header = {0x10, 0x20};
        byte[] body   = {0x30, 0x40, 0x50};
        byte[] footer = {0x60};

        // 拼接任意数量的 byte[]
        byte[] packet = Bytes.concat(header, body, footer);
        
        // 输出长度为 6 的数组: [16, 32, 48, 64, 80, 96]
        System.out.println("合并后长度: " + packet.length);
    }
}
合并后长度: 6
1.2.3、数组动态扩容

类似 ArrayList 的扩容机制,保证 byte[] 满足最小长度条件。如果原始数组长度不足,会重新分配并补零填充。

import com.google.common.primitives.Bytes;

public class BytesCapacityDemo {
    public static void main(String[] args) {
        byte[] buffer = {0x01, 0x02};

        // ensureCapacity(array, minLength, padding)
        // 如果 buffer.length < 5,则返回长度为 5 + 2 = 7 的新数组,原元素会被复制过去
        byte[] expanded = Bytes.ensureCapacity(buffer, 5, 2);

        System.out.println("扩容后新数组长度: " + expanded.length); // 7
    }
}
扩容后新数组长度: 7
1.2.4、原生数组与集合的双向转换
  • asList(byte… backingArray):返回一个由原数组作为底层支撑(Backing Array)的 List 视图。
  • toArray(Collection<? extends Number> collection):将包装类集合安全转换为原生 byte[]。

注意:Bytes.asList() 返回的 List 是固定大小的(写操作如 set() 会直接改变原数组,但无法 add() 或 remove())。

import com.google.common.primitives.Bytes;
import java.util.Arrays;
import java.util.List;

public class BytesConvertDemo {
    public static void main(String[] args) {
        // 1. byte[] 转 List<Byte>
        byte[] origin = {1, 2, 3};
        List<Byte> byteList = Bytes.asList(origin);

        // 修改 List 中的值会直接联动影响原始 byte[] 数组
        byteList.set(0, (byte) 99);
        System.out.println("原数组第 0 位被修改为: " + origin[0]); // 99

        // 2. 集合转 byte[]
        List<Integer> numberList = Arrays.asList(10, 20, 30);
        byte[] byteArray = Bytes.toArray(numberList); // 自动进行 Number.byteValue() 转换
        System.out.println("转换后的 byte[] 长度: " + byteArray.length); // 3
    }
}
原数组第 0 位被修改为: 99
转换后的 byte[] 长度: 3
1.2.5、字典序比较

用于对比两个 byte[] 在字典序上的大小关系(逐个字节按无符号/有符号对比),常用于存储引擎或网络协议的 Key 比较。

import com.google.common.primitives.Bytes;
import java.util.Comparator;

public class BytesCompareDemo {
    public static void main(String[] args) {
        byte[] a = {1, 2, 3};
        byte[] b = {1, 2, 4};

        Comparator<byte[]> comparator = Bytes.lexicographicalComparator();
        int result = comparator.compare(a, b);

        if (result < 0) {
            System.out.println("数组 a 字典序小于 数组 b");
        }
    }
}

2、Shorts

Guava 中的 Shorts(属于 com.google.common.primitives 包)是专门针对原生 short 类型以及 short[] 数组操作的静态工具类。

它补足了 JDK 对 short 类型支持较弱的短板,提供了高频使用的查找、转换、比较、位操作与数组处理功能。

2.1、核心API

分类核心 API说明
数值安全与界限saturatingCast, checkedCastlong 类型安全地强转为 short
数值比较与限制min, max, constrainToRange, compare最值求解、区间截断限制、数值比较
数组查找与判定contains, indexOf, lastIndexOf查找单个 short 或子数组(short[])的匹配索引
数组操作与拼接concat, ensureCapacity, reverse数组合并、自动扩容、原位反转
字节/二进制序列化toByteArray, fromByteArray, fromBytesshortbyte[](大端序/Big-Endian)互转
集合与字符串转换asList, toArray, join, stringConverter原生数组与 List<Short> 互转,字符串拼接与解析转换

2.2、使用示例

2.2.1、类型转换与安全强转

将范围较大的整数类型(如 long 或 int)转为 short 时,标准 Java 的直接强转会导致高位截断溢出。Shorts 提供了两种安全策略:

import com.google.common.primitives.Shorts;

public class ShortsCastDemo {
    public static void main(String[] args) {
        long normalValue = 1000L;
        long overflowValue = 50000L; // 超过 short 最大值 (32767)

        // 1. checkedCast:溢出时直接抛出 IllegalArgumentException 异常
        short safeValue = Shorts.checkedCast(normalValue); 
        System.out.println("checkedCast: " + safeValue); // 1000

        // 2. saturatingCast:饱和转换(溢出时自动截断为 Short.MAX_VALUE 或 Short.MIN_VALUE)
        short clampedValue = Shorts.saturatingCast(overflowValue);
        System.out.println("saturatingCast 溢出截断: " + clampedValue); // 32767
    }
}
2.2.2、最值、范围约束与比较
import com.google.common.primitives.Shorts;

public class ShortsMathDemo {
    public static void main(String[] args) {
        short a = 10, b = 50, c = 30;

        // 1. 获取最值(支持变长参数)
        System.out.println("最大值: " + Shorts.max(a, b, c)); // 50
        System.out.println("最小值: " + Shorts.min(a, b, c)); // 10

        // 2. 区间截断限制 (constrainToRange)
        // 将输入值限制在 [min, max] 区间内:小于 min 返回 min,大于 max 返回 max
        short val1 = Shorts.constrainToRange((short) 5, (short) 10, (short) 20);  // 返回 10
        short val2 = Shorts.constrainToRange((short) 15, (short) 10, (short) 20); // 返回 15
        short val3 = Shorts.constrainToRange((short) 25, (short) 10, (short) 20); // 返回 20
        System.out.println("范围限制结果: " + val1 + ", " + val2 + ", " + val3);

        // 3. 数值比较
        int cmp = Shorts.compare(a, b); // 返回负数,表明 a < b
    }
}
最大值: 50
最小值: 10
范围限制结果: 10, 15, 20
2.2.3、字节序列化转换

在网络协议编解码或二进制处理中,经常需要将 short(2 字节)与 byte[] 互相转换。Shorts 默认采用 大端序(Big-Endian / Network Byte Order)。

import com.google.common.primitives.Shorts;

public class ShortsByteDemo {
    public static void main(String[] args) {
        short value = 0x1234; // 对应十进制 4660

        // 1. short -> byte[] (2 字节)
        byte[] bytes = Shorts.toByteArray(value);
        // bytes[0] = 0x12, bytes[1] = 0x34

        // 2. byte[] -> short
        short restoredValue = Shorts.fromByteArray(bytes);
        System.out.println("还原后的 short: " + restoredValue); // 4660

        // 3. 从任意字节数组指定位置读取 2 字节并转换为 short
        byte[] buffer = {0x00, 0x10, 0x20, 0x00};
        short extracted = Shorts.fromBytes(buffer[1], buffer[2]); // 读取 0x10 和 0x20
        System.out.println("提取的 short: " + extracted); // 4128
    }
}
还原后的 short: 4660
提取的 short: 4128
2.2.4、数组查找、反转与拼接
import com.google.common.primitives.Shorts;

public class ShortsArrayDemo {
    public static void main(String[] args) {
        short[] array = {1, 2, 3, 4, 2, 3};

        // 1. 查找子数组匹配索引
        short[] target = {2, 3};
        int index = Shorts.indexOf(array, target);
        System.out.println("子数组首次匹配索引: " + index); // 1

        // 2. 原位数组反转 (Reverse)
        Shorts.reverse(array);
        // array 变为 [3, 2, 4, 3, 2, 1]

        // 3. 数组合并 (Concat)
        short[] extra = {9, 10};
        short[] combined = Shorts.concat(array, extra);
        System.out.println("合并后数组长度: " + combined.length); // 8
    }
}
子数组首次匹配索引: 1
合并后数组长度: 8
2.2.5、集合适配与字符串处理
import com.google.common.primitives.Shorts;

import java.util.List;

public class ShortsConvertDemo {
    public static void main(String[] args) {
        short[] numbers = {10, 20, 30};

        // 1. short[] 转 List<Short> 视图(改动 List 会联动改动原数组)
        List<Short> shortList = Shorts.asList(numbers);
        shortList.set(0, (short) 99);
        System.out.println("原数组第 0 位被更新: " + numbers[0]); // 99

        // 2. 数组快速连接为分隔符字符串
        String joined = Shorts.join(", ", numbers);
        System.out.println("连接字符串: " + joined); // "99, 20, 30"

        // 3. StringConverter 转换器(双向转换)
        com.google.common.base.Converter<String, Short> converter = Shorts.stringConverter();
        short parsed = converter.convert("123");
        String strValue = converter.reverse().convert((short) 456);
        System.out.println("解析与反转: " + parsed + " / " + strValue);
    }
}
原数组第 0 位被更新: 99
连接字符串: 99, 20, 30
解析与反转: 123 / 456

3、Ints

Guava 中的 Ints(属于 com.google.common.primitives 包)是针对原生 int 类型及 int[] 数组操作的静态工具类。

它补足了 JDK 标准库在处理原生整型数组时的不足,提供了极为丰富的安全强转、范围约束、字节序列化、数组高阶操作与集合适配功能。

3.1、核心API

分类核心 API 方法说明
安全强转与界限checkedCast, saturatingCastlong 安全转换为 int(提供溢出检查或饱和截断)
数值计算与范围min, max, constrainToRange, compare求最值、区间范围限制截断、数值比较
字节/二进制序列化toByteArray, fromByteArray, fromBytesintbyte[](大端序/Big-Endian)双向转换
数组查找与查找子数组contains, indexOf, lastIndexOf查找单个 int 或匹配整个 int[] 子数组
数组修改与拼接concat, ensureCapacity, reverse, sortDescending合并、扩容、原位反转、降序排序
集合与类型转换asList, toArray, join, stringConverter原生数组与 List<Integer> 适配、字符串拼接/双向解析

3.2、使用示例

3.2.1、安全类型转换

在 Java 中,直接将 long 强转为 int(如 (int) longVal)会导致高位直接截断,产生意料之外的负数或错误数值。Ints 提供了两种安全的处理策略:

import com.google.common.primitives.Ints;

public class IntsCastDemo {
    public static void main(String[] args) {
        long normalValue = 1000L;
        long overflowValue = 3_000_000_000L; // 超过 Integer.MAX_VALUE (约 21.47 亿)

        // 1. checkedCast:数值安全时正常返回,超出 int 范围则直接抛出 IllegalArgumentException
        int value1 = Ints.checkedCast(normalValue); 
        System.out.println("checkedCast: " + value1); // 1000

        // 2. saturatingCast:饱和转换(溢出时不会报错,而是自动截断为 Integer.MAX_VALUE 或 Integer.MIN_VALUE)
        int value2 = Ints.saturatingCast(overflowValue);
        System.out.println("saturatingCast 截断值: " + value2); // 2147483647
    }
}
3.2.2、最值、范围约束与比较
import com.google.common.primitives.Ints;

public class IntsMathDemo {
    public static void main(String[] args) {
        // 1. 查找最值(支持变长参数)
        int maxVal = Ints.max(10, 50, 30, 90, 20); // 90
        int minVal = Ints.min(10, 50, 30, 90, 20); // 10

        // 2. 区间限制截断 (constrainToRange)
        // 将输入值限制在指定的 [min, max] 闭区间内
        int low = Ints.constrainToRange(5, 10, 20);   // 小于下限,返回 10
        int mid = Ints.constrainToRange(15, 10, 20);  // 在范围内,返回 15
        int high = Ints.constrainToRange(25, 10, 20); // 大于上限,返回 20

        System.out.println("限制后数值: " + low + ", " + mid + ", " + high);

        // 3. 原生数值比较(Java 7+ 可直接用 Integer.compare,这里行为一致)
        int cmp = Ints.compare(10, 20); // 返回负数 (-1)
    }
}
限制后数值: 10, 15, 20
3.2.3、字节序列化

在网络编程(如 Netty、Socket)或二进制协议解析中,需要频繁将 32 位 int(4 字节)与 byte[] 互转。Ints 采用标准 网络字节序(大端序 / Big-Endian)。

import com.google.common.primitives.Ints;

public class IntsByteDemo {
    public static void main(String[] args) {
        int number = 0x12345678;

        // 1. int -> byte[] (长度为 4 的字节数组)
        byte[] bytes = Ints.toByteArray(number);
        // bytes 为 [0x12, 0x34, 0x56, 0x78]

        // 2. byte[] -> int
        int restored = Ints.fromByteArray(bytes);
        System.out.println("还原后的数值: 0x" + Integer.toHexString(restored)); // 0x12345678

        // 3. 从 4 个独立 byte 构造 int
        int customInt = Ints.fromBytes((byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00);
        System.out.println("解析出的数值: " + customInt); // 256
    }
}
还原后的数值: 0x12345678
解析出的数值: 256
3.2.4、数组高阶操作

除了查找单个元素,Ints 还提供了子数组查找与降序排序等便捷功能:

import com.google.common.primitives.Ints;
import java.util.Arrays;

public class IntsArrayDemo {
    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 2, 3};

        // 1. 查找连续匹配的子数组 (Target Subarray) 起始位置
        int[] target = {2, 3};
        int subIdx = Ints.indexOf(array, target);
        System.out.println("子数组首次匹配索引: " + subIdx); // 1

        // 2. 原位反转数组 (Reverse)
        Ints.reverse(array);
        System.out.println("反转后首个元素: " + array[0]); // 3

        // 3. 原位降序排序 (Sort Descending)
        Ints.sortDescending(array);
        System.out.println("降序排序后: " + Arrays.toString(array)); // [5, 4, 3, 3, 2, 2, 1]

        // 4. 数组拼接 (Concat)
        int[] extra = {100, 200};
        int[] combined = Ints.concat(array, extra);
        System.out.println("拼接后长度: " + combined.length); // 9
    }
}
子数组首次匹配索引: 1
反转后首个元素: 3
降序排序后: [5, 4, 3, 3, 2, 2, 1]
拼接后长度: 9
3.2.5、集合适配与字符串处理
  • asList(int… backingArray):将 int[] 包装为 List<Integer>。需要注意,返回的 List 底层仍然由原 int[] 支撑,修改 List 会同步改动原数组。
  • stringConverter():提供 Converter<String, Integer>,方便在双向映射框架中作为参数传递。
import com.google.common.base.Converter;
import com.google.common.primitives.Ints;
import java.util.List;

public class IntsConvertDemo {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30};

        // 1. 原生数组包装为 List 视图(无需装箱复制,高性能)
        List<Integer> intList = Ints.asList(numbers);
        intList.set(0, 99);
        System.out.println("原数组第 0 位联动更新为: " + numbers[0]); // 99

        // 2. 数组元素快速用分隔符拼接为字符串
        String joined = Ints.join(" - ", numbers);
        System.out.println("拼接字符串: " + joined); // "99 - 20 - 30"

        // 3. StringConverter 转换器
        Converter<String, Integer> converter = Ints.stringConverter();
        Integer num = converter.convert("123");          // String -> Integer
        String str = converter.reverse().convert(456);  // Integer -> String
        System.out.println("解析结果: " + num + ", 正反向转换: " + str);
    }
}
原数组第 0 位联动更新为: 99
拼接字符串: 99 - 20 - 30
解析结果: 123, 正反向转换: 456

4、Longs

Guava 中的 Longs(属于 com.google.common.primitives 包)是专门用于操作原生 long 类型以及 long[] 数组的静态工具类。

它补足了 JDK 标准库对原生 long 数组支持的不足,提供了字节序列化、数值比较与范围约束、子数组查找、原位数组操作以及与集合的无缝适配等功能。

4.1、核心API

分类核心 API 方法说明
数值计算与范围min, max, constrainToRange, compare求最值(支持变长参数)、区间限制截断、数值比较
字节/二进制序列化toByteArray, fromByteArray, fromByteslong(8字节)与 byte[](大端序/Big-Endian)双向转换
数组查找与匹配contains, indexOf, lastIndexOf查找单个 long 或匹配整个 long[] 子数组的索引
数组修改与拼接concat, ensureCapacity, reverse, sortDescending合并、动态扩容、原位反转、降序排序
集合与类型转换asList, toArray, join, stringConverter原生数组与 List<Long> 视图转换、分隔符拼接、字符串双向转换器

4.2、使用示例

4.2.1、最值、范围约束与数值比较
import com.google.common.primitives.Longs;

public class LongsMathDemo {
    public static void main(String[] args) {
        // 1. 查找最值(支持变长参数)
        long maxVal = Longs.max(100L, 500L, 300L, 900L, 200L); // 900
        long minVal = Longs.min(100L, 500L, 300L, 900L, 200L); // 100

        // 2. 区间限制截断 (constrainToRange)
        // 将输入值限制在指定的 [min, max] 闭区间内
        long low = Longs.constrainToRange(50L, 100L, 200L);   // 小于下限,返回 100
        long mid = Longs.constrainToRange(150L, 100L, 200L);  // 在范围内,返回 150
        long high = Longs.constrainToRange(250L, 100L, 200L); // 大于上限,返回 200

        System.out.println("限制后数值: " + low + ", " + mid + ", " + high);

        // 3. 数值比较
        int cmp = Longs.compare(100L, 200L); // 返回负数 (-1)
    }
}
限制后数值: 100, 150, 200
4.2.2、字节序列化

在分布式系统、RPC 框架(如 Thrift/Protobuf 底层)或二进制存储(如 RocksDB Key 序列化)中,经常需要将 64 位 long(8 字节)与 byte[] 进行互转。Longs 默认采用 网络字节序(大端序 / Big-Endian)。

import com.google.common.primitives.Longs;

public class LongsByteDemo {
    public static void main(String[] args) {
        long value = 0x123456789ABCDEF0L;

        // 1. long -> byte[] (长度为 8 的字节数组)
        byte[] bytes = Longs.toByteArray(value);
        // bytes[0] = 0x12, bytes[1] = 0x34 ... bytes[7] = 0xF0

        // 2. byte[] -> long
        long restored = Longs.fromByteArray(bytes);
        System.out.println("还原后的数值: 0x" + Long.toHexString(restored).toUpperCase()); // 0x123456789ABCDEF0

        // 3. 从 8 个独立 byte 构造 long
        long customLong = Longs.fromBytes(
                (byte) 0, (byte) 0, (byte) 0, (byte) 0,
                (byte) 0, (byte) 0, (byte) 1, (byte) 0
        );
        System.out.println("解析出的数值: " + customLong); // 256
    }
}
还原后的数值: 0x123456789ABCDEF0
解析出的数值: 256
4.2.3、数组高阶操作(

除了基础查找,Longs 还支持连续子数组匹配、降序排序以及原位反转:

import com.google.common.primitives.Longs;
import java.util.Arrays;

public class LongsArrayDemo {
    public static void main(String[] args) {
        long[] array = {10L, 20L, 30L, 40L, 50L, 20L, 30L};

        // 1. 查找连续匹配的子数组 (Target Subarray) 起始位置
        long[] target = {20L, 30L};
        int subIdx = Longs.indexOf(array, target);
        System.out.println("子数组首次匹配索引: " + subIdx); // 1

        // 2. 原位反转数组 (Reverse)
        Longs.reverse(array);
        System.out.println("反转后首个元素: " + array[0]); // 30L

        // 3. 原位降序排序 (Sort Descending)
        Longs.sortDescending(array);
        System.out.println("降序排序后: " + Arrays.toString(array)); // [50, 40, 30, 30, 20, 20, 10]

        // 4. 数组拼接 (Concat)
        long[] extra = {100L, 200L};
        long[] combined = Longs.concat(array, extra);
        System.out.println("拼接后长度: " + combined.length); // 9
    }
}
子数组首次匹配索引: 1
反转后首个元素: 30
降序排序后: [50, 40, 30, 30, 20, 20, 10]
拼接后长度: 9
4.2.4、集合适配与转换
  • asList(long… backingArray):将 long[] 包装为 List。修改 List 视图会同步改变原始数组(由原数组直接支撑,不产生多余的对象拷贝)。
  • stringConverter():返回 Converter<String, Long> 实例,便于与 Guava 的其他函数式 API 配合使用。
import com.google.common.base.Converter;
import com.google.common.primitives.Longs;
import java.util.List;

public class LongsConvertDemo {
    public static void main(String[] args) {
        long[] numbers = {100L, 200L, 300L};

        // 1. 原生数组包装为 List 视图(零拷贝,高性能)
        List<Long> longList = Longs.asList(numbers);
        longList.set(0, 999L);
        System.out.println("原数组第 0 位同步更新为: " + numbers[0]); // 999

        // 2. 数组元素快速用分隔符拼接为字符串
        String joined = Longs.join(" | ", numbers);
        System.out.println("拼接字符串: " + joined); // "999 | 200 | 300"

        // 3. StringConverter 转换器
        Converter<String, Long> converter = Longs.stringConverter();
        Long parsed = converter.convert("123456789");        // String -> Long
        String str = converter.reverse().convert(987654321L); // Long -> String
        System.out.println("转换结果: " + parsed + " / " + str);
    }
}
原数组第 0 位同步更新为: 999
拼接字符串: 999 | 200 | 300
转换结果: 123456789 / 987654321
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值