Guava库是一组来自Google的核心Java库,其设计目的是为了简化Java开发过程,提高开发效率。这个库包含了大量实用的API,可以帮助开发者解决日常开发中遇到的各种问题。
提升编程效率的利器: 解析Google Guava库之集合篇Immutable(一)
提升编程效率的利器: 解析Google Guava库之集合篇Multimap(二)
提升编程效率的利器: 解析Google Guava库之集合篇BitMap(三)
提升编程效率的利器: 解析Google Guava库之集合篇Table二维映射(四)
提升编程效率的利器: 解析Google Guava库之集合篇RangeSet范围集合(五)
提升编程效率的利器: 解析Google Guava库之集合篇RangeMap范围映射(六)
一、源码包的分布
Guava库的源码包分布非常广泛,覆盖了多个不同的功能领域。以下是一些主要的源码包及其功能:
com.google.common.base:这个包包含了基本工具类库和接口,提供了一些通用的功能,如Preconditions(用于参数校验)、Optional(用于处理可能为null的值)等。
com.google.common.collect:这个包提供了带泛型的集合接口扩展和实现,以及工具类。它增加了一些Java标准库中没有的集合类型,如Multimap(多映射)、Multiset(多集)等,还提供了一些用于操作集合的实用方法。
com.google.common.eventbus:这个包实现了一个发布-订阅风格的事件总线,允许在不同组件之间发布和订阅事件,实现松耦合的通信。
com.google.common.hash:这个包提供了哈希工具类,用于计算哈希值和处理哈希相关的操作。
com.google.common.io:这个包包含了I/O工具类,提供了一些简化I/O操作的实用方法,如文件读写、字节流处理等。
com.google.common.math:这个包提供了原始算术类型和超大数的运算工具类,用于进行数学计算和处理大数字。
com.google.common.net:这个包包含了网络工具类,提供了一些与网络相关的实用功能,如URL处理、网络地址解析等。
com.google.common.primitives:这个包提供了对八种原始类型和无符号类型的静态工具类,包括一些基本类型的操作、转换和比较。
com.google.common.reflect:这个包包含了反射工具类,提供了一些用于反射操作的实用方法,如获取类信息、调用方法等。
com.google.common.util.concurrent:这个包提供了多线程工具类,包括一些并发编程的实用功能,如异步计算、线程池管理等。
这些源码包构成了Guava库的核心,提供了丰富的功能和工具类,方便开发者进行Java开发。通过使用Guava库,开发者可以更加高效地处理集合、缓存、并发编程、字符串处理、I/O操作等各种常见的开发任务。
二、字符处理工具
import com.google.common.base.CharMatcher; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.io.CharStreams; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; public class GuavaDemo { public static void main(String[] args) throws IOException { // 1.使用Joiner拼接字符串 String joinedString = Joiner.on(", ").join("apple", "banana", "cherry"); System.out.println(joinedString); // 输出: apple, banana, cherry // 2.使用Splitter拆分字符串 Iterable<String> splitStrings = Splitter.on(",").trimResults().split(joinedString); for (String s : splitStrings) { System.out.println(s); // 输出: apple, banana, cherry(每行一个) } // 3.使用Strings处理字符串 String nullString = null; String emptyString = ""; String whitespaceString = " "; System.out.println(Strings.nullToEmpty(nullString)); // 输出: (空字符串) System.out.println(Strings.isNullOrEmpty(emptyString)); // 输出: true System.out.println(Strings.isNullOrEmpty(whitespaceString)); // 输出: false System.out.println(CharMatcher.whitespace().removeFrom(whitespaceString)); // 输出: (空字符串) // 4.使用Charsets指定字符集 Charset utf8 = Charsets.UTF_8; try (InputStream inputStream = GuavaDemo.class.getResourceAsStream("/test.txt"); InputStreamReader reader = new InputStreamReader(inputStream, utf8)) { String content = CharStreams.toString(reader); System.out.println(content); // 输出: test.txt文件的内容(假设文件存在且为UTF-8编码) } // 5.原始字符串,采用驼峰式命名 String camelCaseString = "ExampleClassName"; // 转换为下划线式命名 String lowerUnderscoreString = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, camelCaseString); // 打印转换后的字符串 System.out.println(lowerUnderscoreString); // 输出:example_class_name // 如果要将下划线式命名转回驼峰式命名,可以这样做: String backToCamelCaseString = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, lowerUnderscoreString); // 打印转回驼峰式命名后的字符串 System.out.println(backToCamelCaseString); // 输出:ExampleClassName // 6. 使用CharMatcher String input = "Hello, World! This is a test string."; // 使用CharMatcher移除指定字符 String resultWithoutVowels = CharMatcher.is('a', 'e', 'i', 'o', 'u').removeFrom(input); // 打印结果: "Hll, Wrld! Ths s s tst strng." System.out.println(resultWithoutVowels); // 使用CharMatcher替换指定字符 String resultReplaceVowels = CharMatcher.is('a', 'e', 'i', 'o', 'u').replaceFrom(input, '*'); // 打印结果: "H*ll*, W*rld! Th*s *s * t*st str*ng." System.out.println(resultReplaceVowels); // 使用CharMatcher保留指定字符 String resultKeepVowels = CharMatcher.is('a', 'e', 'i', 'o', 'u').retainFrom(input); // 打印结果: "eiooeiae" System.out.println(resultKeepVowels); // 7.使用CharSequences查找子序列的索引 int indexOfTest = CharSequences.indexOf(input, "test"); // 打印结果: 索引位置 21 System.out.println("索引位置: " + indexOfTest); // 使用CharSequences比较两个CharSequence boolean areEqual = CharSequences.equals("Hello", "Hello"); // 打印结果: true System.out.println("两个序列是否相等: " + areEqual); // 使用CharSequences拼接CharSequence String concatenated = CharSequences.concat("Guava ", "is ", "awesome!").toString(); // 打印结果: "Guava is awesome!" System.out.println(concatenated); } }
Joiner 被用来将一个字符串列表以逗号加空格为分隔符合并成一个字符串。
Splitter 被用来根据逗号拆分合并后的字符串,并移除了结果字符串两端的空白字符。
Strings 类中的方法被用来处理空字符串和空白字符。nullToEmpty 方法将 null 转换为空字符串,isNullOrEmpty 方法检查字符串是否为 null 或空,CharMatcher 的 whitespace().removeFrom 方法移除了字符串中的所有空白字符。
Charsets 被用来获取 UTF-8 字符集,并通过 InputStreamReader 和 CharStreams 来读取和转换文件内容。
三、原始类型工具
Ints, Longs, Doubles, Floats, Booleans, Bytes, Shorts, Chars, 和 PrimitiveArrays 是 Guava 库中提供的一组用于操作原始类型数据的实用工具类。以下是一些使用这些类的示例:
import com.google.common.primitives.Booleans; import com.google.common.primitives.Bytes; import com.google.common.primitives.Chars; import com.google.common.primitives.Doubles; import com.google.common.primitives.Floats; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; import com.google.common.primitives.Shorts; import java.util.Arrays; public class GuavaPrimitivesExample { public static void main(String[] args) { // Ints 示例 int[] intArray = {1, 2, 3, 4, 5}; int sumOfInts = Ints.sum(intArray); // 打印结果: 15 System.out.println("Sum of ints: " + sumOfInts); // Longs 示例 long[] longArray = {1L, 2L, 3L, 4L, 5L}; long sumOfLongs = Longs.sum(longArray); // 打印结果: 15 System.out.println("Sum of longs: " + sumOfLongs); // Doubles 示例 double[] doubleArray = {1.1, 2.2, 3.3, 4.4, 5.5}; double sumOfDoubles = Doubles.sum(doubleArray); // 打印结果: 16.5 System.out.println("Sum of doubles: " + sumOfDoubles); // Floats 示例 float[] floatArray = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f}; float sumOfFloats = Floats.sum(floatArray); // 打印结果: 16.5 System.out.println("Sum of floats: " + sumOfFloats); // Booleans 示例 boolean[] booleanArray = {true, false, true}; boolean anyTrue = Booleans.contains(booleanArray, true); // 打印结果: true System.out.println("Array contains true: " + anyTrue); // Bytes 示例 byte[] byteArray = {1, 2, 3, 4, 5}; byte minByte = Bytes.min(byteArray); // 打印结果: 1 System.out.println("Min byte: " + minByte); // Shorts 示例 short[] shortArray = {1, 2, 3, 4, 5}; short maxShort = Shorts.max(shortArray); // 打印结果: 5 System.out.println("Max short: " + maxShort); // Chars 示例 char[] charArray = {'a', 'b', 'c', 'd', 'e'}; int charCount = Chars.count(charArray, 'c'); // 打印结果: 1 System.out.println("Count of 'c': " + charCount); // 排序示例(使用Java标准库的Arrays.sort而不是Guava) int[] unsortedIntArray = {5, 3, 1, 4, 2}; Arrays.sort(unsortedIntArray); // 打印结果: [1, 2, 3, 4, 5] System.out.println("Sorted int array: " + Arrays.toString(unsortedIntArray)); } }
四、IO工具类
包括 InputSupplier, OutputSupplier, Resources, ByteStreams, 和 CharStreams,它们主要用于简化输入/输出操作和流处理。以下是如何使用这些工具类的示例:
import com.google.common.base.Charsets; import com.google.common.base.Supplier; import com.google.common.io.ByteStreams; import com.google.common.io.CharStreams; import com.google.common.io.InputSupplier; import com.google.common.io.OutputSupplier; import com.google.common.io.Resources; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.net.URL; public class GuavaIoExample { public static void main(String[] args) throws IOException { // InputSupplier 示例 InputSupplier<InputStream> inputSupplier = new InputSupplier<InputStream>() { @Override public InputStream getInput() throws IOException { return new ByteArrayInputStream("Hello, Guava!".getBytes(Charsets.UTF_8)); } }; // 读取 InputSupplier 并转换为字符串 String fromInputSupplier = new String(ByteStreams.toByteArray(inputSupplier.getInput()), Charsets.UTF_8); // 打印结果: Hello, Guava! System.out.println("From InputSupplier: " + fromInputSupplier); // OutputSupplier 示例 OutputSupplier<OutputStream> outputSupplier = new OutputSupplier<OutputStream>() { @Override public OutputStream getOutput() throws IOException { return new ByteArrayOutputStream(); } }; // 写入数据到 OutputSupplier 并获取结果 OutputStream outputStream = outputSupplier.getOutput(); outputStream.write("Hello, from OutputSupplier!".getBytes(Charsets.UTF_8)); ((ByteArrayOutputStream) outputStream).close(); // 对于 ByteArrayOutputStream,需要手动关闭以完成写入 // 注意:上面的代码片段实际上是有问题的,因为我们在外部关闭了流,但OutputSupplier的使用者通常期望自己关闭它。 // 正确的做法是,如果你控制了流的生命周期,不要让OutputSupplier返回它直到你准备好让调用者关闭它。 // 我们只是为了演示,实际上应该避免这样做。 // Resources 示例:从URL读取内容 URL url = Resources.getResource("somefile.txt"); // 假设 somefile.txt 在类路径上 String fromResources = Resources.toString(url, Charsets.UTF_8); // 打印文件内容(取决于 somefile.txt 的实际内容) System.out.println("From Resources: " + fromResources); // ByteStreams 示例:从输入流复制到输出流 InputStream inputStream = new ByteArrayInputStream("Data to copy".getBytes(Charsets.UTF_8)); OutputStream copyOutputStream = new ByteArrayOutputStream(); ByteStreams.copy(inputStream, copyOutputStream); String copiedData = new String(((ByteArrayOutputStream) copyOutputStream).toByteArray(), Charsets.UTF_8); // 打印结果: Data to copy System.out.println("Copied Data: " + copiedData); // CharStreams 示例:从 Reader 读取所有字符 Reader reader = new StringReader("Characters to read"); String fromCharStreams = CharStreams.toString(reader); // 打印结果: Characters to read System.out.println("From CharStreams: " + fromCharStreams); // 使用 try-with-resources 确保流正确关闭 try (StringWriter stringWriter = new StringWriter()) { // 写入数据到 StringWriter stringWriter.write("Hello, try-with-resources!"); // 从 StringWriter 获取数据 String writtenData = stringWriter.toString(); // 打印结果: Hello, try-with-resources! System.out.println("Written Data: " + writtenData); } // 在这里,StringWriter 会自动关闭,因为我们在 try-with-resources 语句中使用了它 } }
注意:在实际中应该避免像上面示例中那样手动关闭流,特别是当使用像 OutputSupplier 这样的构造时。通常,流的关闭应该由最终使用它的代码来处理,或者使用 try-with-resources 语句来自动管理资源。
五、其他常用的工具类
下面是 Guava 中 Stopwatch, ClassPath, BaseEncoding, Throwables, 和 HashCode 的使用示例:
import com.google.common.base.Charsets; import com.google.common.base.Throwables; import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; import com.google.common.io.BaseEncoding; import com.google.common.io.ClassPath; import com.google.common.primitives.Bytes; import com.google.common.util.concurrent.Uninterruptibles; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.concurrent.TimeUnit; public class GuavaUtilitiesExample { public static void main(String[] args) { // Stopwatch 示例:测量代码执行时间 Stopwatch stopwatch = Stopwatch.createStarted(); Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); // 模拟耗时操作 long elapsedMillis = stopwatch.elapsed(TimeUnit.MILLISECONDS); // 打印结果:耗时约 1000 毫秒 System.out.println("Elapsed time: " + elapsedMillis + " ms"); // ClassPath 示例:遍历类路径上的资源 try { ClassPath classPath = ClassPath.from(GuavaUtilitiesExample.class.getClassLoader()); for (ClassPath.ClassInfo classInfo : classPath.getAllClasses()) { if (classInfo.getName().contains("Guava")) { // 打印结果:包含 "Guava" 的类名 System.out.println("Class found: " + classInfo.getName()); } } } catch (IOException e) { Throwables.throwIfUnchecked(e); // 传播未检查的异常 } // BaseEncoding 示例:编码和解码 String originalText = "Hello, Guava!"; String encodedText = BaseEncoding.base64().encode(originalText.getBytes(Charsets.UTF_8)); byte[] decodedBytes = BaseEncoding.base64().decode(encodedText); String decodedText = new String(decodedBytes, Charsets.UTF_8); // 打印结果:编码后的文本和解码后的文本应该与原始文本匹配 System.out.println("Original text: " + originalText); System.out.println("Encoded text: " + encodedText); System.out.println("Decoded text: " + decodedText); // Throwables 示例:获取异常的根因 try { throw new RuntimeException("Outer exception", new IOException("Inner exception")); } catch (Exception e) { Throwable rootCause = Throwables.getRootCause(e); // 打印结果:Inner exception System.out.println("Root cause: " + rootCause.getMessage()); } // HashCode 示例:计算哈希值 String textToHash = "This is some text to hash"; HashCode hashCode = Hashing.sha256().hashString(textToHash, Charsets.UTF_8); // 打印结果:SHA-256 哈希值 System.out.println("SHA-256 hash: " + hashCode); } }
请注意以下几点:
- Stopwatch 用于测量代码段的执行时间。
- ClassPath 用于遍历类加载器加载的所有类资源。由于这可能会加载大量的类,因此在实际应用中要谨慎使用,避免性能问题。
- BaseEncoding 提供了一种便捷的方式来进行 Base64 等编码方式的编码和解码操作。
- Throwables 提供了一些实用方法来处理异常,例如获取根因。
- HashCode 是 Guava 中表示哈希值的类,它与 java.util.Objects.hash() 不同,主要用于计算特定哈希算法(如 SHA-256)的哈希值。
- ninterruptibles.sleepUninterruptibly() 是为了演示目的而使用的,它在实际应用中可能不是一个好的选择,因为它会无条件地忽略中断。在生产代码中,你应该更仔细地处理中断。