commons-collections4包工具类介绍
Package org.apache.commons.collections4
This package contains the interfaces and utilities shared across all the subpackages of this component.
See: Description
-
Interface Summary Interface Description Bag<E> Defines a collection that counts the number of times an object appears in the collection.
BidiMap<K,V> Defines a map that allows bidirectional lookup between key and values.
BoundedCollection<E> Defines a collection that is bounded in size.
BoundedMap<K,V> Defines a map that is bounded in size.
Closure<T> Defines a functor interface implemented by classes that do something.
Equator<T> An equation function, which determines equality between objects of type T.
Factory<T> Defines a functor interface implemented by classes that create objects.
Get<K,V> The "read" subset of the
Map
interface.IterableGet<K,V> The "read" subset of the
Map
interface.IterableMap<K,V> Defines a map that can be iterated directly without needing to create an entry set.
IterableSortedMap<K,V> KeyValue<K,V> Defines a simple key value pair.
ListValuedMap<K,V> Defines a map that holds a list of values against each key.
MapIterator<K,V> Defines an iterator that operates over a
Map
.MultiMap<K,V> Deprecated since 4.1, use
MultiValuedMap
insteadMultiSet<E> Defines a collection that counts the number of times an object appears in the collection.
MultiSet.Entry<E> An unmodifiable entry for an element and its occurrence as contained in a MultiSet.
MultiValuedMap<K,V> Defines a map that holds a collection of values against each key.
OrderedBidiMap<K,V> Defines a map that allows bidirectional lookup between key and values and retains and provides access to an ordering.
OrderedIterator<E> Defines an iterator that operates over an ordered container.
OrderedMap<K,V> Defines a map that maintains order and allows both forward and backward iteration through that order.
OrderedMapIterator<K,V> Defines an iterator that operates over an ordered
Map
.Predicate<T> Defines a functor interface implemented by classes that perform a predicate test on an object.
Put<K,V> The "write" subset of the
Map
interface.ResettableIterator<E> Defines an iterator that can be reset back to an initial state.
ResettableListIterator<E> Defines a list iterator that can be reset back to an initial state.
SetValuedMap<K,V> Defines a map that holds a set of values against each key.
SortedBag<E> Defines a type of
Bag
that maintains a sorted order among its unique representative members.SortedBidiMap<K,V> Defines a map that allows bidirectional lookup between key and values and retains both keys and values in sorted order.
Transformer<I,O> Defines a functor interface implemented by classes that transform one object into another.
Trie<K,V> Defines the interface for a prefix tree, an ordered tree data structure.
Unmodifiable Marker interface for collections, maps and iterators that are unmodifiable.
-
Class Summary Class Description ArrayStack<E> Deprecated use
ArrayDeque
instead (available from Java 1.6)BagUtils Provides utility methods and decorators for
Bag
andSortedBag
instances.ClosureUtils ClosureUtils
provides reference implementations and utilities for the Closure functor interface.CollectionUtils Provides utility methods and decorators for
Collection
instances.ComparatorUtils Provides convenient static utility methods for
Comparator
objects.EnumerationUtils Provides utility methods for
Enumeration
instances.FactoryUtils FactoryUtils
provides reference implementations and utilities for the Factory functor interface.FluentIterable<E> A FluentIterable provides a powerful yet simple API for manipulating Iterable instances in a fluent manner.
IterableUtils Provides utility methods and decorators for
Iterable
instances.IteratorUtils Provides static utility methods and decorators for
Iterator
instances.ListUtils Provides utility methods and decorators for
List
instances.MapUtils Provides utility methods and decorators for
Map
andSortedMap
instances.MultiMapUtils Provides utility methods and decorators for
MultiValuedMap
instances.MultiSetUtils Provides utility methods and decorators for
MultiSet
instances.PredicateUtils PredicateUtils
provides reference implementations and utilities for the Predicate functor interface.QueueUtils Provides utility methods and decorators for
Queue
instances.SetUtils Provides utility methods and decorators for
Set
andSortedSet
instances.SetUtils.SetView<E> An unmodifiable view of a set that may be backed by other sets.
SplitMapUtils Utilities for working with "split maps:" objects that implement
Put
and/orGet
but notMap
.TransformerUtils TransformerUtils
provides reference implementations and utilities for the Transformer functor interface.TrieUtils A collection of
Trie
utilities. -
Exception Summary Exception Description FunctorException Runtime exception thrown from functors.
Package org.apache.commons.collections4 Description
This package contains the interfaces and utilities shared across all the subpackages of this component.
The following collection implementations are provided in the package:
- ArrayStack - a non synchronized Stack that follows the same API as
java.util Stack
工具类:
每个主要的集合接口都有一个utility类。因此,set和sortedset接口的utility类就是setutils。这些utility类提供了操作集合类型的共通方法。
基本的方法都包含在两个根集合接口的utility类中,即collectionutils和maputils。因为所有的其他集合接口都集成collection或者map,所以collectionutils和maputils可以被扩展使用。共同的方法包括交集操作、计数操作、迭代操作、逻辑操作和类型强制转换操作等。同时,utility类还提供了对集合封装类的访问,这与jdk collections类的方式类似。
虽然JDK提供给我们的集合框架已经足够强大,基本能解决我们平时的绝大所述问题,并且效率还挺高。
本文针对于Apache提供的Collections4组件提供的一些特殊数据结构,通过例子解决一些实际问题的讲解。
® bag接口
® 固定大小的map、lru (最近最少使用算法)map和双重(dual)map
® 对象数组和map的迭代器
® map的multikey
® 大量的工具类,提供了使用api的快捷方式
® 封装器,对大多数类提供了自定义的方法
Bag继承自Collection接口,定义了一个集合,该集合会记录对象在集合中出现的次数。
假设你有一个包,包含{a, a, b, c}。调用getCount(a)方法将返回2,调用uniqueset()方法将返回{a, b, c}的set集合。
public interface Bag<E> extends Collection<E> {}
顾名思义,它是包的意思,所以也是拿来装数据的。
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使用TreeMap
作为数据存储,用法与HashBag类似,只是TreeBag会使用自然顺序对元素进行排序。
使用的方式和List差不多,效果也大同小异。
场景:比如我们需要具体知道每个元素出现的次数的时候,并且实现快速去重,使用Bag会非常便捷
对应的BagUtils,能提供BagUtils.EMPTY_BAG、synchronizedBag、unmodifiableBag等编程同步、只读的快捷方法
使用双向映射
,可以使用值查找键,并且可以使用键轻松查找值。(自然,它可以根据key移除,也可以根据value移除)
该场景使用还是比较多的,比如一对一的映射关系,都可以使用这来存储。如果你使用HashMap,那你得维护两个,还是比较麻烦的
public interface BidiMap<K, V> extends IterableMap<K, V> {}
也是个普通的Map。继承IterableMap增加了一种迭代方式,例子里会有讲解
底层维护两个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}
底层采用两个LinkedHashMap存储,其余同上
底层采用两个TreeMap存储,其余同上
它不要求key和value都是实现了比较器接口的,但是自己可以自定义比较器接口传进去
注意TreeBidiMap和DualTreeBidiMap的区别
TreeBidiMap采用是红黑树:Node。一个node就是put的一个键值对,这样子来实现双端的Map,底层的原理和上面的不一样。这样的好处:可以最大程度的节约存储空间,从而提高效率。
firstKey、lastKey、nextKey等等都有一套自己的实现,处理效率还是蛮高的
备注:使用起来基本同上,因此实例省略
此Map要求key和value必须必须必须都实现了比较器接口
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了,没什么多余的可以说明的。
一个key可对应多个值,内部的数据结构逻辑交给它去维护。
我们平时使用的Map<String,List<Long>>
这种数据结构,就可以被这种代替,使用起来非常方便
见名之意,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]
}
基本用法同上,但是很显然values用set去存储。那就无序,但是去重了
这些多值的Map的key,都是采用HashMap的结构存储的
MultiMapUtils
提供一些基础工具方法:emptyMultiValuedMap、unmodifiableMultiValuedMap、newListValuedHashMap、getValuesAsSet、getValuesAsList等等
set我们都知道,它是无序的,并且是不允许出现重复元素的。
但有些场景我们不需要顺序,但是我们需要知道指定key出现的个数(比如每样产品ID对应的剩余数量这种统计信息),那么用MultiSet统计是一个很好的方案
底层实现原理为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); //[]
}
继承自Collection,他提供了一些列的有用的实现
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
当达到指定的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]
}
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}
}
区别:底层采用SortedMap
底层是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
}
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实现了一个不允许重复元素的列表,有点和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实现了优化的快速插入和删除任何索引的列表。这个列表内部实现利用树结构,确保所有的插入和删除都是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]
}
这里汇聚了一些操作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,然后方便遍历、删除等等
之前我们需要遍历删除Map中元素,需要
// 然后在根据key的迭代器去删除
map.entrySet().iterator();
现在方便了
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}
}
返回的是第一个set里有的,但是第二个set里没有的元素们
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]
}
会返回第一个set和第二个有差异的所有元素们
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]
}
newIdentityHashSet:可以实例化出一个newIdentityHashSet
至于它和HashSet的区别在哪里?若需要请参考我的博文:
【小家java】Java中IdentityHashMap使用详解—允许key重复(阐述和HashMap的区别)
他们的区别和HashMap的区别是一样的,请参阅
两个set里面的元素是否都一样(长度一样、元素一样),有时候判断还是非常有用的
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没有污染。
defaultIfNull:可以在为null的时候,自己给个默认值返回
hashCodeForList:给List吧它的HashCode计算出来
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个发一次请求去查询一次,还可以开多个线程,用闭锁去弄
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]]
}
ubtract:相当于做减法,用第一个List除去第二个list里含有的元素 ,然后生成一个新的list
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
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截图如下,就不详细分析了
上一篇: 我说想买个平底锅
下一篇: 医生:等我的蓝满了再说吧