Guava(四)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34231010/article/details/82530368

【强大的集合工具】
    之前的章节中不少次提到了Lists集合工具,通过 Lists.newArrayList(E… elements) 可以很方便的构建ArrayList集合去使用。除了List,Guava对所有的集合类型都有对应的封装,包括JDK没有的新集合类型,并且构造器支持多种类型的参数传递,光这一点就很强大了!

集合 来源 Guava工具类
Collection JDK Collections2(不要和java.util.Collections混淆)
List JDK Lists
Set JDK Sets
SortedSet JDK Sets
Map JDK Maps
SortedMap JDK Maps
Queue JDK Queues
Multiset Guava Multisets
Multimap Guava Multimaps
BiMap Guava Maps
Table Guava Tables

一、集合工具
1.Lists

List<Integer> list1 = Lists.newArrayList(0, 2, 5);
List<Integer> list2 = Lists.newArrayList(3, 4);
// 以指定大小分割list
System.out.println(Lists.partition(list1, 2));             // [[0, 2], [5]]
// list反转
System.out.println(Lists.reverse(list1));                  // [5, 2, 0]
// 返回字符串的不可变列表
System.out.println(Lists.charactersOf("123"));             // [1, 2, 3]
// 计算多个list的笛卡尔积
System.out.println(Lists.cartesianProduct(list1, list2));  // [[0, 3], [0, 4], [2, 3], [2, 4], [5, 3], [5, 4]]

2.Sets

Set<String> set1 = Sets.newHashSet("1", "2", "3", "4", "2", "3");  // [1, 2, 3, 4]
Set<String> set2 = Sets.newHashSet("3", "4", "5", "6", "6");       // [3, 4, 5, 6]
// 计算两set的合集
System.out.println(Sets.intersection(set1, set2));          //  [3, 4]
// 计算两set的差集
System.out.println(Sets.difference(set1, set2));            //  [1, 2]
// 计算对称差集
System.out.println(Sets.symmetricDifference(set1, set2));   //  [1, 2, 5, 6]
// 计算并集
System.out.println(Sets.union(set1, set2));                 //  [1, 2, 3, 4, 5, 6]
// 计算所有子集
System.out.println(Sets.powerSet(set1));                    //  powerSet({1=0, 2=1, 3=2, 4=3})
System.out.println(Sets.newHashSet(Sets.powerSet(set1)));   //  [[], [1, 2], [1, 3], [2, 3], [1, 4], [2, 4], [3, 4], [1, 2, 3, 4], [1], [2], [3], [4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
// 计算笛卡尔积方法见 Lists

集合运算返回 Sets.SetView 的实例,可通过 immutableCopy() 变为不可变集合,读取效率更高。

3.Maps

Map<Integer, String> map1 = ImmutableMap.of(1, "a", 2, "b", 3, "a");
Map<Integer, String> map2 = ImmutableMap.of(2, "b", 3, "c", 4, "d");
MapDifference<Integer, String> difference = Maps.difference(map1, map2);
// 键只存在左边的映射
System.out.println(difference.entriesOnlyOnLeft());    //  {1=a}
// 键只存在右边的映射
System.out.println(difference.entriesOnlyOnRight());   //  {4=d}
// 左、右键值对都相同的映射
System.out.println(difference.entriesInCommon());      //  {2=b}
// 键相同但值不同的映射项
System.out.println(difference.entriesDiffering());     //  {3=(a, c)}
// 左、右键值对是否全部相同
System.out.println(difference.areEqual());             //  false

4.Multisets

Multiset<String> multiset1 = HashMultiset.create(Lists.newArrayList("b", "b", "a"));                 //  [a, b x 2]
Multiset<String> multiset2 = HashMultiset.create(Lists.newArrayList("b", "b", "b", "b", "b", "a"));  //  [a, b x 5]
// multiset1中是否包含所有multiset2中的元素
System.out.println(multiset1.containsAll(multiset2));                         //  true
// 对于任意o,若 multiset1.count(o) >= multiset2.count(o),返回true
System.out.println(Multisets.containsOccurrences(multiset1, multiset2));      //  false
// 计算multiset1和multiset2所有元素总和
System.out.println(Multisets.sum(multiset1, multiset2));                      //  [a x 2, b x 7]
// 将元素按次数降序排序,返回不可变集合
System.out.println(Multisets.copyHighestCountFirst(multiset1));               //  [b x 2, a]
// 对multiset1中的重复元素,仅在multiset2中删除相同个数
Multisets.removeOccurrences(multiset2, multiset1);
System.out.println(multiset2);    //  [b x 3]
// 修改multiset2,保证任意o满足 multiset2.count(o) <= multiset1.count(o)
Multisets.retainOccurrences(multiset2, multiset1);
System.out.println(multiset2);    //  [b x 2]

Multiset同样支持Sets中的部分集合操作。

5.Multimaps

// forMap() 与 invertFrom()
Map<Integer, String> map = ImmutableMap.of(1, "a", 2, "b", 3, "a");
System.out.println(map);       //  {1=a, 2=b, 3=a}
HashMultimap<String, Integer> multimap = Multimaps.invertFrom(Multimaps.forMap(map), HashMultimap.create());
System.out.println(multimap);  //  {a=[1, 3], b=[2]}

forMap将map包装为SetMultimap,invertFrom对Multimaps的键和值进行反转。

6.Tables

Table<String, String, Integer> hashTable = HashBasedTable.create();
hashTable.put("0", "0", 0);  hashTable.put("0", "1", 1);
hashTable.put("1", "0", 2);  hashTable.put("1", "1", 3);
hashTable.put("2", "0", 2);  hashTable.put("2", "1", 3);
System.out.println(hashTable.cellSet());                       //  [(0,0)=0, (0,1)=1, (1,0)=2, (1,1)=3, (2,0)=2, (2,1)=3]
System.out.println(Tables.transpose(hashTable).cellSet());     //  [(0,0)=0, (1,0)=1, (0,1)=2, (1,1)=3, (0,2)=2, (1,2)=3]

transpose()方法能够将 Table<R, C, V> 转为 Table<C, R, V>。用于有向图的反转。

二、 Iterables
Guava提供的工具方法更偏向于接受Iterable而不是Collection类型。因此,很多你期望的支持所有集合的操作都在Iterables类中。大多数Iterables方法有一个在Iterators类中的对应版本,用来处理Iterator。

List<Integer> list1 = Lists.newArrayList(2, 2, 5, 7, 1);
List<Integer> list2 = Lists.newArrayList(2, 5, 1, 7);
// 返回iterable中第一个元素,不存在返回默认值-1
System.out.println(Iterables.getFirst(list2, -1));          //  2
// 返回iterable中最后一个元素,不存在抛出NoSuchElementException
System.out.println(Iterables.getLast(list2));               //  7
// 判断iterable中是否包含元素
System.out.println(Iterables.contains(list2, 3));           //  false
System.out.println(Iterables.elementsEqual(list1, list2));  //  false
System.out.println(Iterables.concat(list1, list2));         //  [2, 2, 5, 7, 1, 2, 5, 1, 7]
System.out.println(Iterables.frequency(list1, 2));          //  2
System.out.println(Iterables.limit(list1, 3));              //  [2, 2, 5]
System.out.println(Iterables.partition(list1, 4));          //  [[2, 2, 5, 7], [1]]
System.out.println(Iterables.paddedPartition(list1, 4));    //  [[2, 2, 5, 7], [1, null, null, null]]
System.out.println(Iterables.skip(list1, 2));               //  [5, 7, 1]
// System.out.println(Iterables.getOnlyElement(list2));     //  java.lang.IllegalArgumentException: expected one element but was: <2, 5, 1, 7>

三、集合扩展工具
1.Forwarding装饰器
    Forwarding装饰器提供了一个抽象方法:delegate(),使用者通过创建ForwardingXXX的子类并重写delegate()方法增加装饰功能。
以ForwardingList为例,delegate()的返回类型为List<E>,方法实现为:

public void add(int index, E element) {
    delegate().add(index, element);
}

因此,当想要实现其他功能时,我们可以重写add()方法来达到想要的功能。

2.PeekingIterator
    通过 Iterators.peekingIterator(iterator) 包装成PeekingIterator,该接口提供了一个peek()方法,能够提前“偷看”到下一次调用next()返回的元素,但需要注意的是当便利到最后一个元素时,使用peek()会抛出NoSuchElementException异常。

3.AbstractIterator
    抽象类AbstractIterator可以实现自定义的Iterator,通过重写computeNext()方法来实现迭代。由于该抽象类继承了UnmodifiableIterator,因此不支持remove()操作。

猜你喜欢

转载自blog.csdn.net/qq_34231010/article/details/82530368