美文网首页
Guava——New Collection Types

Guava——New Collection Types

作者: jiangmo | 来源:发表于2018-04-06 13:28 被阅读28次

    Guava introduces a number of new collection types that are not in the JDK, but that we have found to be broadly useful. These are all designed to coexist happily with the JDK collections framework, without shoehorning things into the JDK collection abstractions.

    All

    Multiset
    SortedMultiset
    Multimap
    ListMultimap
    SetMultimap
    BiMap
    ClassToInstanceMap
    Table

    Multiset

    troditional

    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

    // List 允许重复,有顺序
            // Set 不允许重复、无顺序
            // MultiSet 允许重复,不保证顺序
            String strWorld="wer|dfd|dd|dfd|dda|de|dr";
            String[] words = strWorld.split("\\|");
            Multiset<String> multiset = HashMultiset.create();
            for (String word : words) {
                multiset.add(word);
            }
    
            for(String key:multiset.elementSet()){
                System.out.println(key+" count:"+multiset.count(key));
            }
    

    notice

    Guava provides a new collection type, Multiset, which supports adding multiples of elements. Wikipedia defines a multiset, in mathematics, as “a generalization of the notion of set in which members are allowed to appear more than once...In multisets, as in sets and in contrast to tuples, the order of elements is irrelevant: The multisets {a, a, b} and {a, b, a} are equal.”

    There are two main ways of looking at this:

    • This is like an ArrayList<E> without an ordering constraint: ordering does not matter.
    • This is like a Map<E, Integer>, with elements and counts.

    methods

    Multiset接口定义的接口主要有:
        add(E element) :向其中添加单个元素
        add(E element,int occurrences) : 向其中添加指定个数的元素
        count(Object element) : 返回给定参数元素的个数
        remove(E element) : 移除一个元素,其count值 会响应减少
        remove(E element,int occurrences): 移除相应个数的元素
        elementSet() : 将不同的元素放入一个Set中
        entrySet(): 类似与Map.entrySet 返回Set<Multiset.Entry>。包含的Entry支持使用getElement()和getCount()
        setCount(E element ,int count): 设定某一个元素的重复次数
        setCount(E element,int oldCount,int newCount): 将符合原有重复个数的元素修改为新的重复次数
        retainAll(Collection c) : 保留出现在给定集合参数的所有的元素
        removeAll(Collectionc) : 去除出现给给定集合参数的所有的元素

    Implementations

    Multimap

    implemented a Map<K, List<V>> or Map<K, Set<V>>,using multimap will be easy.
    You rarely use the Multimap interface directly, however; more often you'll use ListMultimap or SetMultimap, which map keys to a List or a Set respectively.

    Construction

    // 可创建1 key : n value 的map结构
    // 可创建1 key : n value 的map结构
            Multimap<String, Integer> multimap = ArrayListMultimap.create();
            for (int i = 0; i < 2; i++) {
                multimap.put("aa", i);
                multimap.put("bb", i);
            }
            // 所有value的数量
            System.out.println("multimap.size() = " + multimap.size());
            System.out.println("multimap.keys() = " + multimap.keys());
            // key不存在 会得到空集合,而不是null
            List<Integer> valueList = (List<Integer>) multimap.get("key");
            System.out.println("valueList = " + valueList);
    
            valueList = (List<Integer>) multimap.get("aa");
            System.out.println("valueList = " + valueList);
    
            // 转为map
            Map<String, Collection<Integer>> map = multimap.asMap();
            List<Integer> list2 = (List<Integer>)map.get("key");
            // key 不存在,得到null
            System.out.println("list2 = " + list2);
    
            valueList = (List<Integer>) map.get("aa");
            System.out.println("valueList = " + valueList);
    
            Collection<Map.Entry<String, Integer>> entries = multimap.entries();
            System.out.println("entries = " + entries);
    

    View

    Multimap也支持一系列强大的视图功能:
      1.asMap把自身Multimap<K, V>映射成Map<K, Collection<V>>视图。这个Map视图支持remove和修改操作,但是不支持put和putAll。严格地来讲,当你希望传入参数是不存在的key,而且你希望返回的是null而不是一个空的可修改的集合的时候就可以调用asMap().get(key)。(你可以强制转型asMap().get(key)的结果类型-对SetMultimap的结果转成Set,对ListMultimap的结果转成List型-但是直接把ListMultimap转成Map<K, List<V>>是不行的。)
      2.entries视图是把Multimap里所有的键值对以Collection<Map.Entry<K, V>>的形式展现。
      3.keySet视图是把Multimap的键集合作为视图
      4.keys视图返回的是个Multiset,这个Multiset是以不重复的键对应的个数作为视图。这个Multiset可以通过支持移除操作而不是添加操作来修改Multimap。
      5.values()视图能把Multimap里的所有值“平展”成一个Collection<V>。这个操作和Iterables.concat(multimap.asMap().values())很相似,只是它返回的是一个完整的Collection。

    尽管Multimap的实现用到了Map,但Multimap<K, V>不是Map<K, Collection<V>>。因为两者有明显区别:
      1.Multimap.get(key)一定返回一个非null的集合。但这不表示Multimap使用了内存来关联这些键,相反,返回的集合只是个允许添加元素的视图。
      2.如果你喜欢像Map那样当不存在键的时候要返回null,而不是Multimap那样返回空集合的话,可以用asMap()返回的视图来得到Map<K, Collection<V>>。(这种情况下,你得把返回的Collection<V>强转型为List或Set)。
      3.Multimap.containsKey(key)只有在这个键存在的时候才返回true。
      4.Multimap.entries()返回的是Multimap所有的键值对。但是如果需要key-collection的键值对,那就得用asMap().entries()。
      5.Multimap.size()返回的是entries的数量,而不是不重复键的数量。如果要得到不重复键的数目就得用Multimap.keySet().size()。

    Implements

    Implementation Keys 的行为类似 Values的行为类似
    ArrayListMultimap HashMap ArrayList
    HashMultimap HashMap HashSet
    LinkedListMultimap LinkedHashMap* LinkedList*
    LinkedHashMultimap LinkedHashMap LinkedHashSet
    TreeMultimap TreeMap TreeSet
    ImmutableListMultimap ImmutableMap ImmutableList
    ImmutableSetMultimap ImmutableMap ImmutableSet

    Multimap提供了丰富的实现,所以你可以用它来替代程序里的Map<K, Collection<V>>,具体的实现如下:

    Implementation Keys 的行为类似 Values的行为类似
    ArrayListMultimap HashMap ArrayList
    HashMultimap HashMap HashSet
    LinkedListMultimap LinkedHashMap* LinkedList*
    LinkedHashMultimap LinkedHashMap LinkedHashSet
    TreeMultimap TreeMap TreeSet
    ImmutableListMultimap ImmutableMap ImmutableList
    ImmutableSetMultimap ImmutableMap ImmutableSet

    以上这些实现,除了immutable的实现都支持null的键和值。

    1. LinkedListMultimap.entries()能维持迭代时的顺序。
    2. LinkedHashMultimap维持插入的顺序,以及键的插入顺序。
      要注意并不是所有的实现都正真实现了Map<K, Collection<V>>!(尤其是有些Multimap的实现为了最小话开销,使用了自定义的hash table)

    BiMap

    troditional

    Map<String, Integer> nameToId = Maps.newHashMap();
    Map<Integer, String> idToName = Maps.newHashMap();
    
    nameToId.put("Bob", 42);
    idToName.put(42, "Bob");
    // what happens if "Bob" or 42 are already present?
    // weird bugs can arise if we forget to keep these in sync...
    

    A BiMap<K, V> is a Map<K, V> that

    • allows you to view the "inverse" BiMap<V, K> with inverse()
    • ensures that values are unique, making values() a Set
    HashBiMap<String, Integer> hashBiMap = HashBiMap.create();
            hashBiMap.put("a1", 1);
            hashBiMap.put("a2", 2);
            hashBiMap.put("a3", 3);
            System.out.println("hashBiMap = " + hashBiMap);
    
            BiMap<Integer, String> inverse = hashBiMap.inverse();
            System.out.println("inverse = " + inverse);
    
            // BiMap 强制保持 1:1 关系,如果要在已有value上添加另外的key,则会抛出异常
            // 要覆盖已有value对应的entry,则可以putforce
            hashBiMap.forcePut("a4", 3);
            System.out.println("hashBiMap = " + hashBiMap);
    
    • BiMap.put(key, value) will throw an IllegalArgumentException if you attempt to map a key to an already-present value. If you wish to delete any preexisting entry with the specified value, use BiMap.forcePut(key, value) instead.
    • inverse方法会返回一个反转的BiMap,但是注意这个反转的map不是新的map对象,它实现了一种视图关联,这样你对于反转后的map的所有操作都会影响原先的map对象。

    Note: BiMap utilities like synchronizedBiMap live in Maps.

    Table

            Table<Integer, Integer, String> table = HashBasedTable.create();
            for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 2; j++) {
                    table.put(i, j, i + "-" + j);
                }
            }
            System.out.println("table = " + table);
            Map<Integer, String> row0 = table.row(0);
            System.out.println("row 0 = " + row0);
            
            Map<Integer, String> colum0 = table.column(0);
            System.out.println("table.column(0) = " + colum0);
            
            Map<Integer, Map<Integer, String>> rowMap = table.rowMap();
            System.out.println("rowMap.get(0).get(0) = " + rowMap.get(0).get(0));
    
            Map<Integer, Map<Integer, String>> columnMap = table.columnMap();
            System.out.println("columnMap.get(0).get(0) = " + columnMap.get(0).get(0));
    
    

    Implements

    Table有以下实现:
      HashBasedTable:基于HashMap<R, HashMap<C, V>>的实现。
      TreeBasedTable:基于TreeMap<R, TreeMap<C, V>>的实现。
      ImmutableTable:基于ImmutableMap<R, ImmutableMap<C, V>>的实现。(注意,ImmutableTable已对稀疏和密集集合做了优化)
      ArrayTable:ArrayTable是一个需要在构建的时候就需要定下行列的表格。这种表格由二维数组实现,这样可以在密集数据的表格的场合,提高时间和空间的效率。

    ClassToInstanceMap

    RangeSet

    A RangeSet describes a set of disconnected, nonempty ranges. When adding a range to a mutable RangeSet, any connected ranges are merged together, and empty ranges are ignored. For example:

    // range.closed [],即闭区间 ,range.closeOpen [),即右开区间
            RangeSet<Integer> rangeSet = TreeRangeSet.create();
            rangeSet.add(Range.closed(5,10));
            System.out.println("rangeSet:"+rangeSet);
            rangeSet.add(Range.closedOpen(12, 15));
            System.out.println("rangeSet:"+rangeSet);
            // 会合并
            rangeSet.add(Range.closedOpen(11, 13));
            System.out.println("rangeSet:"+rangeSet);
    
            // 会分割
            rangeSet.remove(Range.open(7,8));
            System.out.println("rangeSet:"+rangeSet);
    

    RangeMap

    RangeMap is a collection type describing a mapping from disjoint, nonempty ranges to values. Unlike RangeSet, RangeMap never "coalesces" adjacent mappings, even if adjacent ranges are mapped to the same values. For example:

    // 不会像rangeSet自动合并区间
            RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
            rangeMap.put(Range.closed(1, 5), "1-5");
            System.out.println(rangeMap.get(2));
    
            rangeMap.remove(Range.open(2,3));
            System.out.println(rangeMap);
    

    相关文章

      网友评论

          本文标题:Guava——New Collection Types

          本文链接:https://www.haomeiwen.com/subject/hlprhftx.html