Commons-Collections(二)之map

时间:2019-09-03
本文章向大家介绍Commons-Collections(二)之map,主要包括Commons-Collections(二)之map使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

BidiMap: 双重Map

使用双向映射,可以使用值查找键,并且可以使用键轻松查找值。(自然,它可以根绝key移除,也可以根据value移除)

public interface BidiMap<K, V> extends IterableMap<K, V> {}

也是个普通的Map。继承IterableMap增加了一种迭代方式,例子里会有讲解

DualHashBidiMap

底层维护两个HashMap,一个正向,一个逆向来达到效果的。

    public DualHashBidiMap() {
        super(new HashMap<K, V>(), new HashMap<V, K>());
    }
    //把一个普通的Map转成BidiMap
    public DualHashBidiMap(final Map<? extends K, ? extends V> map) {
        super(new HashMap<K, V>(), new HashMap<V, K>());
        putAll(map);
    }

看个示例:

    public static void main(String[] args) {
        BidiMap<String, String> map = new DualHashBidiMap<>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");

        //多出来的一种遍历方式  还是分厂人性化的
        MapIterator<String, String> it = map.mapIterator();
        while (it.hasNext()) {
            it.next(); //此句话必须调用  返回的是key,效果同getKey,但必须调用
            System.out.println(it.getKey() + "---" + it.getValue());
        }

        System.out.println(map.get("key1")); //value1
        //根据value拿key
        System.out.println(map.getKey("value1")); //key1
        //这个方法是Map接口的
        System.out.println(map.getOrDefault("k", "defaultValue")); //defaultValue
        //返回一个逆序的视图  注意是视图
        BidiMap<String, String> inverseMap = map.inverseBidiMap();

        //根据key删除
        inverseMap.remove("key1");
        //根据value删除
        inverseMap.removeValue("value2");

        System.out.println(map); //{key1=value1, key2=value2, key3=value3}
        System.out.println(inverseMap); //{value2=key2, value1=key1, value3=key3}
    }
输出:
key1---value1
key2---value2
key3---value3
value1
key1
defaultValue
{key1=value1, key2=value2, key3=value3}
{value2=key2, value1=key1, value3=key3}
DualLinkedHashBidiMap

底层采用两个LinkedHashMap存储,其余同上

DualTreeBidiMap

底层采用两个TreeMap存储,其余同上

TreeBidiMap

注意TreeBidiMap和DualTreeBidiMap的区别

TreeBidiMap采用是红黑树:Node。一个node就是put的一个键值对,这样子来实现双端的Map,底层的原理和上面的不一样。这样的好处:可以最大程度的节约存储空间,从而提高效率。

firstKey、lastKey、nextKey等等都有一套自己的实现,处理效率还是蛮高的

MultiKeyMap:多键Map

MultiKeyMap能够解决我们平时可能遇到的一个痛点。
比如我们Map的key,可能是由多个字段的值联合决定的(有点类似联合索引的意思),这个时候我们一般方案为:自己拼接字符串,然后put进去。

但现在有了MultiKeyMap,我们可以非常优雅的解决这个问题:

     public static void main(String[] args) {
        // MultiKey功能很简单:装载多个key的一个对象
        MultiKey<String> multiKey = new MultiKey<>("a", "b");
        System.out.println(multiKey); //MultiKey[a, b]


        MultiKeyMap<String, String> multiKeyMap = new MultiKeyMap();

        // 多个键对应一个值 两个key:name和NAME
        multiKeyMap.put("name", "NAME", "jianggujin");
        System.out.println(multiKeyMap); //{MultiKey[name, NAME]=jianggujin}
        System.out.println(multiKeyMap.get("name")); //null
        System.out.println(multiKeyMap.get("NAME")); //null
        System.out.println(multiKeyMap.get("name", "NAME")); //jianggujin

        //测试key覆盖
        multiKeyMap.put("name", "shixiang", "cover");
        System.out.println(multiKeyMap); //{MultiKey[name, shixiang]=cover, MultiKey[name, NAME]=jianggujin}

        //这样子  value值才会被覆盖
        multiKeyMap.put("name", "NAME", "cover");
        System.out.println(multiKeyMap); //{MultiKey[name, shixiang]=cover, MultiKey[name, NAME]=cover}
    }

HashedMap:

简单的说就是做了一个HashMap的通用替代品。让也能使用IterableMap的迭代器那样去使用和迭代Map了,没什么多余的可以说明的。

MultiValuedMap:多值Map

一个key可对应多个值,内部的数据结构逻辑交给它去维护。
我们平时使用的Map<String,List<Long>>这种数据结构,就可以被这种代替,使用起来非常方便

ArrayListValuedHashMap

见名之意,values采用ArrayList来存储

    public static void main(String[] args) {
        MultiValuedMap<String, String> map = new ArrayListValuedHashMap<>();

        map.put("key1", "value1");
        System.out.println(map); //{key1=[value1]}
        map.put("key1", "value11111");
        System.out.println(map); //{key1=[value1, value11111]}

        Collection<String> values = map.values();
        System.out.println(values); //[value1, value11111]

        //map.remove("key1");
        //System.out.println(map); //{}

        //强悍 可以直接干掉values里的某一个值
        map.removeMapping("key1", "value1");
        System.out.println(map); //{key1=[value11111]}

        //一次性放多个value
        map.putAll("key2", Arrays.asList("fang", "shi", "xiang"));
        System.out.println(map); //{key1=[value11111], key2=[fang, shi, xiang]}

         //get方法  返回List
        Collection<String> collection = map.get("key2");
        MultiSet<String> keys = map.keys();
        Set<String> strings = map.keySet();
        System.out.println(keys); //[key1:1, key2:3] //后面的数字表示对应的value的数量
        System.out.println(strings); //[key1, key2]
        System.out.println(map.size()); //4 注意此处的size,是所有value的size 不是key的
        System.out.println(collection); //[fang, shi, xiang]

    }
HashSetValuedHashMap

基本用法同上,但是很显然values用set去存储。那就无序,但是去重了

BoundedMap:

FixedSizeMap
    public static void main(String[] args) {
        FixedSizeMap<String, String> m = FixedSizeMap.fixedSizeMap(new HashMap<String, String>() {{
            put("fang", "a");
            put("shi", "b");
            put("xiang", "c");
        }});

        System.out.println(m); //{shi=b, xiang=c, fang=a}
        System.out.println(m.size()); //3

        //不能再往里面添加数据了
        //m.put("aaa", "aaa"); //java.lang.IllegalArgumentException: Cannot put new key/value pair - Map is fixed size

        //在我没有改变长度的情况下 是可以修改的
        m.put("fang", "aaaaaaaa");
        System.out.println(m); //{shi=b, xiang=c, fang=aaaaaaaa}

    }
FixedSizeSortedMap

区别:底层采用SortedMap

LRUMap

LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。

    public static void main(String[] args) {
        LRUMap<Object, Object> map = new LRUMap<>(3);

        System.out.println(map); //{}
        System.out.println(map.size()); //0
        System.out.println(map.maxSize()); //3
        System.out.println(map.isFull()); //false

        map.put("fang", "a");
        map.put("shi", "b");
        map.put("xiang", "c");

        System.out.println(map); //{fang=a, shi=b, xiang=c}
        System.out.println(map.size()); //3
        System.out.println(map.maxSize()); //3
        System.out.println(map.isFull()); //true

        //虽然满了 但还是可以往里面塞数据

        ////如果我们都没有get使用过 那就从后往前挤出来吧
        //map.put("heng", "heng");
        //map.put("heng22", "heng22");
        //System.out.println(map); //{xiang=c, heng=heng, heng22=heng22}
        //System.out.println(map.size()); //3
        //System.out.println(map.maxSize()); //3
        //System.out.println(map.isFull()); //true

        //我此处多次使用xiang这个key 我们会发现  xiang这个key就不会被挤出来
        map.get("xiang");
        map.get("xiang");

        map.put("heng", "heng");
        map.put("heng22", "heng22");
        System.out.println(map); //{xiang=c, heng=heng, heng22=heng22}
        System.out.println(map.size()); //3
        System.out.println(map.maxSize()); //3
        System.out.println(map.isFull()); //true

    }

SingletonMap

    public static void main(String[] args) {
        SingletonMap<String, String> map = new SingletonMap<>();

        System.out.println(map); //{null=null}
        //size已经是1了
        System.out.println(map.size()); //1
        System.out.println(map.maxSize()); //1

        //哪怕一个都没有 也不能设置值
        //map.put("one","one"); //Cannot put new key/value pair - Map is fixed size singleton

        //虽然不能再放key 但可以改值
        map.setValue("xiang"); //{null=xiang}
        System.out.println(map);

        //一般建议在构造的时候,就给key和value赋值  如下:
        map = new SingletonMap<>("fang","shixiang");
        System.out.println(map); //{fang=shixiang}

    }

Map工具类:MapUtils

这里汇聚了一些操作Map的方法,介绍一些觉得比较实用的方法:

    • emptyIfNull
      之前我们经常会这么写(不返回null的Map):
 if (map != null) {
            return Collections.emptyMap();
        }

现在可以直接这么来了:

return MapUtils.emptyIfNull(map);
  • fixedSizeMap、fixedSizeSortedMap
IterableMap<String, String> itMap = MapUtils.fixedSizeMap(map);

可以一键吧一个Map定长掉,放置一些误操作

  • invertMap:对调key和value的值
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");

        //fanzhuan反转  对调key和value
        Map<String, String> invertMap = MapUtils.invertMap(map);
        System.out.println(map); //{key1=value1, key2=value2, key3=value3}
        System.out.println(invertMap); //{value2=key2, value1=key1, value3=key3}
    }
  • iterableMap:构建一个iterableMap,然后方便遍历、删除等等
    public static void main(String[] args) {
       Map<String, String> map = new HashMap<>();
       map.put("key1", "value1");
       map.put("key2", "value2");
       map.put("key3", "value3");

       IterableMap<String, String> iterableMap = MapUtils.iterableMap(map);
       MapIterator<String, String> it = iterableMap.mapIterator();
       while (it.hasNext()){
           it.next();
           String key = it.getKey();
           if(key.equals("key2")){
               it.remove();
           }
       }
       System.out.println(iterableMap); //{key1=value1, key3=value3}
       //我们发现这样对itMap进行删除  原来的Map也会达到同样的效果
       System.out.println(map); // {key1=value1, key3=value3}

   }
  • populateMap:能很方便向Map里面放值,并且支持定制化key和value,还是挺好用的
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("key1", "value1");

        //序列化 根据提供的values,按照后面规则把key都生成出来然后直接放进去
        MapUtils.populateMap(map, Arrays.asList("a", "b", "c"), e -> "key-" + e);
        System.out.println(map); //{key1=value1, key-a=a, key-c=c, key-b=b}
        //可以在上面的理论上 对value进行进一步操作  不能采用map.values() 否则由于并发修改异常
        // MapUtils.populateMap(map, map.values(), e -> e, e -> "value-" + e); //java.util.ConcurrentModificationException
        MapUtils.populateMap(map, Arrays.asList("a", "b", "c"), e -> e, e -> "value-" + e); //java.util.ConcurrentModificationException

        System.out.println(map); //{key1=value1, key-a=a, a=value-a, b=value-b, c=value-c, key-c=c, key-b=b}
    }

同时该方法也提供了对MutiMap的支持

  • synchronizedMap、unmodifiableMap
  • toProperties:可以有非常简便的转化
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value2");

        Properties properties = MapUtils.toProperties(map);
        System.out.println(properties); //{key3=value2, key2=value2, key1=value1}

    }

原文地址:https://www.cnblogs.com/deityjian/p/11452235.html