天天看點

guava快速入門(二)

Guava工程包含了若幹被Google的 Java項目廣泛依賴 的核心庫,例如:集合 [collections] 、緩存 [caching] 、原生類型支援 [primitives support] 、并發庫 [concurrency libraries] 、通用注解 [common annotations] 、字元串處理 [string processing] 、I/O 等等。

guava類似Apache Commons工具集

Collection

不可變集合

不可變對象有很多優點,包括:

  • 當對象被不可信的庫調用時,不可變形式是安全的;
  • 不可變對象被多個線程調用時,不存在競态條件問題
  • 不可變集合不需要考慮變化,是以可以節省時間和空間。所有不可變的集合都比它們的可變形式有更好的記憶體使用率(分析和測試細節);
  • 不可變對象因為有固定不變,可以作為常量來安全使用。

JDK也提供了Collections.unmodifiableXXX方法把集合包裝為不可變形式,但:

  • 笨重而且累贅:不能舒适地用在所有想做防禦性拷貝的場景;
  • 不安全:要保證沒人通過原集合的引用進行修改,傳回的集合才是事實上不可變的;
  • 低效:包裝過的集合仍然保有可變集合的開銷,比如并發修改的檢查、散清單的額外空間,等等。

建立不可變集合方法:

  • copyOf方法,如ImmutableSet.copyOf(set);
  • of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2);
  • Builder工具
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

public class ImmutableDemo {
	public static void main(String[] args) {
		ImmutableSet<String> set = ImmutableSet.of("a", "b", "c", "d");
		ImmutableSet<String> set1 = ImmutableSet.copyOf(set);
		ImmutableSet<String> set2 = ImmutableSet.<String> builder().addAll(set).add("e").build();
		ImmutableList<String> list = set.asList();
		
		System.out.println("set:"+set);
		System.out.println("set1:"+set1);
		System.out.println("set2:"+set2);
		//set.add("f");//java.lang.UnsupportedOperationException
	}
}
      

  傳回:

set:[a, b, c, d]
set1:[a, b, c, d]
set2:[a, b, c, d, e]
      

  

新型集合類

Multiset

Multiset可統計一個詞在文檔中出現了多少次

import com.google.common.collect.LinkedHashMultiset;
import com.google.common.collect.Multiset;

public class MultiSetDemo {

	public static void main(String[] args) {
		Multiset<String> set = LinkedHashMultiset.create();
		set.add("a");
		set.add("a");
		set.add("lucas");
		set.add("lucas");
		set.setCount("a", 5); // 添加或删除指定元素使其在集合中的數量是count
		System.out.println(set);
		System.out.println(set.count("a")); // 給定元素在Multiset中的計數
		System.out.println(set.size()); // 所有元素計數的總和,包括重複元素
		System.out.println(set.elementSet().size()); // 所有元素計數的總和,不包括重複元素
		set.clear(); // 清空集合
		System.out.println(set);

	}

}
      
[a x 5, lucas x 2]
5
7
2
[]
      
Multimap

Multimap可以很容易地把一個鍵映射到多個值。換句話說,Multimap是把鍵映射到任意多個值的一般方式。

import java.util.Collection;
import java.util.Map;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

public class MultiMapDemo {

	public static void main(String[] args) {
		Multimap<String, Integer> map = HashMultimap.create(); // Multimap是把鍵映射到任意多個值的一般方式
		map.put("a", 1); // key相同時不會覆寫原value
		map.put("a", 2);
		map.put("a", 3);
		map.put("b", 1);
		map.put("b", 2);
		System.out.println(map); // {a=[1, 2, 3]}
		System.out.println(map.get("a")); // 傳回的是集合
		System.out.println(map.size()); // 傳回所有”鍵-單個值映射”的個數,而非不同鍵的個數
		System.out.println(map.keySet().size()); // 傳回不同key的個數
		Map<String, Collection<Integer>> mapView = map.asMap();
		System.out.println(mapView);
	}
}
      
{a=[1, 2, 3], b=[1, 2]}
[1, 2, 3]
5
2
{a=[1, 2, 3], b=[1, 2]}
      
BiMap
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;

public class BitMapDemo {

	public static void main(String[] args) {
		BiMap<String, String> biMap = HashBiMap.create();
		biMap.put("sina", "sina.com");
		biMap.put("qq", "qq.com");
		biMap.put("sina", "sina.cn"); // 會覆寫原來的value
		/*
		 * 在BiMap中,如果你想把鍵映射到已經存在的值,會抛出IllegalArgumentException異常
		 * 如果對特定值,你想要強制替換它的鍵,請使用 BiMap.forcePut(key, value)
		 */
		// 抛出異常java.lang.IllegalArgumentException: value already present: qq.com
		//biMap.put("tecent", "qq.com"); 
		biMap.forcePut("tecent", "qq.com"); // 強制替換key
		System.out.println(biMap);
		System.out.println(biMap.inverse()); // 翻轉value-key
		System.out.println(biMap.inverse().get("sina.cn")); // 通過value找key
		System.out.println(biMap.inverse().inverse() == biMap); // true

	}

}
      
{sina=sina.cn, tecent=qq.com}
{sina.cn=sina, qq.com=tecent}
sina
true
      
Table

Table它有兩個支援所有類型的鍵:”行”和”列”。

import java.util.Set;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;

public class TableDemo {

	public static void main(String[] args) {
		// 記錄學生在某門課上的成績
		Table<String, String, Integer> table = HashBasedTable.create();
		table.put("jack", "java", 100);
		table.put("jack", "c", 90);
		table.put("mike", "java", 93);
		table.put("mike", "c", 100);
		Set<Table.Cell<String, String, Integer>> cells = table.cellSet();
		for (Table.Cell<String, String, Integer> cell : cells) {
			System.out.println(cell.getRowKey() + " " + cell.getColumnKey() + " " + cell.getValue());
		}
		System.out.println("----------------------");
		System.out.println(table.row("jack"));
		System.out.println(table);
		System.out.println(table.rowKeySet());
		System.out.println(table.columnKeySet());
		System.out.println(table.values());
	}

}
      
mike java 93
mike c 100
jack java 100
jack c 90
----------------------
{java=100, c=90}
{mike={java=93, c=100}, jack={java=100, c=90}}
[mike, jack]
[java, c]
[93, 100, 100, 90]
      

Collections2

filter():隻保留集合中滿足特定要求的元素

import java.util.Collection;
import java.util.List;

import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;

public class FilterDemo {

	public static void main(String[] args) {
		List<String> list = Lists.newArrayList("moon", "dad", "refer", "son");
		Collection<String> palindromeList = Collections2.filter(list, input -> {
			return new StringBuilder(input).reverse().toString().equals(input); // 找回文串
		});
		System.out.println(palindromeList);//palindromeList 回文,也叫做鏡文,正寫倒寫一樣,如mam
	}

}
      
[dad, refer]
      

  transform():類型轉換

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Set;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets;

public class TransformDemo {

	public static void main(String[] args) {
		Set<Long> times = Sets.newHashSet();
		times.add(91299990701L);
		times.add(9320001010L);
		times.add(9920170621L);
		Collection<String> timeStrCol = Collections2.transform(times, new Function<Long, String>() {
			
			@Override
			public String apply( Long input) {
				return new SimpleDateFormat("yyyy-MM-dd").format(input);
			}
		});
		System.out.println(timeStrCol);
	}

}
      
[1970-04-19, 1970-04-26, 1972-11-23]
      

  多個Function組合

import java.util.Collection;
import java.util.List;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;

public class TransformDemo2 {

	public static void main(String[] args) {
		List<String> list = Lists.newArrayList("abcde", "good", "happiness");
		// 確定容器中的字元串長度不超過5
		Function<String, String> f1 = new Function<String, String>() {
			
			@Override
			public String apply( String input) {
				return input.length() > 5 ? input.substring(0, 5) : input;
			}
		};
		// 轉成大寫
		Function<String, String> f2 = new Function<String, String>() {
			
			@Override
			public String apply( String input) {
				return input.toUpperCase();
			}
		};
		Function<String, String> function = Functions.compose(f1, f2);
		Collection<String> results = Collections2.transform(list, function);
		System.out.println(results);
	}

}
      
[ABCDE, GOOD, HAPPI]
      

集合操作:交集、差集、并集

import java.util.Set;

import com.google.common.collect.Sets;

public class CollectionsDemo {

	public static void main(String[] args) {
		Set<Integer> set1 = Sets.newHashSet(1, 2, 3, 4, 5);
		Set<Integer> set2 = Sets.newHashSet(3, 4, 5, 6);
		Sets.SetView<Integer> inter = Sets.intersection(set1, set2); // 交集
		System.out.println(inter);
		Sets.SetView<Integer> diff = Sets.difference(set1, set2); // 差集,在A中不在B中
		System.out.println(diff);
		Sets.SetView<Integer> union = Sets.union(set1, set2); // 并集
		System.out.println(union);
	}

}
      
[3, 4, 5]
[1, 2]
[1, 2, 3, 4, 5, 6]