首页 > 技术文章 > 【Java之轨迹】Guava 基础使用之集合(详细注释演示)

iceclean 2021-08-06 19:47 原文


0. 导入依赖包

<!-- guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.1.1-jre</version>
</dependency>

1. 新集合类型

Guava 中包含了多种新的集合类型,包括了:

  • Multiset:新增了元素计数,元素去重,批量添加与删除元素等特性
  • SortedMultiset:新增获取子集特性
  • Multimap:新增将一个键映射到多个值的特性
  • BiMap:新增键值对的双向映射特性
  • Table:新增两个 key(相当于坐标)确定一个 value的特性
  • ClassToInstanceMap:新增从类型到对象的映射的特性

① Mutiset

@Test
public void MultisetTest() {
    // 通过 create 方法创建,使用 add 添加元素
    Multiset<String> set = HashMultiset.create();
    set.add("ice");
    set.add("len");
    set.add("rin");
    set.add("ice");

    // 也可以通过引入其他集合一次性添加
    List<String> list = new ArrayList<>();
    list.add("rex");
    list.add("ice");
    list.add("len");
    list.add("alsie");
    set.addAll(list);

    // 特性 1 :计算某个元素的数量
    System.out.println("【1】ice 的数量:" + set.count("ice"));

    // 特性 2 :去除重复元素(返回值是一个新的 Multiset 可以接收)
    System.out.println("【2】不重复元素:" + set.elementSet());

    // 特性 3 :批量处理元素
    System.out.println("【3】" + set);
    // 设置 ice 的数量为 2(ice 从 3 变成了 2)
    set.setCount("ice", 2);
    // 设置 fire 为 5
    set.setCount("fire", 5);
    System.out.println("【4】" + set);
    
    // 将 ice 的数量增加 4
    set.add("ice", 4);
    // 将 fire 的数量减少 2
    set.remove("fire", 2);
    System.out.println("【5】" + set);
    // 要移除的大于拥有的,视为全部移除
    set.remove("fire", 5);
    System.out.println("【6】" + set);
}
【1】ice 的数量:3
【2】不重复元素:[len, rex, rin, ice, alsie]
【3】[len x 2, rex, rin, ice x 3, alsie]
【4】[len x 2, rex, rin, fire x 5, ice x 2, alsie]
【5】[len x 2, rex, rin, fire x 3, ice x 6, alsie]
【6】[len x 2, rex, rin, ice x 6, alsie]

② SortedMultiset

@Test
public void SortedMultiset() {
    // 添加元素时,自动按元素名称排序(默认升序)(不是按数量排序的哦)
    SortedMultiset<String> sort = TreeMultiset.create();
    sort.setCount("ice", 5);
    sort.setCount("len", 3);
    sort.setCount("rin", 3);
    sort.setCount("rex", 6);
    // 特性 1 —— 自动按名称排序
    System.out.println("【1】" + sort);

    // 特性 2 —— 获取第一个元素的信息(最后一个元素同理,为 lastEntry)
    System.out.println("【2】 第一个元素:" + sort.firstEntry() +
            " , 名称:" + sort.firstEntry().getElement() +
            " , 数量:" + sort.firstEntry().getCount());

    // 特性 3 —— 获取子集,可以选择区间的开闭,OPEN 表示开区间,CLOSE 表示闭区间,如下为左闭右开区间
    SortedMultiset<String> subSort = sort.subMultiset("len", BoundType.CLOSED, "rin", BoundType.OPEN);
    System.out.println("【3】" + subSort);
}
【1】[ice x 5, len x 3, rex x 6, rin x 3]
【2】 第一个元素:ice x 5 , 名称:ice , 数量:5
【3】[len x 3, rex x 6]

③ Multimap

@Test
public void multimapTest() {
    // 直接使用 put 添加元素,一个 key 可以对应多个 value
    Multimap<String, String> multimap = ArrayListMultimap.create();
    multimap.put("ice", "k1");
    multimap.put("ice", "k2");
    multimap.put("len", "k3");
    System.out.println("【1】" + multimap);

    // 也可以通过其他 map 引入(允许相同的 value,两个 k3)
    Multimap<String, String> temp = ArrayListMultimap.create();
    temp.put("len", "k3");
    temp.put("rin", "k4");
    multimap.putAll(temp);
    System.out.println("【2】" + multimap);

    // 还可以为指定 key 批量添加元素(这里使用了 Lists 批量添加元素)
    List<String> list = Lists.newArrayList("k4", "k5", "k6");
    multimap.putAll("rin", list);
    System.out.println("【3】" + multimap);

    // 移除指定 key 的指定 value,移除成功返回 true,否则 false(移除所有 value 使用 removeAll)
    boolean remove = multimap.remove("rin", "k5");
    System.out.println("【4】" + multimap + " --> " + remove);

    // 替换指定 key 的value
    multimap.replaceValues("rin", Lists.newArrayList("r1", "r2"));
    System.out.println("【5】" + multimap);

    // 判读是否存在某个键,某个键值对
    System.out.println("【6】" + multimap.containsKey("len"));
    System.out.println("【7】" + multimap.containsEntry("ice", "k2"));

    // 获取所有的 key,返回值是 multiset
    System.out.println("【8】" + multimap.keys());

    // 获取所有的 value
    System.out.println("【9】" + multimap.values());
}
【1】{ice=[k1, k2], len=[k3]}
【2】{ice=[k1, k2], len=[k3, k3], rin=[k4]}
【3】{ice=[k1, k2], len=[k3, k3], rin=[k4, k4, k5, k6]}
【4】{ice=[k1, k2], len=[k3, k3], rin=[k4, k4, k6]} --> true
【5】{ice=[k1, k2], len=[k3, k3], rin=[r1, r2]}
【6】true
【7】true
【8】[ice x 2, len x 2, rin x 2]
【9】[k1, k2, k3, k3, r1, r2]

④ BiMap

    @Test
    public void biMapTest() {
        // 直接使用 put 添加单个元素
        BiMap<String , Integer> biMap = HashBiMap.create();
        biMap.put("ice", 1000);
        biMap.put("len", 800);
        System.out.println("【1】" + biMap);

        // 将键值对反转,得到一个新的 biMap,原本的不会发生变化
        BiMap<Integer, String> inverseBiMap = biMap.inverse();
        System.out.println("【2】" + inverseBiMap);

        // 由于需要反转,故键值只能是一对一而不可以一对多
        // 尝试为已存在的键映射新的值,旧版说是会抛异常,笔者使用的默认会覆盖原有的值
        biMap.put("ice", 1200);
        System.out.println("【3】" + biMap);
        // 可以使用 forcePut 显示地强制覆盖
        biMap.forcePut("ice", 1300);
        System.out.println("【4】" + biMap);

        // 获得所有的值,返回值为 Set
        System.out.println("【5】" + biMap.values());
    }
【1】{ice=1000, len=800}
【2】{1000=ice, 800=len}
【3】{ice=1200, len=800}
【4】{ice=1300, len=800}
【5】[1300, 800]

⑤ Table

可以说是 Map<K, Map<K, V>> 的简化版
相当于由两个坐标(K)确定一个值(V)

@Test
public void tableTest() {
    // 通过行和列设置值
    Table<String, Integer, String> table = HashBasedTable.create();
    table.put("ice", 1, "aaa");
    table.put("ice", 2, "bbb");
    table.put("len", 2, "ccc");
    System.out.println("【1】" + table);

    // 通过行获取列和值的关系
    System.out.println("【2】" + table.row("ice"));

    // 通过列获取行和值的关系
    System.out.println("【3】" + table.column(2));

    // 通过行和列获取值,删除值
    System.out.println("【4】(ice, 1) -> " + table.get("ice", 1));
    System.out.println("【5】删除了:" + table.remove("ice", 2));
}
【1】{ice={1=aaa, 2=bbb}, len={2=ccc}}
【2】{1=aaa, 2=bbb}
【3】{ice=bbb, len=ccc}
【4】(ice, 1) -> aaa
【5】删除了:bbb

⑥ ClassToInstanceMap

声明该类型时,指定一个父类,后续添加元素时的类型只能为该父类或该父类的子类

@Test
public void classToInstanceMapTest() {
    // 使用类型和对象(这里是自动装箱)添加元素
    ClassToInstanceMap<Number> numberMap = MutableClassToInstanceMap.create();
    numberMap.putInstance(Integer.class, 100);
    // 同一个类型只能映射一个对象,否则将会覆盖
    numberMap.putInstance(Integer.class, 120);
    numberMap.putInstance(Double.class, 12.04);
    System.out.println("【1】" + numberMap);

    // 获取指定类型对应的对象
    System.out.println("【2】" + numberMap.get(Integer.class));
}
【1】{class java.lang.Integer=120, class java.lang.Double=12.04}
【2】120

2. 集合工具类

① Lists

@Test
public void ListsTest() {
    String[] members = {"len", "rin", "rex"};
    String[] foods = {"banana", "orange", "fish"};

    // 将数组转化为 List(元素和数组可混合使用)
    // 注意:第一个位置必须手动设置一个元素(并且最多两个)
    // 往后才可以放数组(这是放一个数组的情况)
    List<String> list1 = Lists.asList("ice", "alsie", members);
    System.out.println("【1】" + list1);

    // 这是放两个数组的情况,第一个数组将直接以对象显示
    List<Serializable> list2 = Lists.asList("ice", members, foods);
    System.out.println("【2】" + list2);

    // 再定义时初始化元素,可以单纯放数组
    ArrayList<String> list3 = Lists.newArrayList(members);
    System.out.println("【3】" + list3);
    // 也可以指定任意数量的元素
    ArrayList<String> list4 = Lists.newArrayList("ice", "len", "rin", "rex", "alsie");
    System.out.println("【4】" + list4);
    // 还可以给予现有的直接创建
    ArrayList<String> list5 = Lists.newArrayList(list4);
    System.out.println("【5】" + list5);
    // 也可以融合多个列表,变成列表数组
    ArrayList<List<String>> lists = Lists.newArrayList(list1, list3, list4);
    System.out.println("【6】" + lists);

    // 指定大小分割为多个 List
    List<List<String>> partition = Lists.partition(list5, 2);
    System.out.println("【7】" + partition);

    // 多个集合作笛卡尔积
    List<List<String>> lists1 = Lists.cartesianProduct(list3, Lists.newArrayList(foods));
    System.out.println("【8】" + lists1);

    // 将字符串转化为字符集合
    ImmutableList<Character> iceClean = Lists.charactersOf("IceClean");
    System.out.println("【9】" + iceClean);

    // 将 List 反转
    List<Character> reverse = Lists.reverse(iceClean);
    System.out.println("【10】" + reverse);

    // 元素替换(将所有元素换成两边有单杆的元素)
    List<String> transform = Lists.transform(iceClean, string -> "-" + string + "-");
    System.out.println("【11】" + transform);
}
【1】[ice, alsie, len, rin, rex]
【2】[ice, [Ljava.lang.String;@567d299b, banana, orange, fish]
【3】[len, rin, rex]
【4】[ice, len, rin, rex, alsie]
【5】[ice, len, rin, rex, alsie]
【6】[[ice, alsie, len, rin, rex], [len, rin, rex], [ice, len, rin, rex, alsie]]
【7】[[ice, len], [rin, rex], [alsie]]
【8】[[len, banana], [len, orange], [len, fish], [rin, banana], [rin, orange], [rin, fish], [rex, banana], [rex, orange], [rex, fish]]
【9】[I, c, e, C, l, e, a, n]
【10】[n, a, e, l, C, e, c, I]
【11】[-I-, -c-, -e-, -C-, -l-, -e-, -a-, -n-]

… 待续


河川淌过的山岭,落日余晖(IceClean)

推荐阅读