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

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

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去存储。那就无序,但是去重了


这些多值的Map的key,都是采用HashMap的结构存储的


MultiMapUtils提供一些基础工具方法:emptyMultiValuedMap、unmodifiableMultiValuedMap、newListValuedHashMap、getValuesAsSet、getValuesAsList等等


MultiSet


set我们都知道,它是无序的,并且是不允许出现重复元素的。

但有些场景我们不需要顺序,但是我们需要知道指定key出现的个数(比如每样产品ID对应的剩余数量这种统计信息),那么用MultiSet统计是一个很好的方案


HashMultiSet


底层实现原理为HashMap和MutableInteger


    public static void main(String[] args) {
        MultiSet<String> set = new HashMultiSet<>();
        set.add("fang");
        set.add("fang");
        set.add("shi");
        set.add("xiang");
        set.add("xiang");
        set.add("xiang");
        //我们发现此set是无序的,但是允许了重复元素的进入 并且记录了总数
        System.out.println(set); //[shi:1, xiang:3, fang:2]
        System.out.println(set.size()); //6 = 1+3+2
        //批量添加  一些字就添加N个
        set.add("test",5);
        System.out.println(set); //[test:5, shi:1, xiang:3, fang:2]
        //移除方法
        System.out.println(set.getCount("fang")); //2
        set.remove("fang");
        //此移除 一次性只会移除一个
        System.out.println(set.getCount("fang")); //1
        //一次性全部移除 N个
        set.remove("xiang", set.getCount("xiang"));
        System.out.println(set.getCount("xiang")); //0  已经被全部移除了
        //removeAll 吧指定的key,全部移除
        set.removeAll(Arrays.asList("fang","shi","xiang","test"));
        System.out.println(set); //[]
    }


PredicatedMultiSet 使用较少,不做讲解


BoundedCollection:有限制的集合


继承自Collection,他提供了一些列的有用的实现


FixedSizeList:固定长度大小的List


    public static void main(String[] args) {
        FixedSizeList<String> c = FixedSizeList.fixedSizeList(Arrays.asList("fang", "shi", "xiang"));
        System.out.println(c); //[fang, shi, xiang]
        System.out.println(c.size()); //3
        //c.remove("fang"); //java.lang.UnsupportedOperationException: List is fixed size
        //c.add("fang"); //UnsupportedOperationException: List is fixed size
        //虽然不能增加和删除 但可以改
        c.set(2, "heng");
        System.out.println(c); //[fang, shi, heng]
        System.out.println(c.get(2));
        //BoundedCollection提供的两个方法
        c.isFull(); //如果是FixedSizeList 永远返回true 因为大小肯定是固定的
        c.maxSize(); //值同size()方法
    }


UnmodifiableBoundedCollection:不能修改的List

CircularFifoQueue:环形的先进先出队列

当达到指定的size长度后,符合FIfo先进先出的原则被环形覆盖


    public static void main(String[] args) {
        CircularFifoQueue<String> c = new CircularFifoQueue<>(3);
        // 这个siz二和MaxSize就有差异化了
        System.out.println(c.size()); //0
        System.out.println(c.maxSize()); //3
        c.add("fang");
        c.add("shi");
        c.add("xiang");
        //我们发现虽然长度是3  但是因为循环的特性 再添加一个并不会报错  而是
        c.add("heng");
        System.out.println(c); //[shi, xiang, heng]
        // 继续添加 就会把前面的继续挤出来 满员了之后,符合先进先出的原则
        c.add("heng2");
        c.add("heng3");
        System.out.println(c); //[heng, heng2, heng3]
    }


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算法


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


GrowthList LazyList :list自增长效果


GrowthList修饰另一个列表,可以使其在因set或add操作造成索引超出异常时无缝的增加列表长度,可以避免大多数的IndexOutOfBoundsException。


    public static void main(String[] args) {
        List<String> src = new ArrayList<>();
        src.add("11");
        src.add("22");
        src = GrowthList.growthList(src);
        System.out.println(src);
        //经过GrowthList.growthList一修饰后  这个list能够最大程度的避免空数组越界问题  有时候还是挺有用的
        // 索引超出,自动增长
        src.set(4, "44");
        System.out.println(src); //[11, 22, null, null, 44]
    }


备注:LazyList修饰另一个列表,当调用get方法时,如果索引超出列表长度,列表会自动增长,我们可以通过一个工厂获得超出索引位置的值。LazyList和GrowthList都可以实现对修饰的列表进行增长,但是LazyList发生在get时候,而GrowthList发生在set和add时候,我们也可以混合使用这两种列表。


SetUniqueList

SetUniqueList实现了一个不允许重复元素的列表,有点和Set类似。但是由有List,保证了顺序


    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("fang");
        list.add("shi");
        list.add("shi");
        list.add("xiang");
        System.out.println(list); //[fang, shi, shi, xiang]
        //完美实现去重 且还完美保证了顺序
        list = SetUniqueList.setUniqueList(list);
        System.out.println(list); //[fang, shi, xiang]
        // 但是需要注意 因为已经是SetUniqueList 类型了  这个时候add相同元素就不再好使了
        list.add("shi");
        System.out.println(list); //[fang, shi, xiang]
    }


我表示这个List在我们既希望去重,有需要保持原来顺序的时候,特别特别好用。装饰一下就行,使用也非常方便


TreeList


TreeList实现了优化的快速插入和删除任何索引的列表。这个列表内部实现利用树结构,确保所有的插入和删除都是O(log n)。

    public static void main(String[] args) {
        List<String> list = new TreeList<>();
        list.add("fang");
        list.add("shi");
        list.add("shi");
        list.add("xiang");
        System.out.println(list); //[fang, shi, shi, xiang]
    }


相关文章
|
18天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
34 6
|
18天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
28 2
|
18天前
|
Java
在Java的世界里,Set只接纳独一无二的元素。
【10月更文挑战第16天】在Java的世界里,Set只接纳独一无二的元素。本文通过拟人化的手法,讲述了重复元素从初次尝试加入Set被拒绝,到经历挣扎、反思,最终通过改变自己,成为独特个体并被Set接纳的全过程。示例代码展示了这一过程的技术实现。
24 1
|
2天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
2天前
|
存储 Java 开发者
Java 中 Set 类型的使用方法
【10月更文挑战第30天】Java中的`Set`类型提供了丰富的操作方法来处理不重复的元素集合,开发者可以根据具体的需求选择合适的`Set`实现类,并灵活运用各种方法来实现对集合的操作和处理。
|
2天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
2天前
|
Java 开发者
|
14天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
43 5
|
13天前
|
Java 程序员 编译器
Java|如何正确地在遍历 List 时删除元素
从源码分析如何正确地在遍历 List 时删除元素。为什么有的写法会导致异常,而另一些不会。
15 3
|
13天前
|
Java 程序员
Java|List.subList 踩坑小记
不应该仅凭印象和猜测,就开始使用一个方法,至少花一分钟认真读完它的官方注释文档。
15 1

推荐镜像

更多