前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【小家java】Java之Apache Commons-Collections4使用精讲(Bag、Map、List、Set全覆盖)

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

作者头像
YourBatman
发布2019-09-03 15:05:06
2.6K0
发布2019-09-03 15:05:06
举报
文章被收录于专栏:BAT的乌托邦BAT的乌托邦


前言

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

虽然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集合。

代码语言:javascript
复制
public interface Bag<E> extends Collection<E> {}

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

HashBag

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

代码语言:javascript
复制
    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,那你得维护两个,还是比较麻烦的

代码语言:javascript
复制
public interface BidiMap<K, V> extends IterableMap<K, V> {}

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

DualHashBidiMap

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

代码语言:javascript
复制
    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);
    }

看个示例:

代码语言:javascript
复制
    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,我们可以非常优雅的解决这个问题:

代码语言:javascript
复制
     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:

源码解释:

代码语言:javascript
复制
* 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了,没什么多余的可以说明的。

MultiValuedMap:多值Map

一个key可对应多个值,内部的数据结构逻辑交给它去维护。

我们平时使用的Map<String,List<Long>>这种数据结构,就可以被这种代替,使用起来非常方便

ArrayListValuedHashMap

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

代码语言:javascript
复制
    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

代码语言:javascript
复制
    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
代码语言:javascript
复制
    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先进先出的原则被环形覆盖

代码语言:javascript
复制
    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
代码语言:javascript
复制
    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算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。

代码语言:javascript
复制
    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
代码语言:javascript
复制
    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。

代码语言:javascript
复制
    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,保证了顺序

代码语言:javascript
复制
    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)。

代码语言:javascript
复制
    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]

    }
Map工具类:MapUtils

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

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

现在可以直接这么来了:

代码语言:javascript
复制
return MapUtils.emptyIfNull(map);
  • fixedSizeMap、fixedSizeSortedMap
代码语言:javascript
复制
IterableMap<String, String> itMap = MapUtils.fixedSizeMap(map);

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

  • invertMap 对调key和value的值
代码语言:javascript
复制
    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,然后方便遍历、删除等等 之前我们需要遍历删除Map中元素,需要
代码语言:javascript
复制
// 然后在根据key的迭代器去删除
map.entrySet().iterator();

现在方便了

代码语言:javascript
复制
    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,还是挺好用的
代码语言:javascript
复制
    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:可以有非常简便的转化
代码语言:javascript
复制
    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}

    }
SetUtils
difference:找到两个set之间的不同元素

返回的是第一个set里有的,但是第二个set里没有的元素们

代码语言:javascript
复制
    public static void main(String[] args) {
        Set<String> set1 = new HashSet<String>(){{
            add("a");
            add("b");
            add("c");
        }};
        Set<String> set2 = new HashSet<String>(){{
            add("c");
            add("d");
            add("e");
        }};

        SetUtils.SetView<String> difference = SetUtils.difference(set1, set2);
        System.out.println(difference); //[a,b]

        Set<String> strings = difference.toSet();
        System.out.println(strings); //[a,b]
    }
disjunction:和上面方法类似,但是属于加强版

会返回第一个set和第二个有差异的所有元素们

代码语言:javascript
复制
    public static void main(String[] args) {
        Set<String> set1 = new HashSet<String>(){{
            add("a");
            add("b");
            add("c");
        }};
        Set<String> set2 = new HashSet<String>(){{
            add("c");
            add("d");
            add("e");
        }};

        SetUtils.SetView<String> difference = SetUtils.disjunction(set1, set2);
        System.out.println(difference); //[a, b, d, e]

        Set<String> strings = difference.toSet();
        System.out.println(strings); //[a, b, d, e]
    }
emptyIfNull:见上MapUtils类似方法
newIdentityHashSet:可以实例化出一个newIdentityHashSet

至于它和HashSet的区别在哪里?若需要请参考我的博文:

【小家java】Java中IdentityHashMap使用详解—允许key重复(阐述和HashMap的区别)

他们的区别和HashMap的区别是一样的,请参阅

isEqualSet:

两个set里面的元素是否都一样(长度一样、元素一样),有时候判断还是非常有用的

union:合并两个set,生成一个新的set
代码语言:javascript
复制
    public static void main(String[] args) {
        Set<String> set1 = new HashSet<String>(){{
            add("a");
            add("b");
            add("c");
        }};
        Set<String> set2 = new HashSet<String>(){{
            add("c");
            add("d");
            add("e");
        }};

        SetUtils.SetView<String> union = SetUtils.union(set1, set2);

        System.out.println(union); //[a, b, c, d, e]
    }

类似于addAll的效果,但是它的好处是生成了一个新的set,对原来的set没有污染。

ListUtils
emptyIfNull:同上
defaultIfNull:可以在为null的时候,自己给个默认值返回
fixedSizeList:不解释
hashCodeForList:给List吧它的HashCode计算出来
intersection:取交集,生成一个新的List
代码语言:javascript
复制
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<String>(){{
            add("a");
            add("b");
            add("c");
        }};
        List<String> list2 = new ArrayList<String>(){{
            add("c");
            add("d");
            add("e");
        }};

        //取出交集 并且返回一个新的List
        List<String> intersection = ListUtils.intersection(list1, list2);

        System.out.println(intersection); //[c]

        //这个方法也能取出交集的效果 但是会直接改变list1里面的元素  list2不变
        list1.retainAll(list2);
        System.out.println(list1); // [c]
        System.out.println(list2); //[c, d, e]
    }
partition:切割 把一个大的List切割成多个List 非常好用

常用场景:有10000个id需要批量查询,我们可以切割一下,200个发一次请求去查询一次,还可以开多个线程,用闭锁去弄

代码语言:javascript
复制
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<String>(){{
            add("a");
            add("b");
            add("c");

            add("a");
            add("b");
            add("c");

            add("a");
            add("b");
            add("c");
        }};

        List<List<String>> partition = ListUtils.partition(list1, 4);

        System.out.println(partition); //[[a, b, c, a], [b, c, a, b], [c]]
    }
subtract:相当于做减法,用第一个List除去第二个list里含有的元素 ,然后生成一个新的list
代码语言:javascript
复制
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<String>(){{
            add("a");
            add("b");
            add("c");
        }};
        List<String> list2 = new ArrayList<String>(){{
            add("c");
            add("d");
            add("e");
        }};

        //取出交集 并且返回一个新的List
        List<String> subtract = ListUtils.subtract(list1, list2);

        System.out.println(subtract); //[a,b]
    }
sum:把两个List的元素相加起来 注意:相同的元素不会加两次 生成一个新的List
代码语言:javascript
复制
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<String>(){{
            add("a");
            add("b");
            add("c");
        }};
        List<String> list2 = new ArrayList<String>(){{
            add("c");
            add("c");
            add("c");
            add("d");
            add("e");
        }};

        //取出交集 并且返回一个新的List
        List<String> sumlist = ListUtils.sum(list1, list2);

        System.out.println(sumlist); //[a, b, c, d, e]
    }

此方法注意了,有相加的功能和去重的功能,很多场景还是很好用的

union:这个和sum方法不一样,它不带去重的功能。内部调用的addAll方法,但是生成一个新的List

例子:略

关于springframework的CollectionUtils

若你在上面没有找到操作集合的相关方法,可议参照Spring提供的这个工具类。API截图如下,就不详细分析了

总结

工欲善其事必先利其器,磨刀不误砍柴工。

希望整理的一些常用工具类、工具方法能够帮助到大家。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年11月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Bag
    • HashBag
      • TreeBag
        • 总结
        • BidiMap: 双重Map
          • DualHashBidiMap
            • DualLinkedHashBidiMap
              • DualTreeBidiMap
                • TreeBidiMap
                • MultiKeyMap:多键Map
                • MultiValuedMap:多值Map
                  • ArrayListValuedHashMap
                    • HashSetValuedHashMap
                    • MultiSet
                      • HashMultiSet
                        • PredicatedMultiSet 使用较少,不做讲解
                        • BoundedCollection:有限制的集合
                          • FixedSizeList:固定长度大小的List
                            • UnmodifiableBoundedCollection:不能修改的List
                              • CircularFifoQueue:环形的先进先出队列
                              • BoundedMap:
                                • FixedSizeMap
                                  • FixedSizeSortedMap
                                    • LRUMap
                                      • SingletonMap
                                      • GrowthList LazyList :list自增长效果
                                      • SetUniqueList
                                      • TreeList
                                      • Map工具类:MapUtils
                                      • SetUtils
                                        • difference:找到两个set之间的不同元素
                                          • disjunction:和上面方法类似,但是属于加强版
                                            • emptyIfNull:见上MapUtils类似方法
                                              • newIdentityHashSet:可以实例化出一个newIdentityHashSet
                                                • isEqualSet:
                                                  • union:合并两个set,生成一个新的set
                                                  • ListUtils
                                                    • emptyIfNull:同上
                                                      • defaultIfNull:可以在为null的时候,自己给个默认值返回
                                                        • fixedSizeList:不解释
                                                          • hashCodeForList:给List吧它的HashCode计算出来
                                                            • intersection:取交集,生成一个新的List
                                                              • partition:切割 把一个大的List切割成多个List 非常好用
                                                                • subtract:相当于做减法,用第一个List除去第二个list里含有的元素 ,然后生成一个新的list
                                                                  • sum:把两个List的元素相加起来 注意:相同的元素不会加两次 生成一个新的List
                                                                    • union:这个和sum方法不一样,它不带去重的功能。内部调用的addAll方法,但是生成一个新的List
                                                                    • 关于springframework的CollectionUtils
                                                                    • 总结
                                                                    相关产品与服务
                                                                    对象存储
                                                                    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                                                                    领券
                                                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档