大多数情况下,使用null表明是某种缺失的情况.
Guava引入Optinal<T>表明可能为null的T类型引用.Optional实例可能包含非null的引用(引用存在),也可能什么也不包括(引用缺失).
Java8将Optional类做为一个新特性引入进Java8的类库.
1.创建空的Optional对象
Optional.empty();
2.使用非null值创建Optional对象,若为null,直接快速失败返回空指针异常
Optional.of("mingm");
3.使用任意值创建Optional对象,可以为空值
Optional.ofNullable(null);
1 /** 2 * 三种创建Optional对象方式 3 */ 4 @Test 5 public void create(){ 6 // 创建空的Optional对象 7 Optional.empty(); 8 9 // 使用非null值创建Optional对象 10 Optional.of("mingm"); 11 // Optional.of(null); 12 /* 13 java.lang.NullPointerException 14 at java.util.Objects.requireNonNull(Objects.java:203) 15 at java.util.Optional.<init>(Optional.java:96) 16 at java.util.Optional.of(Optional.java:108) 17 at com.mingm.guava.OptionalTest.create(OptionalTest.java:23) 18 */ 19 20 //使用任意值创建Optional对象 21 Optional<Object> optional = Optional.ofNullable(null); 22 23 }
1.判断是否引用缺失(建议不直接使用)
boolean present = optional.isPresent();
2.当Optional引用存在时执行,类似的方法:map filter flatMap
optional.ifPresent(System.out::println);
3.当Optional引用缺失时执行
3.1当引用缺失时赋值
optional.orElse("引用缺失");
3.2自定义引用缺失的返回值
optional.orElseGet(() -> {
return "自定义引用缺失";
});
3.3引用缺失抛出异常
optional.orElseThrow(() -> {
//注意是return一个异常对象,而不是throw一个异常对象
return new RuntimeException("引用缺失异常");
});
1 @Test 2 public void use(){ 3 //使用任意值创建Optional对象 4 Optional<Object> optional = Optional.ofNullable(null); 5 6 /** 7 * 判断是否引用缺失(建议不直接使用) 8 */ 9 boolean present = optional.isPresent(); 10 System.out.println(present); 11 12 /** 13 * 当Optional引用存在时执行 14 * 类似的方法:map filter flatMap 15 */ 16 optional.ifPresent(System.out::println); 17 18 /** 19 * 当Optional引用缺失时执行 20 */ 21 optional.orElse("引用缺失");//当引用缺失时赋值 22 //自定义引用缺失的返回值 23 optional.orElseGet(() -> { 24 return "自定义引用缺失"; 25 }); 26 //引用缺失抛出异常 27 optional.orElseThrow(() -> { 28 //注意是return一个异常对象,而不是throw一个异常对象 29 return new RuntimeException("引用缺失异常"); 30 }); 31 }
当list为null也不会抛出异常.
1 @Test 2 public void test(){ 3 stream(null); 4 } 5 public static void stream(List<String> list){ 6 // list.forEach(System.out::println); 7 8 Optional.ofNullable(list) 9 .map(List::stream) 10 .orElseGet(Stream::empty) 11 .forEach(System.out::println); 12 }
创建对象的不可变拷贝是一项很好的防御性编程技巧.
Guava为所有JDK标准集合类型和Guava新集合类型都提供了简单易用的不可变版本.
当对象被不可信得库调用时,不可变形式是安全的.
不可变对象被多个线程调用时,不存在竞态条件问题.
不可变集合不需要考虑变化,因此可以节省时间和空间.
不可变对象因为固定不变,可以作为常量安全使用.
笨重而且累赘
不安全
低效
CopyOf方法: ImmutableSet.copyOf(list);
Of方法: ImmutableSet.of(1, 2, 3);
Builder工具: ImmutableSet.builder().add(1).add(Sets.newHashSet(2, 3)).add(4).build();
1 import com.google.common.collect.ImmutableSet; 2 import com.google.common.collect.Sets; 3 import org.junit.Test; 4 5 import java.util.ArrayList; 6 import java.util.Collections; 7 import java.util.List; 8 9 /** 10 * @description: 不可变集合用法 11 */ 12 public class ImmutableTest { 13 14 List<Integer> list = new ArrayList<Integer>(){ 15 { 16 add(1); 17 add(2); 18 add(3); 19 } 20 }; 21 22 @Test 23 public void test() { 24 list.remove(0); 25 System.out.println(list); 26 } 27 28 @Test 29 public void unmodifiableXXXTest() { 30 list.remove(0); 31 List<Integer> newList = Collections.unmodifiableList(list); 32 System.out.println(newList); 33 } 34 35 /** 36 * 构造不可变集合的三种方式 37 */ 38 @Test 39 public void immutableXXXTest() { 40 //通过已经存在的集合创建 41 ImmutableSet<Integer> immutableSet = ImmutableSet.copyOf(list); 42 //通过初始值,直接创建不可变集合 43 ImmutableSet.of(1, 2, 3); 44 //以builder方式创建 45 ImmutableSet.builder() 46 .add(1) 47 .add(Sets.newHashSet(2, 3)) 48 .add(4) 49 .build(); 50 } 51 }
Guava引入了很多JDK没有的,但明显有用的新集合类型.这些新类型为了和JDK集合框架共存,而没有往JDK集合抽象中硬塞其他概念.
Guava提供了一个新集合类型Multiset,它可以多次添加相等的元素,且和元素顺序无关。Multiset继承于JDK的Cllection接口,而不是Set接口。它和set最大的区别就是它可以对相同元素做一个计数的功能.
add(E):添加单个给定元素
iterator():返回一个迭代器,包含Mutiset所有元素(包括重复元素)
size():返回所有元素的总个数(包括重复元素)
count(Object):返回给定元素的计数
entrySet():返回Set<Multiset.Entry<E>>,和Map的entrySet类似
elementSet():返回所以不重复元素的Set<E>,和Map的keySet类似
元素计数只能是正数
multiset.size()返回集合大小
multiset.iterator()会迭代重复元素
multiset支持直接设置元素的计数
没有元素,multiset.count(E)为0
HashMuitiset
TreeMuitiset
LinkedHashMultiset
ConcurrentHashMultiset
ImmutableMultiset
1 import com.google.common.collect.HashMultiset; 2 import com.google.common.collect.Multiset; 3 import com.google.common.primitives.Chars; 4 import org.junit.Test; 5 6 /** 7 * @description: 使用Multiset统计一首古诗出现频率 8 */ 9 public class MultisetTest { 10 11 private static final String text = 12 "《南陵别儿童入京》" + 13 "白酒新熟山中归,黄鸡啄黍秋正肥。" + 14 "呼童烹鸡酌白酒,儿女嬉笑牵人衣。" + 15 "高歌取醉欲自慰,起舞落日争光辉。" + 16 "游说万乘苦不早,著鞭跨马涉远道。" + 17 "会稽愚妇轻买臣,余亦辞家西入秦。" + 18 "仰天大笑出门去,我辈岂是蓬蒿人。"; 19 20 @Test 21 public void handle() { 22 //multiset创建 23 Multiset<Character> multiset = HashMultiset.create(); 24 //string转换成char数组 25 char[] chars = text.toCharArray(); 26 Chars.asList(chars) 27 .stream() 28 .forEach(character -> { 29 multiset.add(character); 30 }); 31 32 System.out.println("size: " + multiset.size()); 33 System.out.println("count:" + multiset.count(‘人‘)); 34 //size: 105 35 //count:2 36 } 37 }
任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collections包含的工具方法。Guava沿着这些路线提供了更多的工具方法:适用于所有集合的静态方法。这是Guava最流行和成熟的部分之一。
以下是Lists, Sets的用例.
1 import com.alibaba.fastjson.JSON; 2 import com.google.common.collect.Lists; 3 import com.google.common.collect.Sets; 4 import org.junit.Test; 5 6 import java.util.ArrayList; 7 import java.util.List; 8 import java.util.Set; 9 10 /** 11 * @description: Lists使用/Sets使用 12 */ 13 public class CollectionsTest { 14 15 /** 16 * Sets工具类的常用方法 17 * 并集/交集/差集/分解集合的所有子集/求两个集合的笛卡尔积 18 * 19 * Lists工具类的常用方式 20 * 反转/拆分 21 */ 22 23 private static final Set set1 = 24 Sets.newHashSet(1, 2, 3, 4); 25 26 private static final Set set2 = 27 Sets.newHashSet(4, 5, 6); 28 29 /** 30 * 并集 31 */ 32 @Test 33 public void union(){ 34 Set<Integer> set = Sets.union(set1, set2); 35 System.out.println(set); 36 //[1, 2, 3, 4, 5, 6] 37 } 38 39 /** 40 * 交集 41 */ 42 @Test 43 public void intersection(){ 44 Set<Integer> set = Sets.intersection(set1, set2); 45 System.out.println(set); 46 //[4] 47 } 48 49 /** 50 * 差集:如果元素属于A而且不属于B 51 */ 52 @Test 53 public void difference(){ 54 Set<Integer> set = Sets.difference(set1, set2); 55 System.out.println(set); 56 //[1, 2, 3] 57 58 //相对差集:属于A而且不属于B,或者属于B而且不属于A 59 Set<Integer> set0 = Sets.symmetricDifference(set1, set2); 60 System.out.println(set0); 61 //[1, 2, 3, 5, 6] 62 } 63 64 /** 65 * 获取所以子集 66 */ 67 @Test 68 public void powerSet(){ 69 Set<Set<Integer>> set = Sets.powerSet(set1); 70 System.out.println(JSON.toJSONString(set, true)); 71 //[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3],[4],[1,4],[2,4],[1,2,4],[3,4],[1,3,4],[2,3,4],[1,2,3,4]] 72 } 73 74 /** 75 * 计算笛卡尔积 76 */ 77 @Test 78 public void cartesianProduct(){ 79 Set<List<Integer>> set = Sets.cartesianProduct(set1, set2); 80 System.out.println(JSON.toJSONString(set, true)); 81 } 82 83 private static final ArrayList<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7); 84 85 /** 86 * 切片 87 */ 88 @Test 89 public void partition(){ 90 List<List<Integer>> partition = Lists.partition(list, 3); 91 System.out.println(JSON.toJSONString(partition)); 92 //[[1,2,3],[4,5,6],[7]] 93 } 94 95 /** 96 * 反转 97 */ 98 @Test 99 public void reverse(){ 100 List<Integer> integerList = Lists.reverse(list); 101 System.out.println(integerList); 102 //[7, 6, 5, 4, 3, 2, 1] 103 } 104 105 }
ByteStream:提供对InputStream/OutputStream的操作
CharStream:提供对Reader/Writer的操作
源是可读的:ByteSource/CharSource
汇是可写的:ByteSink/CharSink
1 import com.google.common.base.Charsets; 2 import com.google.common.io.CharSink; 3 import com.google.common.io.CharSource; 4 import com.google.common.io.Files; 5 import org.junit.Test; 6 7 import java.io.File; 8 import java.io.IOException; 9 10 /** 11 * @description: 演示如何使用流(Source)与汇(Sink)来对文件进行操作 12 */ 13 public class IOTest { 14 /** 15 * 并不需要对流关闭 16 * @throws IOException 17 */ 18 @Test 19 public void copyFile() throws IOException { 20 21 /** 22 * 创建对应的Source和Sink 23 */ 24 CharSource charSource = Files.asCharSource(new File("lib/SourceText.txt"), Charsets.UTF_8); 25 CharSink charSink = Files.asCharSink(new File("lib/SinkText.txt"), Charsets.UTF_8); 26 27 /** 28 * 拷贝 29 */ 30 charSource.copyTo(charSink); 31 } 32 }
原文:https://www.cnblogs.com/mingmingn/p/13131388.html