zoukankan      html  css  js  c++  java
  • 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}
    
        }
  • 相关阅读:
    java基本数据类型及运算的注意事项
    B-Tree 和 B+Tree 结构及应用,InnoDB 引擎, MyISAM 引擎
    软件工程与软件开发模型、软件开发方法
    2020年3月份Unity3D游戏源码合集-免费下载
    独立游戏开发必备!8个效果不错的Unity3D 免费模型资源包
    2019年4月份整理的Unity3D 20个实用插件-免费下载
    2019年4月份整理的Unity3D游戏完整源码
    2019年3月整理的2D美术资源合集
    画面效果都不错!20个精品Unity3D着色器插件
    Unity3D中UnityPlayerActivity与UnityPlayerNativeActivity有什么区别
  • 原文地址:https://www.cnblogs.com/deityjian/p/11452235.html
Copyright © 2011-2022 走看看