开发者社区> 游客xl2p7nx4x3c7g> 正文

【小家java】Java之Apache Commons-Collections4使用精讲(Bag、Map、List、Set全覆盖)(上)

简介: 【小家java】Java之Apache Commons-Collections4使用精讲(Bag、Map、List、Set全覆盖)(上)
+关注继续查看

前言


这个库简化了你的代码,使它易写、易读、易于维护。它能提高你的工作效率,让你从大量重复的底层代码中脱身。


虽然JDK提供给我们的集合框架已经足够强大,基本能解决我们平时的绝大所述问题,并且效率还挺高。


本文针对于Apache提供的Collections4组件提供的一些特殊数据结构,通过例子解决一些实际问题的讲解。


® bag接口

® 固定大小的map、lru (最近最少使用算法)map和双重(dual)map

® 对象数组和map的迭代器

® map的multikey

® 大量的工具类,提供了使用api的快捷方式

® 封装器,对大多数类提供了自定义的方法


Bag


Bag继承自Collection接口,定义了一个集合,该集合会记录对象在集合中出现的次数。


假设你有一个包,包含{a, a, b, c}。调用getCount(a)方法将返回2,调用uniqueset()方法将返回{a, b, c}的set集合。


public interface Bag<E> extends Collection<E> {}


顾名思义,它是包的意思,所以也是拿来装数据的。


HashBag


HashBag使用HashMap作为数据存储,是一个标准的Bag实现。


    public static void main(String[] args) {
        Bag hashBag = new HashBag();
        String s1 = "s1";
        String s2 = "s2";
        hashBag.add(s1);
        hashBag.add(s1);
        //一次性放置多个元素
        hashBag.add(s2, 3);

        // 获得包中元素迭代器
        Iterator<?> iterator = hashBag.iterator();
        System.out.println("包中元素为:");
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        System.out.println("包中元素个数为:" + hashBag.size()); //5
        //下面两个特有的方法 使用起来较为方便
        System.out.println("包中entity1个数为:" + hashBag.getCount(s1)); //2
        System.out.println("去重后个数为:" + hashBag.uniqueSet().size()); //2
    }
结果输出:
包中元素为:
s1
s1
s2
s2
s2
包中元素个数为:5
包中entity1个数为:2
去重后个数为:2


TreeBag


TreeBag使用TreeMap作为数据存储,用法与HashBag类似,只是TreeBag会使用自然顺序对元素进行排序。


总结


使用的方式和List差不多,效果也大同小异。

场景:比如我们需要具体知道每个元素出现的次数的时候,并且实现快速去重,使用Bag会非常便捷


对应的BagUtils,能提供BagUtils.EMPTY_BAG、synchronizedBag、unmodifiableBag等编程同步、只读的快捷方法


BidiMap: 双重Map


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


该场景使用还是比较多的,比如一对一的映射关系,都可以使用这来存储。如果你使用HashMap,那你得维护两个,还是比较麻烦的


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存储,其余同上


它不要求key和value都是实现了比较器接口的,但是自己可以自定义比较器接口传进去


TreeBidiMap


注意TreeBidiMap和DualTreeBidiMap的区别

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


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


备注:使用起来基本同上,因此实例省略


此Map要求key和value必须必须必须都实现了比较器接口


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

我们可以看到 name+NAME联合确定了一个value值。这样子,我们就可以非常优雅的处理这种情况,并且还不容易犯错。


MultiKeyMap底层采用MultiKey作为普通Map的key,采用HashedMap存储


HashedMap:

源码解释:


* A <code>Map</code> implementation that is a general purpose alternative
 * to <code>HashMap</code>.
 * <p>
 * This implementation improves on the JDK1.4 HashMap by adding the
 * {@link org.apache.commons.collections4.MapIterator MapIterator}
 * functionality and many methods for subclassing.


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



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
common-io的使用(十二)下
common-io的使用(十二)
28 0
Using Validation Annottions 使用验证
You can use four attributes in the DataAnnotations namespace to cover common validation scenarios. Required    特性 Like all the built-in validation a...
746 0
【小家java】Java之Apache Commons-Collections4使用精讲(Bag、Map、List、Set全覆盖)(上)
【小家java】Java之Apache Commons-Collections4使用精讲(Bag、Map、List、Set全覆盖)(上)
32 0
JAVA压缩、解压,使用Apache Common Compress包下载链接
JAVA压缩、解压,使用Apache Common Compress包下载链接
41 0
Github Actions 第一次使用
Github Actions 第一次使用
12 0
【Elastic Engineering】Elasticsearch:使用 alias 数据类型来遵循 ECS (Elastic Common Schema)
Elasticsearch:使用 alias 数据类型来遵循 ECS (Elastic Common Schema)
42 0
common-io的使用(十二)中
common-io的使用(十二)
42 0
734
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载