Guava引入了很多JDK没有的、但我们发现明显有用的新集合类型。
Multiset
统计一个词在文档中出现了多少次,传统的做法是这样的:(这里举个简单的传统方法,下面不在说明)
@Test public void test20(){ List<String> words = new ArrayList<String>(); Map<String, Integer> counts = new HashMap<String, Integer>(); for (String word : words) { Integer count = counts.get(word); if (count == null) { counts.put(word, 1); } else { counts.put(word, count + 1); } } }
这种写法很笨拙,也容易出错,并且不支持同时收集多种统计信息,如总词数。我们可以做的更好。
Guava提供了一个新集合类型 Multiset,它可以多次添加相等的元素。很好使用例如:
@Test public void test10() { Multiset<String> multiset1 = HashMultiset.create(); multiset1.add("a", 2); multiset1.add("b"); multiset1.add("b"); int count = multiset1.count("b"); System.out.println(count); Multiset<String> multiset2 = HashMultiset.create(); multiset2.add("a", 5); multiset1.containsAll(multiset2); // 返回true;因为包含了所有不重复元素, // 虽然multiset1实际上包含2个"a",而multiset2包含5个"a" Multisets.containsOccurrences(multiset1, multiset2); // returns false // multiset2.removeOccurrences(multiset1); // multiset2 现在包含3个"a" multiset2.removeAll(multiset1);// multiset2移除所有"a",虽然multiset1只有2个"a" multiset2.isEmpty(); // returns true }
下面我用测试用例说明一下guava集合类型的新功能
// 在JDK的基础上增加了map的功能 @Test public void test8() { Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3, "d", 4); Map<String, Integer> right = ImmutableMap.of("a", 2, "b", 2, "c", 3); MapDifference<String, Integer> diff = Maps.difference(left, right); System.out.println(diff.entriesDiffering());// 键相同 但是值不相同的映射项 System.out.println(diff.entriesInCommon());// 键值都相同的映射项 System.out.println(diff.entriesOnlyOnLeft()); // {"a" => 1} System.out.println(diff.entriesOnlyOnRight()); // {"d" => 5} } // 一个非常有用的集合,取得交集,并集,第一个集合中有的数据第二个集合中没有的数据等方法 @Test public void test7() { List<String> list = Lists.newArrayList(); // list. Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight"); Set<String> primes = ImmutableSet.of("two", "three", "five", "seven"); // primes.add("hello"); SetView<String> intersection = Sets.intersection(primes, wordsWithPrimeLength); // intersection包含"two", "three", "seven" ImmutableSet<String> immutableCopy = intersection.immutableCopy();// 可以使用交集,但不可变拷贝的读取效率更高 // Sets.difference(set1, set2); SetView<String> difference = Sets.difference(primes, wordsWithPrimeLength); SetView<String> union = Sets.union(primes, wordsWithPrimeLength); System.out.println(union); System.out.println(difference); System.out.println(immutableCopy); Set<String> animals = ImmutableSet.of("gerbil", "hamster"); Set<String> fruits = ImmutableSet.of("apple", "orange", "banana"); Set<List<String>> product = Sets.cartesianProduct(animals, fruits); // {{"gerbil", "apple"}, {"gerbil", "orange"}, {"gerbil", "banana"}, // {"hamster", "apple"}, {"hamster", "orange"}, {"hamster", "banana"}} Set<Set<String>> animalSets = Sets.powerSet(animals); // {{}, {"gerbil"}, {"hamster"}, {"gerbil", "hamster"}} } // 比较器,能够比较数据大小按照自己的要求 @Test public void test6() { Ordering<String> order = new Ordering<String>() { @Override public int compare(String left, String right) { return Ints.compare(left.length(), right.length()); } }; order.compare("a", "b"); String min = order.min("a", "b1", "c11", "d111"); System.out.println(min); } @Test public void test11() { Multiset<String> multiset = HashMultiset.create(); multiset.add("a", 3); multiset.add("b", 5); multiset.add("c", 1); multiset.add("a"); multiset.add("a"); multiset.add("a"); multiset.add("a"); ImmutableMultiset<String> highestCountFirst = Multisets.copyHighestCountFirst(multiset); System.out.println(highestCountFirst.elementSet()); // highestCountFirst,包括它的entrySet和elementSet,按{"b", "a", "c"}排列元素 } // 根据特征进行筛选集合中的数据 @Test public void test12() { ImmutableSet<String> digits = ImmutableSet.of("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"); Function<String, Integer> lengthFunction = new Function<String, Integer>() { public Integer apply(String string) { return string.length(); } }; ImmutableListMultimap<Integer, String> digitsByLength = Multimaps.index(digits, lengthFunction); System.out.println(digitsByLength); /* * digitsByLength maps: 3 => {"one", "two", "six"} 4 => {"zero", "four", * "five", "nine"} 5 => {"three", "seven", "eight"} */ } @Test public void test13() { ArrayListMultimap<String, Integer> multimap = ArrayListMultimap.create(); multimap.putAll("b", Ints.asList(2, 4, 6)); multimap.putAll("a", Ints.asList(4, 2, 1)); multimap.putAll("c", Ints.asList(2, 5, 3)); TreeMultimap<Integer, String> create = TreeMultimap.create(); TreeMultimap<Integer, String> inverse = Multimaps.invertFrom(multimap, create); System.out.println(inverse); // 注意我们选择的实现,因为选了TreeMultimap,得到的反转结果是有序的 /* * inverse maps: 1 => {"a"} 2 => {"a", "b", "c"} 3 => {"c"} 4 => {"a", * "b"} 5 => {"c"} 6 => {"b"} */ } //map中的key和value值进行反转 @Test public void test14() { Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 1, "c", 2); SetMultimap<String, Integer> multimap = Multimaps.forMap(map); // multimap:["a" => {1}, "b" => {1}, "c" => {2}] System.out.println(multimap); HashMultimap<Integer, String> dest = HashMultimap.create(); Multimap<Integer, String> inverse = Multimaps.invertFrom(multimap, dest); System.out.println(inverse); // inverse:[1 => {"a","b"}, 2 => {"c"}] /* * Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 1, "c", 2); * SetMultimap<String, Integer> multimap = Multimaps.forMap(map); */ // multimap:["a" => {1}, "b" => {1}, "c" => {2}] // Multimap<Integer, String> inverse = Multimaps.invertFrom(multimap, // Multimap<Integer, String>.create()); // inverse:[1 => {"a","b"}, 2 => {"c"}] } // 多功能的map @Test public void test15() { ArrayListMultimap<String, Integer> multimap = ArrayListMultimap.create(); multimap.put("a", 1); multimap.put("a", 2); System.out.println(multimap); Map<String, Integer> map = new HashMap<String, Integer>(); map.put("a", 1); map.put("a", 2); System.out.println(map); Map<String, Integer> tree = new TreeMap<String, Integer>(); tree.put("a", 1); tree.put("a", 2); System.out.println(tree); Map<String, Integer> table = new Hashtable<String, Integer>(); table.put("a", 1); table.put("a", 2); System.out.println(table); /** * {a=[1, 2]} {a=2} {a=2} {a=2} */ }