跟着 Guava 学 Java 之 新集合类型

Guava 引入了很多 JDK 没有的、但明显有用的新集合类型。

这些新类型是为了和 JDK 集合框架共存,而没有往 JDK 集合抽象中硬塞其他概念。

作为一般规则,Guava 集合非常精准地遵循了 JDK 接口契约。

Multiset

我们都知道 Set 是无序不重复的,与之相反的是 List 是有序可重复的。 Multiset 是几个意思?

没错 ,Multiset 占据了 List 和 Set 之间的一个灰色地带:允许重复,但是不保证顺序

举个例子,使用 JDK 如果我们想:“统计每个单词出现的次数” 一般这样写:

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);
    }
}

我用 multiset 就轻松多了,比如

  List<String> languages = List.of("java""python""javascript""java");

  HashMultiset<String> multiset = HashMultiset.create(languages);

  System.out.println(multiset.count("java"));   //结果是:2
  System.out.println(multiset.count("python")); //结果是:1
  
  // 如果你想要不重复元素集合,还可以直接转成 Set 
  // Set<String> words = multiset.elementSet();

如果你用传统的 HashMap 做统计,那么后续如果再增加元素,你想变更统计结果是不还得再写个 for 循环往 Map 添加元素计数?用 Multiset 轻松多了,直接 add 就行:

  List<String> languages = List.of("java""python""javascript""java");

  HashMultiset<String> multiset = HashMultiset.create(languages);

  multiset.add("python");
  multiset.addAll(Lists.newArrayList("go""java""c"));

  multiset.elementSet().forEach(x -> {
      System.out.println(x + " 的出现次数: " + multiset.count(x));
  });

结果:

python 的出现次数: 2
java 的出现次数: 3
c 的出现次数: 1
go 的出现次数: 1
javascript 的出现次数: 1

当然如果你的需求比较简单,比如只是简单统计去重后的个数什么的,用 JDK8 以上的流式编程一行代码就能搞定,不用搞这么复杂

words.stream().distinct().count();

下面是 multiset 的一些常用方法:

方法 描述
count(E) 给定元素在 Multiset 中的计数
elementSet() Multiset 中不重复元素的集合,类型为 Set
entrySet() 和 Map 的 entrySet 类似,返回 Set<Multiset.Entry >,其中包含的 Entry 支持 getElement() 和 getCount() 方法
add(E, int) 增加给定元素在 Multiset 中的计数
remove(E, int) 减少给定元素在 Multiset 中的计数
setCount(E, int) 设置给定元素在 Multiset 中的计数,不可以为负数
size() 返回集合元素的总个数(包括重复的元素)

Guava 提供了多种 Multiset 的实现,大致对应 JDK 中 Map 的各种实现:

Map 对应的 Multiset 是否支持 null 元素
HashMap HashMultiset
TreeMap TreeMultiset 是(如果 comparator 支持的话)
LinkedHashMap LinkedHashMultiset
ConcurrentHashMap ConcurrentHashMultiset
ImmutableMap ImmutableMultiset

总结

使用 Multiset 可以减少 Map 的复杂操作,从而减少代码量,代码量少了,bug 自然少。早点儿下班。

Multimap

有的时候我们需要一个 key 对应多个 value 的这种结构,通常我们会构造类似这样的数据结构:

Map<K, List<V>> 或 Map<K, Set<V>> ,甚至可能更复杂,基于这个还有嵌套数据结构。

如果你需要找到 List 中的某个值是否存在,或者删除 List 中的一个元素 ,又或者要遍历整个数据结构,那么要写一坨代码,老费劲了。

我们来看用 Multimap 怎么做,比如:

    ArrayListMultimap<String, String> multimap = ArrayListMultimap.create();

    multimap.put("Fruits""Bannana");
    multimap.put("Fruits""Apple");
    multimap.put("Fruits""Pear");
    multimap.put("Vegetables""Carrot");

    multimap.put("language""java");
    multimap.put("language""python");
    multimap.put("language""go");
    multimap.put("language""python");

下面是输出的结果:


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值