guava学习笔记(集合一)

不可变对象集合的创建

  • copyOf 方法,如 ImmutableSet.copyOf(set);
  • of 方法,如 ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”,1,“b”, 2);
  • Builder 工具,如
  public static final ImmutableSet<Color> GOOGLE_COLORS =
            ImmutableSet.<Color>builder()
                .addAll(WEBSAFE_COLORS)
                .add(new Color(0, 191, 255))
                .build();

所有不可变集合都有一个 asList()方法提供 ImmutableList 视图,来帮助你用列表形式方便地读取集合元素。例如,你可以使用 sortedSet.asList().get(k)从 ImmutableSortedSet 中读取第 k 个最小元素。

可变集合接口 属于JDK还是Guava 不可变版本
Collection JDK ImmutableCollection
List JDK ImmutableList
Set JDK ImmutableSet
SortedSet/NavigableSet JDK ImmutableSortedSet
Map JDK ImmutableMap
SortedMap JDK ImmutableSortedMap
Multiset Guava ImmutableMultiset
SortedMultiset Guava ImmutableSortedMultiset
Multimap Guava ImmutableMultimap
ListMultimap Guava ImmutableListMultimap
SetMultimap Guava ImmutableSetMultimap
BiMap Guava ImmutableBiMap
ClassToInstanceMap Guava ImmutableClassToInstanceMap
Table Guava ImmutableTable

集合类型

Multiset接口(比较适合统计集合中数据出现几次)

该接口实现了 Collection 接口,并履行了 Collection 接口相关的契约,Guava 提供了一个新集合类型 Multiset,它可以多次添加相等的元素。维基百科从数学角度这样定义 Multiset:”集合[set]概念的延伸,它的元素可以重复出现…与集合[set]相同而与元组[tuple]相反的是,Multiset 元素的顺序是无关紧要的:Multiset {a, a, b}和{a, b, a}是相等的

可以用两种方式看待 Multiset:

  • 没有元素顺序限制的 ArrayList
  • Map
    @Test
    public void testMultiset1() {

            String strWorld="wer|dfd|dd|dfd|dda|de|dr";
            String[] words=strWorld.split("\\|");
            List<String> wordList=new ArrayList<String>();
            for (String word : words) {
                wordList.add(word);
            }
            Multiset<String> wordsMultiset = HashMultiset.create();
            wordsMultiset.addAll(wordList);

            for(String key:wordsMultiset.elementSet()){
                System.out.println(key+" count:"+wordsMultiset.count(key));
            }
        }

       输出:
        dd count1
        dda count1
        de count1
        dfd count2
        wer count1
        dr count1

Multimap接口

特点:不会有任何键映射到空集合:一个键要么至少到一个值,要么根本就不在Multimap中。

可以用两种方式思考 Multimap 的概念:”键-单个值映射”的集合:

a -> 1 a -> 2 a ->4 b -> 3 c -> 5

或者”键-值集合映射”的映射:

a -> [1, 2, 4] b -> 3 c -> 5

一般来说,Multimap 接口应该用第一种方式看待,但 asMap()视图返回 Map

package com.unis.GuavaStudy;

import com.google.common.base.MoreObjects;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Ordering;

class Person implements Comparable<Person> {

    public String name;
    public int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }



    @Override
    public String toString() {
        return MoreObjects.toStringHelper(Person.class).add("name", this.name).add("age", this.age).toString();
    }



    @Override
    public int compareTo(Person that) {
        // TODO Auto-generated method stub
        return ComparisonChain.
                start()
                .compare(this.age, that.age)//对对象类型的字段进行排序修改
                .compare(this.name, that.name,Ordering.natural().nullsFirst())
                .result();
    }
}

@Test
public void testMultiMap() {

    Multimap<String , Person > multimap = ArrayListMultimap.create();//创建集合

    for(int i=0;i<3;i++) {
        Person p1 = new Person("steven"+i, i);
        multimap.put("England", p1);
    }
    for(int i=6;i<8;i++) {
        Person p1 = new Person("小米"+i, i);
        multimap.put("Chinese", p1);
    }

    System.out.println("keyset="+multimap.keySet());
    System.out.println("values="+multimap.values());

    System.out.println("asMap()取key="+multimap.asMap().get("England"));
    //所有键的个数
    System.out.println(multimap.size());
    //不同键的个数
    System.out.print(multimap.keySet().size());


}
输出结果:
keyset=[England, Chinese]
values=[Person{name=steven0, age=0}, Person{name=steven1, age=1}, Person{name=steven2, age=2}, Person{name=小米6, age=6}, Person{name=小米7, age=7}]
asMap()取key=[Person{name=steven0, age=0}, Person{name=steven1, age=1}, Person{name=steven2, age=2}]
5
2

BiMap

传统上,实现键值对的双向映射需要维护两个单独的 map,并保持它们间的同步。但这种方式很容易出错,而且对于值已经在 map 中的情况,会变得非常混乱。例如:

Map<String, Integer> nameToId = Maps.newHashMap();
Map<Integer, String> idToName = Maps.newHashMap();

nameToId.put("Bob", 42);
idToName.put(42, "Bob");
//如果"Bob"和42已经在map中了,会发生什么?
//如果我们忘了同步两个map,会有诡异的bug发生...

BiMap

table(就和名字一样类似二维表的数据结构)

通常来说,当你想使用多个键做索引的时候,你可能会用类似 Map

@Test
    public void testTable() {
         Table<String, String, Integer> weightedGraph = HashBasedTable.create();
            weightedGraph.put("v1", "v2", 4);
            weightedGraph.put("v1", "v3", 20);
            weightedGraph.put("v2", "v3", 5);

            System.out.println(weightedGraph.row("v1")); // returns a Map mapping v2 to 4, v3 to 20
            System.out.println(weightedGraph.column("v3")); // returns a Map mapping v1 to 20, v2 to 5

            System.out.println(weightedGraph.columnMap());
            System.out.println(weightedGraph.rowKeySet());

    }
输出结果:
{v2=4, v3=20}
{v1=20, v2=5}
{v2={v1=4}, v3={v1=20, v2=5}}
[v1, v2]

主要的实现类:
- HashBasedTable:本质上用 HashMap

ClassToInstanceMap

ClassToInstanceMap 是一种特殊的 Map:它的键是类型,而值是符合键所指类型的对象。

为了扩展 Map 接口,ClassToInstanceMap 额外声明了两个方法:T getInstance(Class) 和 T putInstance(Class, T),从而避免强制类型转换,同时保证了类型安全。

ClassToInstanceMap 有唯一的泛型参数,通常称为 B,代表 Map 支持的所有类型的上界
实现上, ClassToInstanceMap实现了Map

  MutableClassToInstanceMap<Number> map = MutableClassToInstanceMap.create(); map.putInstance(Integer.class, 100);
  map.putInstance(Float.class, 10.01f);
  System.out.println(map.getInstance(Integer.class));
  System.out.println(map.getInstance(Float.class));

RangeSet

RangeSet描述了一组不相连的、非空的区间。当把一个区间添加到可变的RangeSet时,所有相连的区间会被合并,空区间会被忽略。例如:

@Test
    public void testRangeSet() {

        RangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(Range.closed(1, 10)); // {[1,10]}
        rangeSet.add(Range.closedOpen(11, 15));//不相连区间:{[1,10], [11,15)}
        rangeSet.add(Range.closedOpen(15, 20)); //相连区间; {[1,10], [11,20)}
        rangeSet.remove(Range.open(5, 10)); //分割[1, 10]; {[1,5], [10,10], [11,20)}

        Set<Range<Integer>> ranges = rangeSet.asRanges();
        System.out.println(ranges);//[[1..5], [10..10], [11..20)]

        Preconditions.checkArgument(rangeSet.contains(7), "7 not in the rangeset");//rangeSet 不包含7

    }

RangeMap (貌似和前面的比,就是不会把相交集合合并喽?)

描述了”不相交的、非空的区间”到特定值的映射。和 RangeSet 不同,RangeMap 不会合并相邻的映射,即便相邻的区间映射到相同的值。例如:

@Test
    public void testRangeMap() {
          RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
          rangeMap.put(Range.closed(1, 10), "foo"); //{[1,10] => "foo"}
          rangeMap.put(Range.open(3, 6), "bar"); //{[1,3] => "foo", (3,6) => "bar", [6,10] => "foo"}
          rangeMap.put(Range.open(10, 20), "foo"); //{[1,3] => "foo", (3,6) => "bar", [6,10] => "foo", (10,20) => "foo"}
          rangeMap.remove(Range.closed(5, 11)); //{[1,3] => "foo", (3,5) => "bar", (11,20) => "foo"}

          Map<Range<Integer>, String> asMapOfRanges = rangeMap.asMapOfRanges();//返回一个不可变的集合用于遍历

          System.out.println(asMapOfRanges);
          RangeMap<Integer, String> subRangeMap = rangeMap.subRangeMap(Range.closed(8,14));//求子集映射
          System.out.println(subRangeMap);

    }

输出结果:
{[1..3]=foo, (3..5)=bar, (11..20)=foo}
{(11..14]=foo}

猜你喜欢

转载自blog.csdn.net/whp404/article/details/81944114