Guava的類特別多,就將常用的進行展開記錄,以後需要用到了再補充
Guava簡介
Guava工程包含了若干個被Google的Java項目廣泛依賴的核心庫,例如:集合、緩存、原生類型支持、併發庫、通用註解、字符串處理、I/0等等
引入依賴
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.1-jre</version>
</dependency>
對null處理 :Optional類
Optional 類是一個可以爲null的容器對象
Optional 類的引入很好的解決空指針異常
JDK8中,將Optional類引入到了Java 8的類庫,所以可以直接使用JDK的Optional類
創建Optional對象的三種方式
//創建空的Optional對象
Optional.empty();
//使用非null值創建Optional對象
Optional.of("zhangsan");
//使用任意值創建Optional對象
Optional<Object> optional = Optional.ofNullable("zhangsan");
常用方法:
- 判斷是否引用缺失(null)
/**
* 判斷是否引用缺失(是否爲空)
* 不建議使用
*/
optional.isPresent();
- 如果引用存在(非nulll),則進行系列操作
/**
* 如果引用存在,即不爲null,進行操作(如打印)
* 類似的有map。flatmap,filter
*/
optional.ifPresent(System.out::println);
- 引用缺失時的三種操作
optional.orElse("引用缺失");//缺失修改值爲某值
optional.orElseGet(() -> {//缺失時直接進行相應操作(如返回提示)
return "自定義引用缺失";
});
optional.orElseThrow(() -> {//缺失時可以拋出異常
throw new RuntimeException("引用缺失異常");
});
- 實際應用實踐
創建一個方法通過流打印集合內容
public static void stream(List<String> list) {
//如果list爲空,會拋出異常
list.stream().forEach(System.out::println);
}
如果list爲空,則會拋出異常,stream初始化失敗
使用Optional進行優化:
public static void stream(List<String> list) {
//如果list不爲空,初始化流,如果爲空,初始化一個空的流
Optional.ofNullable(list)
.map(List::stream)
.orElseGet(Stream::empty)
.forEach(System.out::println);
}
- 首先通過 Optional.ofNullable(list)創建一個Optional對象
- 如果Optional對象引用存在,則執行map中的list.stream()方法
- 如果Optional對象引用缺失,則執行 Stream.empty()方法創建一個空的對象
- 最後再打印輸出
不可變集合 :Immutable*類
不可變對象的優點:
- 當對象被不可信的庫調用時,是安全的
- 不可變對象在多線程環境下安全
- 不可變集合不需要考慮變化,可以節省時間和空間
- 不可變對象常作爲常量來安全使用
Immutabl*是一系列的不可變集合,包括了很多很多的類,使用起來其實大同小異,一下就以ImmutableSet說明下他的創建
創建不可變對象的三種方式(以ImmutableSet爲例)
List<Integer>list = new ArrayList<Integer>(){
{add(1);}
{add(2);}
{add(3);}
};
//通過已存在集合創建
ImmutableSet.copyOf(list);
//通過初始值直接創建不可變集合
ImmutableSet.of(1, 2, 3, 4, 5);
//以builder方式創建
ImmutableSet immutableSet = ImmutableSet.builder()
.add(1)
.addAll(Sets.newHashSet(2, 3, 4))
.add(5)
.build();
構建好的Immutable*的對象不具有添加和刪除的接口
新的集合類型 Multiset接口
類似的還有和Multimap接口,一下以Multiset爲例
Multiset是一種介於Set和List直接的一種數據結構,兩種角度理解Multiset
- 沒有元素順序限制的ArrayList
- add(E):添加單個元素
- iterator():返回一個迭代器
- size():返回所有元素的總個數(包括重複的)
- Map<E,Integer>,鍵爲元素,值爲計數
- count(Object):返回給的元素的計數
- entrySet():相當於Map中的entrySet
- elementSet():相當於Map中的KeySet
接口的五種實現類:
- HashMultiset
- TreeMultiset
- LinkedHashSet
- ConcurrentHashMultiset
- mmutableMultiset
業務中的實踐:
實現字符統計的功能
/**
* 〈使用Mutiset統計古詩文字出現頻率〉
*
* @author Chkl
* @create 2020/4/21
* @since 1.0.0
*/
public class MultisetTest {
private static final String text =
"《山坡羊·潼關懷古》\n" +
"峯巒如聚,波濤如怒,山河表裏潼關路。 \n" +
"望西都,意躊躇。\n" +
"傷心秦漢經行處,宮闕萬間都做了土。 \n" +
"興,百姓苦。亡,百姓苦。";
@Test
public void handle(){
//創建Multiset
Multiset<Character> multiset = HashMultiset.create();
//stirng to char
char[] chars = text.toCharArray();
//遍歷數組,加入到multiset
Chars.asList(chars)
.stream()
.forEach(charitem->{
multiset.add(charitem);
});
System.out.println(multiset.size());
for (Character c : multiset.elementSet()){
System.out.println(c+" "+multiset.count(c));
}
}
}
常用工具集 :Sets、Lists類
Sets工具類常用方法: 並集、交集、差集、分解集合中所有的子集、求兩個集合的笛卡爾積
Lists工具類常用方法: 反轉、拆分
演示實踐:
初始化兩個set
private static final Set set1 =
Sets.newHashSet(1, 2, 3, 4);
private static final Set set2 =
Sets.newHashSet(4, 5, 6);
- 求並集
@Test
public void union() {
Set<Integer> set = Sets.union(set1, set2);
System.out.println(set);
}
- 求交集
@Test
public void intersection() {
Set<Integer> set = Sets.intersection(set1, set2);
System.out.println(set);
}
- 求差集
元素屬於a但不屬於b
@Test
public void difference() {
Set<Integer> set = Sets.difference(set1, set2);
System.out.println(set);
}
- 求相對差集
元素屬於a但不屬於b 或元素屬於b但不屬於a
@Test
public void symmetricDifference() {
Set<Integer> set = Sets.symmetricDifference(set1, set2);
System.out.println(set);
}
- 拆解集合(求所有子集)
@Test
public void powerSet() {
Set<Set<Integer>> set = Sets.powerSet(set1);
System.out.println(JSON.toJSONString(set));
}
- 求笛卡爾積
@Test
public void cartesianProduct() {
Set<List<Integer>> set = Sets.cartesianProduct(set1, set2);
System.out.println(JSON.toJSONString(set));
}
初始化一個List
private static final List<Integer> list =
Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);
- 按指定長度拆分
@Test
public void partition() {
List<List<Integer>> partition = Lists.partition(list, 3);
System.out.println(JSON.toJSONString(partition));
}
- 反轉集合
@Test
public void reverse() {
List<Integer> reverse = Lists.reverse(list);
System.out.println(JSON.toJSONString(reverse));
}
IO操作: Files類
對字節流和字符流操作的封裝
- ByteStreams:提供對InputStream和OutputStream針對字節流的操作
- CharStreams:提供Reader和Writer針對字符流的操作
針對源(Source)和匯(Sink)的抽象
- 源(可讀的):ByteSource/CharSource
- 匯(可寫的):ByteSink/CharSink
Files中封裝了很多好用的方法,這裏主要記錄一下源與匯的使用
實踐案例:
通過源與匯實現文件拷貝,源與匯是比較高級的封裝,直接使用不需要對輸入輸出流進行創建和關閉
/**
* 通過源與匯實現文件拷貝
*/
@Test
public void copyFile() throws IOException {
/**
* 創建對應的Source和Sink
*/
CharSource charSource = Files.asCharSource(
new File("lib/FileCopy.java"), Charsets.UTF_8);
CharSink charSink = Files.asCharSink(
new File("outTest/out.txt"), Charsets.UTF_8);
/**
* 拷貝,不需要創建連接和關閉連接
*/
charSource.copyTo(charSink);
}
更多的方法在具體使用時查Api吧 ,源與匯還是挺好用的
最後
Guava用起來非常強大,方法也非常多,找到一個算是目錄的網站,可以去系統的看一看Api 直達