https://blog.csdn.net/liuerchong/article/details/108556945
package com.baili.demo.test;
import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.collections.Bag;
import org.apache.commons.collections4.map.MultiKeyMap;
import org.apache.commons.collections4.*;
import org.apache.commons.collections4.bag.HashBag;
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
import org.apache.commons.collections4.keyvalue.MultiKey;
import org.apache.commons.collections4.list.*;
import org.apache.commons.collections4.map.FixedSizeMap;
import org.apache.commons.collections4.map.LRUMap;
import org.apache.commons.collections4.map.SingletonMap;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import org.apache.commons.collections4.multiset.HashMultiSet;
import org.apache.commons.collections4.multiset.PredicatedMultiSet;
import org.apache.commons.collections4.queue.CircularFifoQueue;
import org.junit.Test;
import java.util.*;
@Slf4j
public class CollectionsStudy {
/* Bag接口定义了一个集合,它可以计算一个对象出现在集合中的次数。 例如,如果Bag包含{a,a,b,c},则getCount("a")方法将返回2,而uniqueSet()返回唯一值。*/
@Test
public void testHashBag() {
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
}
@Test
public void testMultiKey() {
// MultiKey 多Key Map 功能很简单:装载多个key的一个对象
MultiKey multiKey = new MultiKey<>("a", "b");
System.out.println(multiKey); //MultiKey[a, b]
// 多个键对应一个值 两个key:name和NAME
MultiKeyMap multiKeyMap = new MultiKeyMap();
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");
multiKeyMap.put("name", "NAME","NAME3", "cover");
System.out.println(multiKeyMap); //{MultiKey[name, shixiang]=cover, MultiKey[name, NAME]=cover}
}
@Test
public void testMultiValuedMap() {
/* MultiValuedMap:多值Map ; 一个key可对应多个值,内部的数据结构逻辑交给它去维护。
我们平时使用的Map>这种数据结构,就可以被这种代替,使用起来非常方便
ArrayListValuedHashMap 见名之意,values采用ArrayList来存储
*/
MultiValuedMap map = new ArrayListValuedHashMap<>();
map.put("key1", "value1");
System.out.println(map); //{key1=[value1]}
map.put("key1", "value11111");
System.out.println(map); //{key1=[value1, value11111]}
log.info("----------1---------");
Collection values = map.values();
System.out.println(values); //[value1, value11111]
log.info("----------2---------");
//map.remove("key1");
//System.out.println(map); //{}
//强悍 可以直接干掉values里的某一个值
map.removeMapping("key1", "value1");
System.out.println(map); //{key1=[value11111]}
log.info("---------3---------");
//一次性放多个value
map.putAll("key2", Arrays.asList("fang", "shi", "xiang"));
System.out.println(map); //{key1=[value11111], key2=[fang, shi, xiang]}
log.info("---------4----------");
//get方法 返回List
Collection collection = map.get("key2");
MultiSet keys = map.keys();
Set 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等等
*/
}
@Test
public void testHashMultiSet() {
/*
HashSetValuedHashMap
基本用法同上,但是很显然values用set去存储。那就无序,但是去重了
这些多值的Map的key,都是采用HashMap的结构存储的
MultiMapUtils提供一些基础工具方法:emptyMultiValuedMap、unmodifiableMultiValuedMap、newListValuedHashMap、getValuesAsSet、getValuesAsList等等
MultiSet
set我们都知道,它是无序的,并且是不允许出现重复元素的。
但有些场景我们不需要顺序,但是我们需要知道指定key出现的个数(比如每样产品ID对应的剩余数量这种统计信息),那么用MultiSet统计是一个很好的方案
HashMultiSet
底层实现原理为HashMap和MutableInteger
*/
MultiSet 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); //[]
}
@Test
public void testFixedSizeList() {
// PredicatedMultiSet 使用较少,不做讲解
// BoundedCollection:有限制的集合
// 继承自Collection,他提供了一些列的有用的实现
// FixedSizeList:固定长度大小的List
/*FixedSizeList:固定长度大小的List*/
FixedSizeList 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提供的两个方法
boolean full = c.isFull();//如果是FixedSizeList 永远返回true 因为大小肯定是固定的
int size = c.maxSize();//值同size()方法
}
@Test
public void testFixedSizeMap() {
/*
BoundedMap:
FixedSizeMap
*/
FixedSizeMap m = FixedSizeMap.fixedSizeMap(new HashMap() {{
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}
}
@Test
public void testLRUMap() {
/*
FixedSizeSortedMap
区别:底层采用SortedMap
LRUMap
底层是LRU算法
LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
*/
LRUMap 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
}
@Test
public void testCircularFifoQueue() {
/* 环形的先进先出队列
UnmodifiableBoundedCollection:不能修改的List
CircularFifoQueue:环形的先进先出队列
当达到指定的size长度后,符合FIfo先进先出的原则被环形覆盖
* */
CircularFifoQueue c = new CircularFifoQueue<>(3);
// 这个size二和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]
}
@Test
public void testSingletonMap() {
// SingletonMap 单例模式Map
SingletonMap 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}
}
@Test
public void testDualHashBidiMap() {
/*
在项目当中,经常出现需要根据Key值获取value;而且要求根据value获取key值
BidiMap: 双重Map 使用双向映射,可以使用值查找键,并且可以使用键轻松查找值。(自然,它可以根据key移除,也可以根据value移除)
该场景使用还是比较多的,比如一对一的映射关系,都可以使用这来存储。如果你使用HashMap,那你得维护两个,还是比较麻烦的
public interface BidiMap extends IterableMap {}
也是个普通的Map。继承IterableMap增加了一种迭代方式,例子里会有讲解
DualHashBidiMap
底层维护两个HashMap,一个正向,一个逆向来达到效果的。
public DualHashBidiMap() { super(new HashMap(), new HashMap()); }
public DualHashBidiMap(final Map extends K, ? extends V> map) {
super(new HashMap(), new HashMap());
putAll(map);
}
* */
/* DualLinkedHashBidiMap 底层采用两个LinkedHashMap存储,其余同上
DualTreeBidiMap 底层采用两个TreeMap存储,其余同上
它不要求key和value都是实现了比较器接口的,但是自己可以自定义比较器接口传进去
TreeBidiMap
注意TreeBidiMap和DualTreeBidiMap的区别
TreeBidiMap采用是红黑树:Node。一个node就是put的一个键值对,这样子来实现双端的Map,底层的原理和上面的不一样。这样的好处:可以最大程度的节约存储空间,从而提高效率。
firstKey、lastKey、nextKey等等都有一套自己的实现,处理效率还是蛮高的
备注:使用起来基本同上,因此实例省略 此Map要求key和value必须必须必须都实现了比较器接口
*/
BidiMap map = new DualHashBidiMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
//多出来的一种遍历方式 还是非常人性化的
MapIterator it = map.mapIterator();
while (it.hasNext()) {
it.next(); //此句话必须调用 返回的是key,效果同getKey,但必须调用
System.out.println(it.getKey() + "---" + it.getValue());
}
log.info("---------1----------");
System.out.println(map.get("key1")); //value1
//根据value拿key
System.out.println(map.getKey("value1")); //key1
//这个方法是Map接口的
String orDefault = map.getOrDefault("k", "Default Value");
System.out.println(map.getOrDefault("k", "Default Value")); //Default Value
//返回一个逆序的视图 注意是视图
BidiMap 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}
}
@Test
public void testGrowthList() {
/*
GrowthList LazyList :list自增长效果
GrowthList修饰另一个列表,可以使其在因set或add操作造成索引超出异常时无缝的增加列表长度,
可以避免大多数的IndexOutOfBoundsException。(下标越界)
备注:LazyList修饰另一个列表,当调用get方法时,如果索引超出列表长度,列表会自动增长,
我们可以通过一个工厂获得超出索引位置的值。LazyList和GrowthList都可以实现对修饰的列表进行增长,
但是LazyList发生在get时候,而GrowthList发生在set和add时候,我们也可以混合使用这两种列表。
*/
List src = new ArrayList<>();
src.add("11");
src.add("22");
// src.set(5,"22");//java.lang.IndexOutOfBoundsException: Index 5 out of bounds for length 2
src = GrowthList.growthList(src);
System.out.println(src);
// 经过GrowthList.growthList一修饰后 这个list能够最大程度的避免空数组越界问题 有时候还是挺有用的
// 索引超出,自动增长 空索引位 补 null
src.set(5, "44");
System.out.println(src); //[11, 22, null, null, null, 44]
//LazyList修饰 列表,当调用get方法时
src = LazyList.lazyList(src, new Factory() {
@Override
public String create() {
return null;
}
});
//src.set(9, "944"); //不报错是
System.out.println(src);
System.out.println(src.get(7));
}
@Test
public void testSetUniqueList() {
/*
SetUniqueList
SetUniqueList实现了一个不允许重复元素的列表,有点和Set类似。
但是由有List,保证了顺序
*/
List list = new ArrayList<>();
list.add("fang");
list.add("shi");
list.add("shi");
list.add("xiang");
System.out.println(list); //[fang, shi, shi, xiang]
//list.get(5);//java.lang.IndexOutOfBoundsException: Index 5 out of bounds for length 4
//完美实现去重 且还完美保证了顺序
list = SetUniqueList.setUniqueList(list);
System.out.println(list); //[fang, shi, xiang]
// 但是需要注意 因为已经是SetUniqueList 类型了 这个时候add相同元素就不再好使了
list.add("shi");
System.out.println(list); //[fang, shi, xiang]
}
@Test
public void testTreeList() {
// 我表示这个List在我们既希望去重,有需要保持原来顺序的时候,特别特别好用。装饰一下就行,使用也非常方便
// TreeList
// TreeList实现了优化的快速插入和删除任何索引的列表。这个列表内部实现利用树结构,确保所有的插入和删除都是O(log n)。
List list = new TreeList<>();
list.add("fang");
list.add("shi");
list.add("shi");
list.add("xiang");
System.out.println(list); //[fang, shi, shi, xiang]
}
@Test
public void testpartition() {
// partition:切割 把一个大的List切割成多个List 非常好用
// 常用场景:有10000个id需要批量查询,我们可以切割一下,200个发一次请求去查询一次,还可以开多个线程,用闭锁去弄
List list1 = new ArrayList(){{
add("a");
add("b");
add("c");
add("a");
add("b");
add("c");
add("a");
add("b");
add("c");
}};
List> partition = ListUtils.partition(list1, 4);
System.out.println(partition); //[[a, b, c, a], [b, c, a, b], [c]]
}
@Test
public void testListUtils() {
// List工具类: ListUtils emptyIfNull:同上
// defaultIfNull:可以在为null的时候,自己给个默认值返回
// fixedSizeList:不解释
// hashCodeForList:给List吧它的HashCode计算出来
// intersection:取交集,生成一个新的List
List list1 = new ArrayList(){{
add("a");
add("b");
add("c");
}};
List list2 = new ArrayList(){{
add("c");
add("d");
add("e");
}};
//两个列表的交集
//取出交集 并且返回一个新的List
// 返回一个新列表,该列表包含两个给定列表中包含的所有元素。
List intersection = ListUtils.intersection(list1, list2);
System.out.println(intersection); //[c]
// ubtract:相当于做减法,用第一个List除去第二个list里含有的元素 ,然后生成一个新的list
// 从第一个列表中减去第二个列表中的所有元素,将结果放入新列表中。
// 并且返回一个新的List
List subtract = ListUtils.subtract(list1, list2);
System.out.println("subtract"+subtract); //[a,b]
//这个方法也能取出交集的效果 但是会直接改变list1里面的元素 list2不变 (污染原来的集合)
// list1.retainAll(list2);
// System.out.println(list1); // [c]
// System.out.println(list2); //[c, d, e]
//取出并集 并且返回一个新的List 此方法 有相加的功能和去重的功能,很多场景还是很好用的
List sumlist = ListUtils.sum(list1, list2);
System.out.println(sumlist); //[a, b, c, d, e]
}
@Test
public void testSetUtils() {
//Set工具类: SetUtils
//difference:找到两个set之间的不同元素
//返回的是第一个set里有的,但是第二个set里没有的元素们
Set set = new HashSet();
Set set1 = new HashSet() {{
add("a");
add("b");
add("c");
}};
Set set2 = new HashSet() {{
add("c");
add("d");
add("e");
}};
SetUtils.SetView difference = SetUtils.difference(set1, set2);
System.out.println(difference); //[a,b]
Set strings = difference.toSet();
System.out.println(strings); //[a,b]
//disjunction:和上面方法类似,但是属于加强版
//会返回第一个set和第二个有差异的所有元素们 {感觉类似交集取反}
SetUtils.SetView disjunction = SetUtils.disjunction(set1, set2);
System.out.println(disjunction); //[a, b, d, e]
Set strings1 = disjunction.toSet();
System.out.println(strings1); //[a, b, d, e]
//emptyIfNull:与 MapUtils类似方法
// .emptyIfNull(set) 如果参数为null,则返回一个可变的空映射,否则返回参数本身。
// 好像啥也没变 ???
Set sets = SetUtils.emptyIfNull(strings1);
set = SetUtils.emptyIfNull(set);
set.add("key8");
set.add("key7");
set.add("key6");
set.add("key5");
set.add(null);
set.add(null);
System.out.println(set);
// emptySortedSet 一个不可修改的空排序集
SortedSet sortedSet = SetUtils.emptySortedSet();
// sortedSet.add("key8"); // java.lang.UnsupportedOperationException
System.out.println(sortedSet);
// 使用Set.hashCode()中指定的算法生成哈希代码。 返回 hashCode : 13154014
System.out.println(SetUtils.hashCodeForSet(set));
// 可以K,V 为空的 线程安全的 MAP Set
Map map = Collections.synchronizedMap(new IdentityHashMap());
Set synchronizedSet = Collections.synchronizedSet(SetUtils.newIdentityHashSet());
//isEqualSet:
//两个set里面的元素是否都一样(长度一样、元素一样),有时候判断还是非常有用的
//union:合并两个set,生成一个新的set
boolean equalSet = SetUtils.isEqualSet(set1, set2);
System.out.println(equalSet);
//类似于addAll的效果,但是它的好处是生成了一个新的set,对原来的set没有污染。
SetUtils.SetView union = SetUtils.union(set1, set2);
System.out.println(union); //[a, b, c, d, e]
System.out.println(set1); //[a, b, c, d, e]
System.out.println(set2); //[a, b, c, d, e]
}
@Test
public void testMapUtils() {
//Map工具类:MapUtils
// 一个空的 MAP
HashMap map = new HashMap<>();
System.out.println(map);
//返回一个空的 MAP
Map objectMap = Collections.emptyMap();
System.out.println(objectMap); // {} 返回一个空的 MAP
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key5", "value5");
map.put("key3", "value3");
//MapUtils.emptyIfNull(map) 如果参数为null,则返回一个不可变的空映射,否则返回参数本身。
System.out.println( MapUtils.emptyIfNull(map)); //{} / {key1=value1, key2=value2, key5=value5, key3=value3}
// if (map == null) put 元素报错 Map is fixed size
//map.put("key8", "emptyIfNull");
// java.lang.IllegalArgumentException: Cannot put new key/value pair - Map is fixed size
// if (map != null) put 元素不报错
//map.put("key8", "emptyIfNull");
log.info("-----------------------------------------");
//fixedSizeMap、fixedSizeSortedMap
Map sizeMapap = MapUtils.fixedSizeMap(map);
System.out.println(sizeMapap);
System.out.println(sizeMapap.size()); //
//不能再往里面添加数据了
// 固定长 后在put 报 Cannot put new key
//m.put("aaa", "aaa"); //java.lang.IllegalArgumentException: Cannot put new key/value pair - Map is fixed size
//在我没有改变长度的情况下 是可以修改的
sizeMapap.put("key5", "aaaaaaaa");
System.out.println(sizeMapap); //{key1=value1, key2=value2, key5=aaaaaaaa, key3=value3}
log.info("-----------------------------------------");
log.info("--------------------invertMap---------------------");
// invertMap 对调key和value的值
Map maps = new HashMap<>();
maps.put("key1", "value1");
maps.put("key2", "value2");
maps.put("key3", "value3");
System.out.println(maps);
//fanzhuan反转 对调key和value
Map invertMap = MapUtils.invertMap(maps);
System.out.println(invertMap); //{key1=value1, key2=value2, key3=value3}
log.info("-----------------------------------------");
log.info("--------------------iterableMap---------------------");
//iterableMap 构建一个iterableMap,然后方便遍历、删除等等
//之前我们需要遍历删除Map中元素,需要
// 然后在根据key的迭代器去删除 map.entrySet().iterator();
Map map2 = new HashMap<>();
map2.put("key1", "value1");
map2.put("key2", "value2");
map2.put("key3", "value3");
// 现在
IterableMap iterableMap = MapUtils.iterableMap(map2);
MapIterator it = iterableMap.mapIterator();
MapIterator iterator = MapUtils.iterableMap(map2).mapIterator();
// while (iterator.hasNext()){
// }
while (it.hasNext()){
it.next();
String key = it.getKey();
if(key.equals("key2")){
it.remove();
}
}
System.out.println(iterableMap); //{key1=value1, key3=value3}
//我们发现这样对it Map进行删除 原来的Map也会达到同样的效果
System.out.println(map2); // {key1=value1, key3=value3}
log.info("-----------------------------------------");
log.info("--------------------populateMap---------------------");
//populateMap
//能很方便向Map里面放值,并且支持定制化key和value,还是挺好用的
//同时该方法也提供了对MutiMap的支持
Map map3 = new HashMap<>();
map3.put("key1", "value1");
//序列化 根据提供的values,按照后面规则把key都生成出来然后直接放进去
MapUtils.populateMap(map3, Arrays.asList("a", "b", "c"), e -> "key-" + e);
System.out.println(map3); //{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(map3, Arrays.asList("a", "b", "c"), e -> e, e -> "value-" + e); //java.util.ConcurrentModificationException
System.out.println(map3); //{key1=value1, key-a=a, a=value-a, b=value-b, c=value-c, key-c=c, key-b=b}
log.info("-----------------------------------------");
log.info("--------------------toProperties---------------------");
// synchronizedMap、unmodifiableMap
// toProperties:可以有非常简便的转化
map3.put(null,"ooo");
map3.put("ooo",null);
System.out.println(map3);
//获取用Map中的值初始化的新(Properties)资源对象。空输入将返回空的(Properties)资源对象。
// (Properties)对象只能存储非空键和值,因此,如果提供的映射包含空键或值,则会抛出NullPointerException。
Properties properties = MapUtils.toProperties(map3);
System.out.println(properties); //{key3=value2, key2=value2, key1=value1}
}
public static void main(String[] args) {
}
}