【小家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]
    }


相关文章
|
人工智能 Java
Java 中数组Array和列表List的转换
本文介绍了数组与列表之间的相互转换方法,主要包括三部分:1)使用`Collections.addAll()`方法将数组转为列表,适用于引用类型,效率较高;2)通过`new ArrayList&lt;&gt;()`构造器结合`Arrays.asList()`实现类似功能;3)利用JDK8的`Stream`流式计算,支持基本数据类型数组的转换。此外,还详细讲解了列表转数组的方法,如借助`Stream`实现不同类型数组间的转换,并附带代码示例与执行结果,帮助读者深入理解两种数据结构的互转技巧。
1143 1
Java 中数组Array和列表List的转换
|
存储 缓存 安全
只会“有序无序”?面试官嫌弃的List、Set、Map回答!
小米,一位热衷于技术分享的程序员,通过与朋友小林的对话,详细解析了Java面试中常见的List、Set、Map三者之间的区别,不仅涵盖了它们的基本特性,还深入探讨了各自的实现原理及应用场景,帮助面试者更好地准备相关问题。
614 20
|
JSON Java 关系型数据库
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
1895 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
存储 算法 Java
Java Set深度解析:为何它能成为“无重复”的代名词?
Java的集合框架中,Set接口以其“无重复”特性著称。本文解析了Set的实现原理,包括HashSet和TreeSet的不同数据结构和算法,以及如何通过示例代码实现最佳实践。选择合适的Set实现类和正确实现自定义对象的hashCode()和equals()方法是关键。
285 4
|
Java
那些与Java Set擦肩而过的重复元素,都经历了什么?
在Java的世界里,Set如同一位浪漫而坚定的恋人,只对独一无二的元素情有独钟。重复元素虽屡遭拒绝,但通过反思和成长,最终变得独特,赢得了Set的认可。示例代码展示了这一过程,揭示了成长与独特性的浪漫故事。
213 4
|
Java 开发者
Java Set:当“重复”遇见它,秒变“独宠”!
在Java编程中,Set接口确保集合中的元素不重复,每个元素都是独一无二的“独宠”。本文介绍了Set的两种常见实现:HashSet和TreeSet。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet基于红黑树实现,不仅去重还能对元素进行排序。通过示例代码,展示了这两种集合的具体应用,帮助开发者更好地理解和使用Set。
227 4
|
存储 算法 Java
为什么Java Set如此“挑剔”,连重复元素都容不下?
在Java的集合框架中,Set是一个独特的接口,它严格要求元素不重复,适用于需要唯一性约束的场景。Set通过内部数据结构(如哈希表或红黑树)和算法(如哈希值和equals()方法)实现这一特性,自动过滤重复元素,简化处理逻辑。示例代码展示了Set如何自动忽略重复元素。
299 1
|
存储 Java 开发者
Java Set:无序之美,不重复之魅!
在Java的集合框架中,Set接口以其“无序之美”和“不重复之魅”受到开发者青睐。Set不包含重复元素,不保证元素顺序,通过元素的hashCode()和equals()方法实现唯一性。示例代码展示了如何使用HashSet添加和遍历元素,体现了Set的高效性和简洁性。
305 4
|
存储 算法 Java
Java中的Set,你真的了解它的“无重复”奥秘吗?
在Java的广阔天地里,Set以其独特的“无重复”特性,在众多数据结构中脱颖而出。本文将揭秘Set的“无重复”奥秘,带你领略其魅力。Set通过哈希算法和equals()方法协同工作,确保元素不重复。通过一个简单的案例,我们将展示HashSet如何实现这一特性。
269 1
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
4897 113

推荐镜像

更多