MultiMap,BidiMap与LazyMap简述

Map 作为一种 key-value 格式的数据结构在我们的开发过程中经常用到。通过 Map 我们可以对数据数据检索实现接近 O(1) 的时间复杂度。

// 创建一个 Map 对象
Map<Integer,String> map = new HashMap<>(12);
// 往 map 中写入数据
map.put(1,"张三");
map.put(2,"李四");
// 从 map 中读取数据
System.out.println("key: %d value: %s",1,map.get(1)); 
// key: 1 value: 张三

但是一些 Map 的志向却不仅仅于此,它们为了在更加复杂场景下提供更加简单高效的操作而努力拼搏着,这些 Map 由 guava 工具包提供。

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>30.1-jre</version>
</dependency>

集合中的集合 MultiMap<Key,Value>

MultiMap 是一种 value集合(List/Set) 类型的 Map 结构,通过组合数据结构形成了 Map<K, Collecton<V>> 这样集合套集合的形式。在普通 Map 操作下,我们需要自己构造和判断内集合操作。比如内集合是是否存在或者删除一个内集合,亦或者遍历整个 Map,这些场景下我们需要基于普通 Map 下实现更多代码来完成这些操作。而 MultiMap 帮助我们封装了这些操作,使得我们对于这类的数据结构的操作变的简单。

 // 数集合示例
 final ArrayListMultimap<String, Number> numExamples = ArrayListMultimap.create();
 numExamples.put("Integer", Integer.MAX_VALUE);
 numExamples.put("Integer", Integer.MIN_VALUE);
 numExamples.put("Integer", 12);
 // 放入浮点数集合
 numExamples.put("Float", Float.MAX_VALUE);
 numExamples.put("Float", Float.MIN_VALUE);
 numExamples.put("Float", Float.MIN_NORMAL);
 numExamples.put("Float", Float.MIN_EXPONENT);
 // 打印整数集合示例
 System.out.println(numExamples.get("Integer"));

可以看到,我们在put(value)的时候需要像普通 Map 一样先获取 Value 并判断 Value 是否为 ,null如果为 null 然后新建 list 并将值放入,封装后的 MultiMap 帮助我们做了所有麻烦的操作,让我们能够专注于业务代码:
在这里插入图片描述
从上面可以看到 Map<Key,List<Value>> 的实现格式需要我们单独对 List 进行判断,而 MultiMap<Key,Value> 的实现形式则帮助我们封装了这些操作。

英汉互译词典 BidiMap<Key,Value>

BidiMap<Key,Value> 是另一种特殊的 Map 形式,可以实现对 Map 的反向查询。 Map 数据结构本身有点像"词典" 的效果,能够根据 key 帮助我们快速检索对应的内容。而 BidiMap<Key,Value> 更像是一本英汉-汉英互译的词典,因为它不仅能够帮助我们根据 key 去查找 value,同时也能够帮助我们根据 value 去查找 key
这种"英汉互译"形式的数据结构存在于 Apache Common Collections 包中,在使用前我们需要引入该包。

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>
 BidiMap<String,String> dictionary = new DualHashBidiMap<>();
 dictionary.put("苹果","apple");
 dictionary.put("橘子","orange");
 dictionary.put("香蕉","banana");
 // 根据苹果查 apple
 System.out.println(dictionary.get("苹果"));
 // 根据 apple 查 苹果
 System.out.println(dictionary.getKey("apple"));

注意:BidiMap中key不能重复,value也不可以。

永不放弃 LazyMap

LazyMap 为我们存在但是还没有放入 Map 的值设计了一些特殊的行为,使得我们可以在还没有放入值的时候通过这些行为获取到值。简单来说,普通的 Map 在无法 get 到值的时候会返回 null,而 LazyMap会在此时去尝试根据我们制定的行为去获取值。

LazyMap同样是 Apache Common Collections 中的数据结构,我们需要引入该工具包来进行调用。

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>
示例1
// 设计一个记录时间的记录器,当没有获取到改时间的时候返回当前时间
final LazyMap<String, Long> recorder = LazyMap.lazyMap(new HashMap<>(12), 
System::currentTimeMillis);
recorder.put("Birthday", 852087816904L);
// lazy 模式,如果没有值则根据方法获取值,这里返回上面 put 的值
System.out.println(recorder.get("Birthday"));
// 返回当前时间
System.out.println(recorder.get("Today"));
// 返回当前时间
System.out.println(recorder.get("Anniversary"));
示例2
// 设计一个记录时间的记录器,当没有获取到改时间的时候返回当前时间
final LazyMap<String, String> recorder = LazyMap.lazyMap(new HashMap<>(12), 
str-> str+": "+ System.currentTimeMillis());
recorder.put("Birthday", "1970-1-1");
// lazy 模式,如果没有值则根据方法获取值
System.out.println(recorder.get("Birthday"));
System.out.println(recorder.get("Today"));
System.out.println(recorder.get("Anniversary"));

参考资料

MultiMap、BidiMap及LazyMap的使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值