Guava——New Collection Types

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 counts = new HashMap();
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 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 without an ordering constraint: ordering does not matter.
  • This is like a Map, 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。包含的Entry支持使用getElement()和getCount()
    setCount(E element ,int count): 设定某一个元素的重复次数
    setCount(E element,int oldCount,int newCount): 将符合原有重复个数的元素修改为新的重复次数
    retainAll(Collection c) : 保留出现在给定集合参数的所有的元素
    removeAll(Collectionc) : 去除出现给给定集合参数的所有的元素

Implementations

Guava——New Collection Types_第1张图片

Multimap

implemented a Map> or Map>,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 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 valueList = (List) multimap.get("key");
        System.out.println("valueList = " + valueList);

        valueList = (List) multimap.get("aa");
        System.out.println("valueList = " + valueList);

        // 转为map
        Map> map = multimap.asMap();
        List list2 = (List)map.get("key");
        // key 不存在,得到null
        System.out.println("list2 = " + list2);

        valueList = (List) map.get("aa");
        System.out.println("valueList = " + valueList);

        Collection> entries = multimap.entries();
        System.out.println("entries = " + entries);

View

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

尽管Multimap的实现用到了Map,但Multimap不是Map>。因为两者有明显区别:
  1.Multimap.get(key)一定返回一个非null的集合。但这不表示Multimap使用了内存来关联这些键,相反,返回的集合只是个允许添加元素的视图。
  2.如果你喜欢像Map那样当不存在键的时候要返回null,而不是Multimap那样返回空集合的话,可以用asMap()返回的视图来得到Map>。(这种情况下,你得把返回的Collection强转型为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>,具体的实现如下:

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>!(尤其是有些Multimap的实现为了最小话开销,使用了自定义的hash table)

BiMap

troditional

Map nameToId = Maps.newHashMap();
Map 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 is a Map that

  • allows you to view the "inverse" BiMap with inverse()
  • ensures that values are unique, making values() a Set
HashBiMap hashBiMap = HashBiMap.create();
        hashBiMap.put("a1", 1);
        hashBiMap.put("a2", 2);
        hashBiMap.put("a3", 3);
        System.out.println("hashBiMap = " + hashBiMap);

        BiMap 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对象。
Guava——New Collection Types_第2张图片

Note: BiMap utilities like synchronizedBiMap live in Maps.

Table

        Table 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 row0 = table.row(0);
        System.out.println("row 0 = " + row0);
        
        Map colum0 = table.column(0);
        System.out.println("table.column(0) = " + colum0);
        
        Map> rowMap = table.rowMap();
        System.out.println("rowMap.get(0).get(0) = " + rowMap.get(0).get(0));

        Map> columnMap = table.columnMap();
        System.out.println("columnMap.get(0).get(0) = " + columnMap.get(0).get(0));

Implements

Table有以下实现:
  HashBasedTable:基于HashMap>的实现。
  TreeBasedTable:基于TreeMap>的实现。
  ImmutableTable:基于ImmutableMap>的实现。(注意,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 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 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)