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
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]