MultiKeyMap的使用

序言

平时开发中,用的比较多的可能就是hashMap、LinkedHashMap、ConcurrentHashMap,但其实还有好多可以用的Map。

MultiKeyMap

官方网址:MultiKeyMap (Apache Commons Collections 4.4 API)

MultiKeyMap继承自抽象类AbstractMapDecorator,AbstractMapDecorator抽象类又继承自AbstractIterableMap抽象类,Java中所有类的父类是Object。

看MultiKeyMap类的实现可以发现它是将多个key(重载的put方法中有2个键、3个键、4个键、5个键以及键数组)通过hash运算得到hash值,然后再用hash值和数据长度减1做与运算得到的索引值。

这样做的好处就是可以通过2~5个关键字组合映射到对应的值,下面是一个简单的demo。

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.map.MultiKeyMap;

public class MultiKeyMapTest {
    /**
     * 如果考虑并发则使用volatile保证线程可见性,但不能保证原子性
     */
    private static final MultiKeyMap<Object, ValueObject> ID_MAP = new MultiKeyMap<>();

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    private static class ValueObject {
        @JsonProperty("name")
        private String name;
        private int age;
    }

    public static void main(String[] args) {
        ID_MAP.put("key1", "key2", ValueObject.builder().name("test1").age(13).build());
        ID_MAP.put("key1", "key2", "key3", ValueObject.builder().name("test2").build());
        ID_MAP.put(new MultiKey<>("key1", "key2", "key3", "key4", "key5"), ValueObject.builder().name("test3").build());
        System.out.println(ID_MAP.get("key1", "key2"));
        System.out.println(ID_MAP.get("key1", "key2", "key3"));
        System.out.println(ID_MAP.get("key1", "key2", "key3", "key4", "key5"));
    }
}

MultiValueMap

上面有多个key对应一个value,这里有一个key对应多个value,即MultiValueMap,

官方网站:MultiValueMap (Apache Commons Collections 4.4 API)

使用也比较简单,

import org.apache.commons.collections.MultiMap;
import org.apache.commons.collections.map.MultiValueMap;

public class MultiMapTest {
    public static void main(String[] args) {
        MultiMap giftMap = new MultiValueMap();
        giftMap.put("gift", "flower");
        giftMap.put("gift", "ring");
        System.out.println(giftMap.get("gift"));    //[flower, ring]
    }
}

DualHashBidiMap

官方网址:DualHashBidiMap (Apache Commons Collections 4.4 API)

比如我们在做接口调用时,可能调用下层接口时可能存在某个字段有关联但表征不同。我们可能需要建一个中间转换的枚举或者存一个有映射关系的Map,然后通过中间转换器去做映射。

打个比方,使用枚举建立中间关系。

import lombok.AllArgsConstructor;

@AllArgsConstructor
public enum MappingEnum {
    APPLE("apple", "fruit"),
    KNIFE("knife", "tool");
    private String primaryKey;
    private String secondaryKey;

    /**
     * 通过值获得对应的键
     *
     * @param value 值
     * @return 键
     */
    public String getKeyByValue(String value) {
        for (MappingEnum enums : MappingEnum.values()) {
            if (enums.secondaryKey.equalsIgnoreCase(value)) {
                return enums.primaryKey;
            }
        }
        return null;
    }

    /**
     * 通过键获得值
     *
     * @param key 键
     * @return 值
     */
    public String getValueByKey(String key) {
        for (MappingEnum enums : MappingEnum.values()) {
            if (enums.primaryKey.equalsIgnoreCase(key)) {
                return enums.secondaryKey;
            }
        }
        return null;
    }
}

那么使用DualHashBidiMap也能达到从key中获取value,从value中获取key的效果,

DualHashBidiMap里放了一个容量为2的Map数组,第一个Map放正向映射Map,第二个Map放反向映射Map。

import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.DualHashBidiMap;

public class DualHashBidiMapTest {
    public static void main(String[] args) {
        BidiMap bidiMap = new DualHashBidiMap();
        bidiMap.put("apple", "fruit");
        bidiMap.put("knife", "tool");
        System.out.println("Key-Value: Value = " + bidiMap.get("apple"));   //fruit
        System.out.println("Value-Key: Key = " + bidiMap.getKey("fruit"));  //apple
        System.out.println("Key-Value: Value = " + bidiMap.get("knife"));   //tool
        System.out.println("Key-Value: Key = " + bidiMap.getKey("tool"));   //knife
    }
}

LRUMap

LRU(Least Recently Used,最近最少使用)属于缓存淘汰机制中的一种,前面也有介绍,

传送门:缓存淘汰算法_四问四不知的博客-CSDN博客

官方网站:LRUMap (Apache Commons Collections 4.4 API)

  • put 操作:如果当前map大小大于等于Map的最大容量,且加入的元素不在Map集合中,则从缓存中删除最近最少使用的元素。
  • get 操作:如果获取的元素在Map集合中,则先删除元素,再将元素到map中。

使用示例如下,

import java.util.Collections;
import java.util.Map;

public class LRUMapTest {
    public static void main(String[] args) {
        LRUMap<String, String> lruMap = new LRUMap<>(3);
        Map<String, String> map = Collections.synchronizedMap(lruMap);
        map.put("cache1", "MD5_21841259921");
        map.put("cache2", "MD5_48102837152");
        map.put("cache3", "MD5_66666639123");
        map.get("cache1");
        map.get("cache2");
        map.put("cache5", "MD5_97817293405");
        System.out.println(map);//{cache1=MD5_21841259921, cache2=MD5_48102837152, cache5=MD5_97817293405}
    }
}

总结

上面介绍了几种不常用的Map,一方面可以对一些不常用的类或对象加深印象,另一方面也可以学习不同的使用方法,好让自己在写代码时有更多的选择。

对于不同或相同数据类型的映射关系我们可以用Map保存返回,有时可能也会需要使用那种轻量级的对象结构把不同数据类型的对象放在一起从方法中返回出去。javafx的工具包中就提供了Pair类可以实现,下面是一个简单例子,

import javafx.util.Pair;

public class PairTest {
    public static void main(String[] args) {
        Pair<String, Boolean> pair = new Pair<>("test", true);
        System.out.println("key : " + pair.getKey());
        System.out.println("value : " + pair.getValue());
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值