• Guava 3: 集合Collections


    一、引子

    Guava 对JDK集合的拓展,是最成熟且最受欢迎的部分。本文属于Guava的核心,需要仔细看。

    二、Guava 集合

    2.1 Immutable Collections不可变集合

    1.作用

    用不变的集合进行防御性编程和性能提升。

    2.简单使用

     1 package guava.collect;
     2 
     3 import com.google.common.collect.ImmutableSet;
     4 
     5 /**
     6  * @author denny
     7  * @Description 不可变集合
     8  * @date 2018/7/26 下午3:16
     9  */
    10 public class ImmutableCollectionsTest {
    11     /**
    12      * 1.直接申明静态集合
    13      */
    14     public static final ImmutableSet<String> COLOR_NAMES_1 = ImmutableSet.of(
    15         "red",
    16         "orange",
    17         "yellow",
    18         "green");
    19     /**
    20      * 2.防御式copy
    21      */
    22     public static final ImmutableSet<String> COLOR_NAMES_2 = ImmutableSet.copyOf(COLOR_NAMES_1);
    23 
    24     /**
    25      * 3.builder建造者模式
    26      */
    27     public static final ImmutableSet<String> COLOR_NAMES_3 = ImmutableSet.<String>builder().addAll(COLOR_NAMES_2).add("blue").build();
    28 
    29 
    30     public static void main(String[] args) {
    31         System.out.println("of:"+COLOR_NAMES_1);
    32         System.out.println("防御式copy:"+COLOR_NAMES_2);
    33         System.out.println("建造者模式:"+COLOR_NAMES_3);
    34         System.out.println("转换成list:"+COLOR_NAMES_3.asList());
    35     }
    36 }

    打印:

    of:[red, orange, yellow, green]
    防御式copy:[red, orange, yellow, green]
    建造者模式:[red, orange, yellow, green, blue]
    转换成list:[red, orange, yellow, green, blue]

    2.2 新集合类型

    1.作用

    提供multisets, multimaps, tables, bidirectional maps等,方便各种使用场景。

    2.简单使用

    很多类,我们只举例分析multiset、multimap接口,其它的就在测试类中体现。

    multiset接口

    继承自JDK:java.util.Collection接口,支持多次添加相同的元素,且无序。

    当把Multiset看成普通的Collection时,它表现得就像无序的ArrayList:

    • add(E)添加单个给定元素
    • iterator()返回一个迭代器,包含Multiset的所有元素(包括重复的元素)
    • size()返回所有元素的总个数(包括重复的元素)

    当把Multiset看作Map<E, Integer>时,它也提供了符合性能期望的查询操作:

    • count(Object)返回给定元素的计数。HashMultiset.count的复杂度为O(1),TreeMultiset.count的复杂度为O(log n)。
    • entrySet()返回Set<Multiset.Entry<E>>,和Map的entrySet类似。
    • elementSet()返回所有不重复元素的Set<E>,和Map的keySet()类似。
    • 所有Multiset实现的内存消耗随着不重复元素的个数线性增长。 

    multimap接口

    • 支持一个key映射多个value: k1-v1, k1-v2。
    • 提供asMap()视图,返回Map<K, Collection<V>>,即k1->v集合(v1,v2)

    各种multimap实现类如下:

    测试类如下:

     1 package guava.collect;
     2 
     3 import com.google.common.collect.BiMap;
     4 import com.google.common.collect.ClassToInstanceMap;
     5 import com.google.common.collect.HashBasedTable;
     6 import com.google.common.collect.HashBiMap;
     7 import com.google.common.collect.HashMultimap;
     8 import com.google.common.collect.HashMultiset;
     9 import com.google.common.collect.Lists;
    10 import com.google.common.collect.Multimap;
    11 import com.google.common.collect.Multiset;
    12 import com.google.common.collect.MutableClassToInstanceMap;
    13 import com.google.common.collect.Range;
    14 import com.google.common.collect.RangeMap;
    15 import com.google.common.collect.RangeSet;
    16 import com.google.common.collect.Table;
    17 import com.google.common.collect.TreeRangeMap;
    18 import com.google.common.collect.TreeRangeSet;
    19 
    20 /**
    21  * @author denny
    22  * @Description 多重集合测试类
    23  * @date 2018/7/26 下午6:29
    24  */
    25 public class MultiCollectionsTest {
    26     public static void main(String[] args) {
    27 
    28         System.out.println("====1.Multiset=======");
    29         /** 1.Multiset 专用于统计元素出现次数 */
    30         Multiset<String> wordsMultiset = HashMultiset.create();
    31         // 添加元素
    32         wordsMultiset.addAll(Lists.newArrayList("a", "b", "c", "a", "b", "a"));
    33         //遍历不同元素集合,打印次数
    34         wordsMultiset.elementSet().forEach(e -> System.out.println(e + ":" + wordsMultiset.count(e)));
    35 
    36         System.out.println("====2.Multimap=======");
    37         /** 2.Multimap 1个key多value映射 */
    38         Multimap<String, Integer> multimap = HashMultimap.create();
    39         multimap.put("a", 1);
    40         multimap.put("b", 2);
    41         multimap.put("c", 3);
    42         multimap.put("a", 4);
    43         System.out.println("键-值集合映射:");
    44         // 键-值集合映射:asMap()转成map(key,Collection<E>),再调用map相关方法,打印
    45         multimap.asMap().entrySet().forEach(e -> System.out.println(e.getKey() + ":" + e.getValue()));
    46         System.out.println("键-单个值映射:");
    47         // 键-单个值映射:包括重复键
    48         multimap.entries().forEach(e -> System.out.println(e.getKey() + ":" + e.getValue()));
    49 
    50         System.out.println("====3.BiMap=======");
    51         /** 3.BiMap 键值反转 */
    52         BiMap<String, Integer> biMap = HashBiMap.create();
    53         biMap.put("a", 1);
    54         biMap.put("b", 2);
    55         System.out.println("键值对" + biMap);
    56         System.out.println("键值反转:" + biMap.inverse());
    57 
    58         System.out.println("====4.Table=======");
    59         /** 4.Table <R rowKey, C columnKey, V value> */
    60         Table<String, String, Integer> table = HashBasedTable.create();
    61         table.put("a", "b", 1);
    62         table.put("a", "c", 2);
    63         table.put("d", "b", 3);
    64         System.out.println(table);
    65         System.out.println("row a=" + table.row("a"));
    66         System.out.println("column b=" + table.column("b"));
    67 
    68         /** 5.ClassToInstanceMap 类、实例映射 */
    69         System.out.println("====5.ClassToInstanceMap=======");
    70         ClassToInstanceMap<Number> classToInstanceMap = MutableClassToInstanceMap.create();
    71         classToInstanceMap.putInstance(Integer.class, 1);
    72         classToInstanceMap.putInstance(Double.class, 2D);
    73         classToInstanceMap.putInstance(Long.class, 3L);
    74         System.out.println(classToInstanceMap);
    75 
    76         /** 6. RangeSet 区间运算; RangeMap 区间映射*/
    77         System.out.println("====6.RangeSet、RangeMap=======");
    78         RangeSet<Integer> rangeSet = TreeRangeSet.create();
    79         // [1,10]
    80         rangeSet.add(Range.closed(1,10));
    81         // 不相连区间  [1,10] [11,15)
    82         rangeSet.add(Range.closedOpen(11,15));
    83         // 相连合并[11,15)+[15,20)=[11,20),最终结果:[1,10] [11,20)
    84         rangeSet.add(Range.closedOpen(15,20));
    85         // [1,10]-(5,10)=[1,5][10,10] ,最终结果:[1,5][10,10][11,20]
    86         rangeSet.remove(Range.open(5,10));
    87         System.out.println("rangeSet="+rangeSet);
    88         RangeMap<Integer,String> rangeMap = TreeRangeMap.create();
    89         rangeMap.put(Range.closed(1,10),"区间1");
    90         // 不处理任何key的区间交集,只是简单映射
    91         rangeMap.put(Range.closed(5,20),"区间2");
    92         System.out.println("rangeMap="+rangeMap);
    93     }
    94 }

    打印日志如下:

     1 ====1.Multiset=======
     2 a:3
     3 b:2
     4 c:1
     5 ====2.Multimap=======
     6 键-值集合映射:
     7 a:[4, 1]
     8 b:[2]
     9 c:[3]
    10 键-单个值映射:
    11 a:4
    12 a:1
    13 b:2
    14 c:3
    15 ====3.BiMap=======
    16 键值对{a=1, b=2}
    17 键值反转:{1=a, 2=b}
    18 ====4.Table=======
    19 {a={b=1, c=2}, d={b=3}}
    20 row a={b=1, c=2}
    21 column b={a=1, d=3}
    22 ====5.ClassToInstanceMap=======
    23 {class java.lang.Integer=1, class java.lang.Double=2.0, class java.lang.Long=3}
    24 ====6.RangeSet、RangeMap=======
    25 rangeSet=[[1..5], [10..10], [11..20)]
    26 rangeMap=[[1..5)=区间1, [5..20]=区间2]

    2.3 强大的集合工具类

    1.作用

    提供java.util.Collections中没有的集合工具

    2.简单使用

    集合接口、所属关系、Guava对应的工具映射关系如下表:

     1 package guava.collect;
     2 
     3 import com.google.common.base.Function;
     4 import com.google.common.collect.ImmutableMap;
     5 import com.google.common.collect.ImmutableSet;
     6 import com.google.common.collect.Iterables;
     7 import com.google.common.collect.Lists;
     8 import com.google.common.collect.MapDifference;
     9 import com.google.common.collect.Maps;
    10 import com.google.common.collect.Sets;
    11 import com.google.common.primitives.Ints;
    12 
    13 import java.util.List;
    14 import java.util.Map;
    15 import java.util.Set;
    16 
    17 /**
    18  * @Description 
    19  * @author denny
    20  * @date 2018/7/27 下午2:46
    21  */
    22 public class UtilityClassesTest {
    23 
    24     public static void main(String[] args) {
    25         /** 1.Iterables 迭代器工具集 */
    26         System.out.println("=========Iterables=========");
    27         Iterable<Integer> concate = Iterables.concat(Ints.asList(1,2,3),Ints.asList(2,3,4));
    28         System.out.println("链接:"+concate);
    29         System.out.println("元素2出现次数:"+Iterables.frequency(concate,2));
    30         System.out.println("按照指定长度拆分集合:"+Iterables.partition(concate,2));
    31         System.out.println("取第一个元素,为空返回默认:"+Iterables.getFirst(concate,99));
    32         System.out.println("取最后元素:"+Iterables.getLast(concate));
    33 
    34         /** 2.Lists 列表工具集 */
    35         System.out.println("=========Lists=========");
    36         List list = Lists.newArrayList(1,2,3,4,5);
    37         System.out.println("反转:"+Lists.reverse(list));
    38         System.out.println("拆分:"+Lists.partition(list,2));
    39 
    40         /** 3.Sets 集合工具集 */
    41         System.out.println("=========Sets=========");
    42         Set<Integer> set1 = Sets.newHashSet(1,2,3);
    43         Set<Integer> set2 = Sets.newHashSet(3,4,5);
    44         System.out.println("并集:"+Sets.union(set1,set2));
    45         System.out.println("交集:"+Sets.intersection(set1,set2));
    46         System.out.println("差集(set1有set2没有):"+Sets.difference(set1,set2));
    47         System.out.println("并集-交集:"+Sets.symmetricDifference(set1,set2));
    48         System.out.println("笛卡尔积:"+Sets.cartesianProduct(set1,set2));
    49         System.out.println("全部子集:");
    50         Sets.powerSet(set1).forEach(System.out::println);
    51 
    52         /** 4.Maps 集合工具集 */
    53         System.out.println("=========Maps=========");
    54         Map<String,Integer> map1 = Maps.newHashMap();
    55         map1.put("a",1);
    56         map1.put("b",2);
    57         map1.put("d",5);
    58         Map<String,Integer> map2 = Maps.newHashMap();
    59         map2.put("a",1);
    60         map2.put("b",3);
    61         map2.put("c",4);
    62         MapDifference<String,Integer> mapDifference = Maps.difference(map1,map2);
    63         System.out.println("共有的:"+mapDifference.entriesInCommon());
    64         System.out.println("key相同,value不同:"+mapDifference.entriesDiffering());
    65         System.out.println("左边独有的:"+mapDifference.entriesOnlyOnLeft());
    66         System.out.println("右边独有的:"+mapDifference.entriesOnlyOnRight());
    67         // 字符串长度
    68         ImmutableSet<String> allColors = ImmutableSet.of("red", "green", "blue");
    69         ImmutableMap<Integer,String> immutableMap = Maps.uniqueIndex(allColors, input -> input.length());
    70         System.out.println("字符串长度作为唯一key:"+immutableMap);
    71     }
    72 }

    打印结果如下:

    =========Iterables=========
    链接:[1, 2, 3, 2, 3, 4]
    元素2出现次数:2
    按照指定长度拆分集合:[[1, 2], [3, 2], [3, 4]]
    取第一个元素,为空返回默认:1
    取最后元素:4
    =========Lists=========
    反转:[5, 4, 3, 2, 1]
    拆分:[[1, 2], [3, 4], [5]]
    =========Sets=========
    并集:[1, 2, 3, 4, 5]
    交集:[3]
    差集(set1有set2没有):[1, 2]
    并集-交集:[1, 2, 4, 5]
    笛卡尔积:[[1, 3], [1, 4], [1, 5], [2, 3], [2, 4], [2, 5], [3, 3], [3, 4], [3, 5]]
    全部子集:
    []
    [1]
    [2]
    [1, 2]
    [3]
    [1, 3]
    [2, 3]
    [1, 2, 3]
    =========Maps=========
    共有的:{a=1}
    key相同,value不同:{b=(2, 3)}
    左边独有的:{d=5}
    右边独有的:{c=4}
    字符串长度作为唯一key{3=red, 5=green, 4=blue}

    2.4 扩展工具类

    1.作用

    让实现和扩展集合类变得更容易,比如创建Collection的装饰器,或实现迭代器

    2.简单使用

    不提供。guava本生就是JDK拓展,自己再去拓展,你再逗我吗...

    三、总结

     本文根据官方文档简单理解并使用了Guava Collect包下的类,主要包含Immutable Collections不可变集合、新集合类型、集合工具类、拓展工具类。其中前三个建议使用,最后一个拓展工具类就算了吧。

  • 相关阅读:
    从运维角度看中大型网站架构的演变之路
    <经验杂谈>Mysql中字符串处理的几种处理方法concat、concat_ws、group_concat
    <经验杂谈>C#使用AES加密解密的简单介绍
    <经验杂谈>C#对CA证书加密解密的简单介绍
    C#实现HttpUtility.UrlEncode输出大写字母
    <微信应用开发系列>定时刷新AccessToken
    <经验杂谈>C#/.Net字符串操作方法小结
    <经验杂谈>查询表结构的SQL语句
    如何在.Net中使用Redis
    ASP.NET MVC进阶之路:深入理解Controller激活机制并使用Ioc容器创建对象
  • 原文地址:https://www.cnblogs.com/dennyzhangdd/p/9378978.html
Copyright © 2020-2023  润新知