Commons-Collections(二)之map
BidiMap: 双重Map
使用双向映射,可以使用值查找键,并且可以使用键轻松查找值。(自然,它可以根绝key移除,也可以根据value移除)
public interface BidiMap<K, V> extends IterableMap<K, V> {}
也是个普通的Map。继承IterableMap增加了一种迭代方式,例子里会有讲解
DualHashBidiMap
底层维护两个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}
DualLinkedHashBidiMap
底层采用两个LinkedHashMap存储,其余同上
DualTreeBidiMap
底层采用两个TreeMap存储,其余同上
TreeBidiMap
注意TreeBidiMap和DualTreeBidiMap的区别
TreeBidiMap采用是红黑树:Node。一个node就是put的一个键值对,这样子来实现双端的Map,底层的原理和上面的不一样。这样的好处:可以最大程度的节约存储空间,从而提高效率。
firstKey、lastKey、nextKey等等都有一套自己的实现,处理效率还是蛮高的
MultiKeyMap:多键Map
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}
}
HashedMap:
简单的说就是做了一个HashMap的通用替代品。让也能使用IterableMap的迭代器那样去使用和迭代Map了,没什么多余的可以说明的。
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去存储。那就无序,但是去重了
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算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
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}
}
Map工具类:MapUtils
这里汇聚了一些操作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,然后方便遍历、删除等等
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}
}
Commons-Collections(二)之map的更多相关文章
- Apache Commons Collections 反序列化详细分析学习总结
0x01.环境准备: Apache Commons Collections 3.1版本,下载链接参考: https://www.secfree.com/a/231.html jd jui地址(将jar ...
- 出现java.lang.NoClassDefFoundError: org/apache/commons/collections/FastHashMap错误问题解决
首先出现这个问题,你应该是用了 BeanUtils.populate(meter,map); import org.apache.commons.beanutils.BeanUtils;并且导入了co ...
- ysoserial分析【一】 之 Apache Commons Collections
目录 前言 基础知识 Transformer 利用InvokerTransformer造成命令执行 Map TransformedMap LazyMap AnnotationInvocationHan ...
- Java中的集合(十二) 实现Map接口的WeakHashMap
Java中的集合(十二) 实现Map接口的WeakHashMap 一.WeakHashMap简介 WeakHashMap和HashMap一样,WeakHashMap也是一个哈希表,存储的也是键值对(k ...
- JAVA之旅(二十二)——Map概述,子类对象特点,共性方法,keySet,entrySet,Map小练习
JAVA之旅(二十二)--Map概述,子类对象特点,共性方法,keySet,entrySet,Map小练习 继续坚持下去吧,各位骚年们! 事实上,我们的数据结构,只剩下这个Map的知识点了,平时开发中 ...
- Codeforces 519D A and B and Interesting Substrings(二维map+前缀和)
题目链接:http://codeforces.com/problemset/problem/519/D 题目大意:给你一串字符串s仅由小写字母组成,并且对于'a'~'z'都给了一个值.求子串t满足t的 ...
- 【Java入门提高篇】Day19 Java容器类详解(二)Map接口
上一篇里介绍了容器家族里的大族长——Collection接口,今天来看看容器家族里的二族长——Map接口. Map也是容器家族的一个大分支,但里面的元素都是以键值对(key-value)的形式存放的, ...
- 关于java.lang.NoClassDefFoundError: org/apache/commons/collections/FastHashMap的错误解决办法
在JavaEE开发中,在把配置文件中的数据或用户表单提交上来的数据,封装在相应JavaBean的对象的对应属性中时:在实际开发中,使用第三方法工具包BeanUtils(commons-beanutil ...
- 记一次坑爹的golang 二维map判断问题
记一次坑爹的golang 二维map判断问题 2018年10月18日 23:16:21 yinnnnnnn 阅读数:32更多 个人分类: golang 版权声明:本文为博主原创文章,未经博主允许不 ...
- HDU 1263 二维map
题意:给出一份水果的交易表,根据地区统计出水果的交易情况. 思路:二维map使用. #include<cstdio> #include<string> #include ...
随机推荐
- [刘阳Java]_easyui-panel组件入门级_第3讲
EasyUI中的panel组件在前面一节中我们简单告诉了大家代码如何写.这一节我们会从panel的入门级开始讲起走,重点包括它的事件监听,属性tool介绍 1. 事件监听-通过data-options ...
- 在不受支持的 Mac 上安装 macOS Monterey 12
请注意,当前为 Beta 版,后续会及时更新. 请访问原文链接:https://sysin.org/blog/install-macos-12-on-unsupported-mac/,查看最新版.原创 ...
- 【LeetCode】59.螺旋矩阵II
59.螺旋矩阵II 知识点:数组: 题目描述 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix . 示例 输入:n = 3 ...
- 【数论】A%B Problem luogu-1865
题目描述 让你输出区间内的素数的个数 分析 预处理筛法,在随便搞一下就好了. AC代码 #include <bits/stdc++.h> using namespace std; #def ...
- PostgreSQL-WITH AS短语
WITH提供了一种方式来书写在一个大型查询中使用的辅助语句.这些语句通常被称为公共表表达式或CTE,它们可以被看成是定义只在一个查询中存在的临时表.在WITH子句中的每一个辅助语句可以是一个SELEC ...
- 有语言基础的人应该如何学习python?
正好最近在学python,感觉有语言基础的话更多在乎一些语法糖,毕竟其他东西在之前应该接触过了. 笔者C++是起始语言,也接触过java.js,介绍一点python的特点吧.帮助自己巩固所学,也希望能 ...
- pointnet.pytorch代码解析
pointnet.pytorch代码解析 代码运行 Training cd utils python train_classification.py --dataset <dataset pat ...
- ;~ 小部分AutoHotkey源代码片段测试模板2019年10月9日.ahk
;~ 小部分AutoHotkey源代码片段测试模板2019年10月9日.ahk ;~ 此脚本用于测试执行一行或多行AHK脚本源代码的效果;~ 此脚本最后修改于2019年9月22日20时03分;~ 把此 ...
- QT-可拖拽可编辑的多控件ListView
目标 结合前面的2篇文章, 继续升级QML版本的ListView: 又要拖拽, 又要可编辑, 还得支持多个控件. 循序渐进 本文基于前一篇的基础: Qt-可编辑的ListView 要循序渐进的学习. ...
- [剑指 Offer 28. 对称的二叉树]
剑指 Offer 28. 对称的二叉树 请实现一个函数,用来判断一棵二叉树是不是对称的.如果一棵二叉树和它的镜像一样,那么它是对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的. 1 / ...