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不可变版本
CollectionJDKImmutableCollection
ListJDKImmutableList
SetJDKImmutableSet
SortedSet/NavigableSetJDKImmutableSortedSet
MapJDKImmutableMap
SortedMapJDKImmutableSortedMap
MultisetGuavaImmutableMultiset
SortedMultisetGuavaImmutableSortedMultiset
MultimapGuavaImmutableMultimap
ListMultimapGuavaImmutableListMultimap
SetMultimapGuavaImmutableSetMultimap
BiMapGuavaImmutableBiMap
ClassToInstanceMapGuavaImmutableClassToInstanceMap
TableGuavaImmutableTable

集合类型

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}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值