Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。
Guava 是Java的工具集,提供了一些常用的便利的操作工具类,减少因为 空指针、异步操作等引起的问题BUG,提高开发效率。
Google Guava中包含大概七大模块,分别如下:
- Guava Utils:在Guava中封装了很多关于字符串,join,split,断言等工具,可以极大的方便我们在开发中进行使用
- Functional Programming:在JDK8 以前,Java对函数式编程几乎没有任何支持,Guava提供了一系列的函数式编程接口,可以很方便的使用函数式(陈述式)编写优雅灵活的代码
- Collections: 相比较Java的Collections以及Apache Commons的Collections,Guava的Collections显然要强大很多,在Google Guava中支持了几乎你能想到的任何数据结构 ,这对对程序员来说无路是使用,还是研习代码都有很大的裨益
- Concurrency: 在Guava中对并发编程也提供了不少的支持,比如Monitor(类似于条件锁),支持回调的Future接口,异步函数接口以及RateLimte,使用RateLimte我们可以很容易的实现令牌桶,漏桶等高并发算法
- Guava Cache: Guava的Cache功能同样非常强大,通过Google Guava我们可以轻而易举的实现基于JVM进程级别的Cache功能
- EventBus:事件总线,是一个非常好的程序解耦合解决方案,使用EventBus,就像使用消息中间件一样,让Event的消费者只专注于Event本身
- Guava IO:在Guava中提供了很多source,sink,encoding工具集,可以很方便的操作文件,以及字节流
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.0-jre</version>
</dependency>
1 使用和避免null
大多数情况下,使用null表明的是某种缺失情况
Guava引入 Optional<T>表明可能为null的T类型引用,Optional实例可能包含非null的引用(引用存在),也可能什么也不包括(引用缺失)
正是受到Guava的启发,Java8将Optional类做为一个新特性引入进Java8的类库
1.1 学习Java8中的Optional使用方法
import java.util.Optional;
/** * 三种创建Optional对象方式 */
// 1.创建空的Optional对象Optional<Object> optional1 = Optional.empty();
// 2.使用非null值创建Optional对象Optional<String> optional2 = Optional.of("蔡徐坤");
// 3.使用任意值创建Optional对象Optional optional3 = Optional.ofNullable("乔碧萝");
Optional optional = Optional.ofNullable("蔡徐坤");/** * 判断是否引用缺失的方法(建议不直接使用) */boolean isNull = optional.isPresent();/** * 当optional引用存在时执行 * 类似的方法:map filter flatMap */optional.ifPresent(System.out::println);
Optional optional = Optional.empty();/** * 当optional引用缺失时执行 */// 1.引用缺失时的替换值Object obj1 = optional.orElse("引用缺失");System.out.println(obj1); // 2.自定义引用缺失时的返回值Object obj2 = optional.orElseGet(() -> { return "自定义引用缺失";});System.out.println(obj2); // 3.抛出异常Object obj3 = optional.orElseThrow(() -> { throw new RuntimeException("引用缺失异常");});
public static void stream(List<String> list) { // list.stream().forEach(System.out::println); Optional.ofNullable(list) .map(List::stream) //创建一个空的流 .orElseGet(Stream::empty) .forEach(System.out::println); }public static void main(String[] args) { List<String> list = new ArrayList(){{ add("蔡徐坤"); add("乔碧萝"); add("卢本伟"); }}; stream(list); //stream(null);}
@Dataclass User { private String id; private String name; public User(){} public User(String id,String name){this.id=id;this.name=name;}} public class OptionalTest { public static void main(String[] args) { User user = new User(); user.setName("蔡徐坤"); user = null; String name = Optional.ofNullable(user).map(User::getName).orElse("默认值"); System.out.println(name); }}
2 不可变集合
- 创建对象的不可变拷贝是一项很好的防御性编程技巧
- Guava为所有JDK标准集合类型和Guava新集合类型都提供了简单易用的不可变版本
2.1 不可变对象的优点
- 当对象被不可信的库调用时,不可变形式是安全的
- 不可变对象被多个线程调用时,不存在竞态条件问题
- 不可变集合不需要考虑变化,因此可以节省时间和空间
- 不可变对象因为有固定不变,可以作为常量来安全使用
2.2 JDK提供的unmodifiableXxx方法
- 笨重而且累赘
- 不安全
- 低效
public static void test(List<Integer> list) { list.remove(0);}public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>() {{ add(1); add(2); add(3); }}; //创建不可变集合 List<Integer> newList = Collections.unmodifiableList(list); test(newList); System.out.println(newList);}
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableList.remove(Collections.java:1317)
at com.imooc.zhangxiaoxi.guava.ImmutableTest.test(ImmutableTest.java:16)
at com.imooc.zhangxiaoxi.guava.ImmutableTest.main(ImmutableTest.java:26)
2.3 Guava构造不可变集合对象
import com.google.common.collect.ImmutableSet;import com.google.common.collect.Sets;
List<Integer> list = new ArrayList<Integer>() {{ add(1); add(2); add(3);}};
// 1.通过已经存在的集合创建ImmutableSet<Integer> immutable = ImmutableSet.copyOf(list);
// 2.通过初始值,直接创建不可变集合
ImmutableSet immutableSet = ImmutableSet.of(1, 2, 3);
// 3.以builder方式创建
ImmutableSet.builder() .add(1) .addAll(Sets.newHashSet(2, 3)) .add(4) .build();
List<Integer> list = new ArrayList<Integer>() {{
add(1);
add(2);
add(3);}};
ImmutableSet<Integer> immutableList = ImmutableSet.copyOf(list);
//immutableList里面的添加删除方法时不支持的
for (Integer num : immutableList) { System.out.println(num);}
3 新集合类型
Guava引入了很多JDK没有的、但明显有用的新集合类型。这些新类型是为了和JDK集合框架共存,而没有往JDK集合抽象中硬塞其他概念。
3.1 Multiset
image3.1.1 Multiset两种视角
image没有元素顺序限制的ArrayList(E)
imageMap<E, Integer> ,键为元素,值为计数
3.1.2 Multiset与Map的区别
image3.1.3 多种Multiset的实现
image3.1.4 Coding
import com.google.common.collect.HashMultiset;import com.google.common.collect.Multiset;import com.google.common.primitives.Chars;import org.junit.Test;import java.util.Arrays;/** * 实现:使用Multiset统计一首古诗的文字出现频率 */public class MultisetTest { private static final String text = "《南陵别儿童入京》" + "白酒新熟山中归,黄鸡啄黍秋正肥。" + "呼童烹鸡酌白酒,儿女嬉笑牵人衣。" + "高歌取醉欲自慰,起舞落日争光辉。" + "游说万乘苦不早,著鞭跨马涉远道。" + "会稽愚妇轻买臣,余亦辞家西入秦。" + "仰天大笑出门去,我辈岂是蓬蒿人。"; @Test public void handle() { // multiset创建 Multiset<Character> multiset = HashMultiset.create(); // string 转换成 char 数组 char[] chars = text.toCharArray(); System.out.println(Arrays.toString(chars)); // 遍历数组,添加到multiset中 //multiset.addAll(Chars.asList(chars)); Chars.asList(chars) .stream() .forEach(charItem -> { multiset.add(charItem); }); System.out.println("size : " + multiset.size()); System.out.println("count : " + multiset.count('人')); }}
4 集合工具类
import com.alibaba.fastjson.JSON;import com.google.common.collect.Lists;import com.google.common.collect.Sets;import org.junit.Test;
/** * Lists / Sets 使用 */public class SetsTest { /** * Sets工具类的常用方法 * 并集 / 交集 / 差集 / 分解集合中的所有子集 / 求两个集合的笛卡尔积 * * Lists工具类的常用方式 * 反转 / 拆分 */ private static final Set set1 = Sets.newHashSet(1, 2); private static final Set set2 = Sets.newHashSet(4);
4.1 Sets的使用
4.1.1 并集
// 并集@Testpublic void union() { Set<Integer> set = Sets.union(set1, set2); //[1, 2, 4] System.out.println(set);}
4.1.2 交集
// 交集@Testpublic void intersection() { Set<Integer> set = Sets.intersection(set1, set2); //[] System.out.println(set);}
4.1.3 差集
@Testpublic void difference() { // 差集:如果元素属于A而且不属于B Set<Integer> set = Sets.difference(set1, set2); //[1, 2] System.out.println(set); // 相对差集:属于A而且不属于B 或者 属于B而且不属于A // 两个集合之和-两个集合的交集 set = Sets.symmetricDifference(set1, set2); //[1, 2, 4] System.out.println(set);}
4.1.4 拆分所有子集合
// 拆分所有子集合@Testpublic void powerSet() { Set<Set<Integer>> powerSet = Sets.powerSet(set1); //[[],[1],[2],[1,2]] System.out.println(JSON.toJSONString(powerSet));}
4.1.5 计算两个集合笛卡尔积
// 计算两个集合笛卡尔积@Testpublic void cartesianProduct() { Set<List<Integer>> product = Sets.cartesianProduct(set1, set2); //[[1,4],[2,4]] System.out.println(JSON.toJSONString(product));}
4.2 Lists的使用
4.2.1 拆分
/** * 拆分 */@Testpublic void partition() { List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7); //拆分成3个3个一组 List<List<Integer>> partition = Lists.partition(list, 3); //[[1,2,3],[4,5,6],[7]] System.out.println(JSON.toJSONString(partition));}
4.2.2 反转
// 反转@Testpublic void reverse() { List<Integer> list = Lists.newLinkedList(); list.add(1); list.add(2); list.add(3); List<Integer> newList = Lists.reverse(list); //[3, 2, 1] System.out.println(newList);}
5 I/O
5.1 对字节流/字符流提供的工具方法
image需要手动关闭流
5.2 对源(Source)与汇(Sink)的抽象
image不需要手动关闭流
5.3 Coding
import com.google.common.base.Charsets;import com.google.common.io.CharSink;import com.google.common.io.CharSource;import com.google.common.io.Files;import org.junit.Test;import java.io.File;import java.io.IOException;
/** * 演示如何使用流(Source)与汇(Sink)来对文件进行常用操作 */public class IOTest { @Test public void copyFile() throws IOException { /** * 创建对应的Source和Sink */ CharSource charSource = Files.asCharSource(new File("SourceText.txt"), Charsets.UTF_8); CharSink charSink = Files.asCharSink(new File("TargetText.txt"), Charsets.UTF_8); /** * 拷贝 */ charSource.copyTo(charSink); }}
6 异常工具类
6.1 获得字符串类型的堆栈信息
public class ExceptionStackTest { public static void main(String[] args) { try { controller(); } catch (Throwable e) { String stackTrace = Throwables.getStackTraceAsString(e); System.out.println(stackTrace); } } private static void controller() { service(); } private static void service() { dao(); } private static void dao() { int a = 1 / 0; }}//java.lang.ArithmeticException: / by zero// at cn.yuanyu.guava.ExceptionStackTest.dao(ExceptionStackTest.java:24)// at cn.yuanyu.guava.ExceptionStackTest.service(ExceptionStackTest.java:21)// at cn.yuanyu.guava.ExceptionStackTest.controller(ExceptionStackTest.java:18)// at cn.yuanyu.guava.ExceptionStackTest.main(ExceptionStackTest.java:11)
网友评论