随笔1 interface Map<K,V>
第一次写笔记就从map开始吧,如上图所示,绿色的是interface,黄色的是abstract class,蓝色的是class,可以看出所有和图相关的接口,抽象类和类的起源都是interface map<K,V>。现在看一下当前Map接口中实现了什么,里面包含了一个内部接口interface Entry<K,V>,声明了14个方法,同时还定义了11个方法(在jdk1.8中,在interface中可以使用default关键字来定义完整的方法)
由于声明的方法都是原来版本jdk已经存在的,比较简单,所以我们从声明的方法开始介绍
public interface Map<K, V> { /**
* 方法返回键值对个数,当键值对个数大于Integer.MAX_VALUE
* 时返回Integer.MAX_VALUE
*/
int size(); /**
* 当Map中没有键值对的时候,返回true
*/
boolean isEmpty(); /**
* 当Map中的键包含key的时候返回true,相当于执行了如下语句
* key==null ? k==null : key.equals(k)
* 此处应该注意Map中的键是可以为null的,但是只可以有一个
* 需要注意的是本方法会有两个异常
* ClassCastException当传入的key和本Map中设置的key类型不相容的时候
* NullPointerException当传入的key==null,并且Map中的键没有null的时候
*/
boolean containsKey(Object key); /**
* 当有多于一个key的value等于传入的value时会返回true
* 相当于执行value==null ? v==null : value.equals(v)
* 可见value也是可以为null的
* 需要注意的是本方法会抛出两个异常
* ClassCastException当传入的值和Map中的值不相容的时候
* NullPointerException当value中没有一个值为null的时候
*/
boolean containsValue(Object value); /**
* 如果当前的key存在于Map中,会返回对应的value,否则会返回null
* 需要注意的是本方法会有两个异常
* ClassCastException当传入的key和本Map中设置的key类型不相容的时候
* NullPointerException当传入的key==null,并且Map中的键没有null的时候
*
*/
V get(Object key); /**
* 当key不存在是会放入新的键值对,当key存在时,会更新key对应的value值
* 本方法会产生四个异常
* UnsupportedOperationException当Map不支持put操作的时候
* ClassCastException当key或者value不相容的时候
* NullPointerException当Map不允许key或者value为null的时候
* IllegalArgumentException如果指定键或值的某些属性阻止将其存储在此映射中
*/
V put(K key, V value); /**
* 当Map中有这个key的时候,会返回相应的value,否则会返回null
* 本方法会抛出三个异常
* UnsupportedOperationException当Map不支持此操作时
* ClassCastException当key的类型不相容时
* NullPointerException当key是null并且这个Map不允许key为null时
*/
V remove(Object key); /**
* 将一个Map的所有键值对放入本Map,对于每一个键值对都调用的是put(K key, V value)方法
* 本方法会产生四个异常
* UnsupportedOperationException当Map不支持put操作的时候
* ClassCastException当key或者value不相容的时候
* NullPointerException当Map不允许key或者value为null的时候
* IllegalArgumentException如果指定键或值的某些属性阻止将其存储在此映射中
*/
void putAll(Map<? extends K, ? extends V> m); /**
* 从Map中移除所有的元素
* 会抛出一个异常
* UnsupportedOperationException当Map不支持本操作的时候
*/
void clear(); /**
* 会以集合的形式返回key,当修改Map的key时会反应在Set中,反之亦然
*/
Set<K> keySet(); /**
* 返回一个Collection集合对于值来说,因为值可以有重复的,所以才选用了Collection
* 同样的对Map修改时,也会反应到Collection上
*/
Collection<V> values(); /**
* 返回一个键值对的集合Entry<K, V>
*/
Set<Map.Entry<K, V>> entrySet(); /**
* 本方法是用来比较两个Map是否相同的
*/
boolean equals(Object o); /**
* 本方法是用于返回一个Map的Hash值,本方法要求对Map中的每一个Entry<K,V>进行运算的
* 这样保证了当m1.equals(m2)时m1.hashCode()==m2.hashCode()
*/
int hashCode(); }
接下来我们来看一下内部的接口interface Entry<K,V>的内容
interface Entry<K,V> {
/**
* 返回Entry的key
* IllegalStateException 并不要求实现类必须抛出这个异常,在访问Map中的Entry元素时可能用到,即Entry已经被移除时
*/
K getKey(); /**
* 返回Entry的value
* IllegalStateException 并不要求实现类必须抛出这个异常,在访问Map中的Entry元素时可能用到,即Entry已经被移除时
*/
V getValue(); /**
* 重新设置Entry的value,但是当映射关系被移除时,该方法的行为还未被定义
* 抛出五个异常
* UnsupportedOperationException如果Map不支持put操作
* ClassCastException当与指定类型不相容的时候
* NullPointerException当Map不允许出现null而此时设置的值为null的时候
* IllegalArgumentException如果当前值的属性不允许它存储在图中
* IllegalStateException并不要求实现类必须抛出这个异常,在访问Map中的Entry元素时可能用到,即Entry已经被移除时
*/
V setValue(V value); /**
* 当比较对象也是一个Entry并且表达同样的映射关系的时候返回true
*/
boolean equals(Object o); /**
* 本方法实现的要求是当e1.equals(e2)时,e1.hashCode()==e2.hashCode()
*/
int hashCode(); //从以下开始都是jdk1.8新增的方法,对于jdk1.8的新特性就不再这里分析了,会单写一篇的
/**
* 本方法会返回一个比较器,用来实现对Entry的key进行比较
*/
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
} /**
* 本方法返回一个比较器,用来实现对Entry的value进行比较,这里表示返回值同时满足两个接口
*/
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
} /**
* 这个方法和上两个方法不同之处在于上两个要求K或者V实现Comparable接口,使得本身可以比较
* 而这个方法中并没有对K,V有什么要求,而是需要一个已经实现Comparator的接口
*/
public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
} /**
* 同上
*/
public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
} }
这里简单解释一下上述代码中jdk1.8的新特性以便使代码容易理解一些,Comparator<Map.Entry<K, V>> & Serializable这里并不是表达与操作,而是返回值同时实现了这两个接口,(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue())是lambda表达式实现了一个函数式接口Comparator的compare方法
最后一部分是Map在jdk1.8中新增的default方法,在jdk1.8中,可以在interface中实现方法了,但是得用default关键字修饰
/**
* 本方法是在普通get方法上增加了一个默认值,防止了得到的value为null的情况
* 抛出两个异常
* ClassCastException当key和Map中要求的key不兼容时
* NullPointerException当Map不支持null为key时
*/
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
} /**
* 对Map中的每一个Entry进行一次action包含的操作
* 抛出两个异常
* NullPointerException当action为null时
* ConcurrentModificationException在迭代过程中有元素被移除
*/
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
} /**
* 对Map中的每个Entry都用function进行操作,返回得到的结果重新设置value
*/
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
Objects.requireNonNull(function);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
} // ise thrown from function is not a cme.
v = function.apply(k, v); try {
entry.setValue(v);
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
}
} /**
* 当key对应的value为null的时候,设置新的value值
*/
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
} return v;
} /**
* 当key和value与当前map中有完全相同的,就删除该元素,返回true,否则返回false,不做任何操作
*/
default boolean remove(Object key, Object value) {
Object curValue = get(key);
if (!Objects.equals(curValue, value) ||
(curValue == null && !containsKey(key))) {
return false;
}
remove(key);
return true;
} /**
* 当Map中存在key->oldValue时,替换为key->newValue,返回true,否则返回false,不做任何操作
*/
default boolean replace(K key, V oldValue, V newValue) {
Object curValue = get(key);
if (!Objects.equals(curValue, oldValue) ||
(curValue == null && !containsKey(key))) {
return false;
}
put(key, newValue);
return true;
} /**
* 用新的value替换老的value,并返回老的value,如果key不存在,返回null
*/
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
} /**
* 传入一个单参数函数,找到key对应的value,如果value==null,然后对key进行重新计算,得到新的value,返回新的value。否则返回null
*/
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
} return v;
} /**
* 如果Map中存在key,并且对应的value!=null的时候,用传入的两个参数的函数进行重新计算,得到新的value,如果新的value==null
* 就删除这个键值对,返回null,否则覆盖旧值,返回新的value,如果key不存在,也返回null
*/
default V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue;
if ((oldValue = get(key)) != null) {
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
put(key, newValue);
return newValue;
} else {
remove(key);
return null;
}
} else {
return null;
}
} /**
* 通过原来的键值对,计算出一个新的值,如果新的值不为空,重新设置键值对,并返回新的value,否则删除原来的键值对,返回null
*/
default V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue = get(key); V newValue = remappingFunction.apply(key, oldValue);
if (newValue == null) {
// delete mapping
if (oldValue != null || containsKey(key)) {
// something to remove
remove(key);
return null;
} else {
// nothing to do. Leave things as they were.
return null;
}
} else {
// add or replace old mapping
put(key, newValue);
return newValue;
}
} /**
* 将旧的value和新的value进行混合计算,得到另一个value,如果这个value不为空,就和原来的key形成映射关系,返回新的value,
* 否则移除原来的键值对,返回null
*/
default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}
这些方法中出现了比较陌生的BiConsumer,BiFunction和Function这三个接口,都是在java.util.function包下的新接口,可以把他们看做一个函数去理解就好了。BiConsumer
是接受两个参数,没有计算的返回值。BiFunction是接受两个参数返回一个参数。Function是接受一个参数返回一个参数。
随笔1 interface Map<K,V>的更多相关文章
- JDK源码(1.7) -- java.util.Map<K,V>
java.util.Map<K,V> 源码分析 --------------------------------------------------------------------- ...
- Map<k,v>接口
https://docs.oracle.com/javase/8/docs/api/java/util/Map.html public interface Map<K,V> K—key,V ...
- cocos基础教程(5)数据结构介绍之cocos2d::Map<K,V>
1.概述 cocos2d::Map<K,V> 是一个内部使用了 std::unordered_map的关联容器模版. std::unordered_map 是一个存储了由key-value ...
- 关于jsp利用EL和struts2标签来遍历ValueStack的东东 ------> List<Map<K,V>> 以及 Map<K,<List<xxx>>> 的结构遍历
//第一种结构Map<K,<List<xxx>>> <body> <% //显示map<String,List<Object>& ...
- Cocos2d-x之Map<K, V>
| 版权声明:本文为博主原创文章,未经博主允许不得转载. Map<K, V>是Cocos2d-x 3.0x中推出的字典容器,它也能容纳Ref类型.Map<K,V>是模仿C+ ...
- Mybatis返回List<Map<K,V>>
最终映射的字段名 会被作为 hashMap 的 key , <!-- TODO 测试返回 HashMap--> <resultMap id="testResultMap&q ...
- Map<K, V> 中k,v如果为null就转换
Set<String> set = map.keySet(); if(set != null && !set.isEmpty()) { for(String key : s ...
- Java------遍历Map<k,v>的方法
1. public class MapAction extends ActionSupport{ private Map<String, User> map = new HashMap&l ...
- Cocos2d-x3.0模版容器具体解释之二:cocos2d::Map<K,V>
1.概述: 版本号: v3.0 beta 语言: C++ 定义在 "COCOS2DX_ROOT/cocos/base" 路径下的 "CCMap.h" 的头文件里 ...
随机推荐
- [ethereum源码分析](3) ethereum初始化指令
前言 在上一章介绍了关于区块链的一些基础知识,这一章会分析指令 geth --datadir dev/data/02 init private-geth/genesis.json 的源码,若你的eth ...
- Linux Shell中捕获CTRL+C
#!/bin/bash trap 'onCtrlC' INTfunction onCtrlC () { echo 'Ctrl+C is captured'} while true; do echo ' ...
- Spring Data JPA开发中遇到的问题1:org.hibernate.hql.internal.ast.QuerySyntaxException: DispatchShift is not mapped
org.hibernate.hql.internal.ast.QuerySyntaxException: T_D_SHIFT_DISPATCH is not mapped 错误原因: 没有映射到表,经 ...
- node.js配置环境变量
今天配置node.js的时候,碰到了配置环境变量的问题 为什么会出这样的问题: 因为我将 node.js 安装到了D盘,(这是个坑,以后一定要安到C盘),当我发现,我的node操作指令无效的时候,知道 ...
- ajax传递json参数
var pros = []; for(var i = 1; i <= 2; i++) { var obj = {}; obj.id = i; obj.age = i*20; pros = pro ...
- springMVC解决跨域
原文:https://www.cnblogs.com/shihaiming/p/9544060.html 介绍: 跨站 HTTP 请求(Cross-site HTTP request)是指发起请求 ...
- Jmeter之CSV Data Set Config
在很多情况下,需要针对测试数据做参数化操作,Jmeter提供了很好用的CSV Data Set Config插件. 一.界面显示 二.界面说明 1.名称:标识,建议设置为该组件是提供什么功能 2.注释 ...
- 为什么说 Babel 将推动 JavaScript 的发展【转】
Babel是一个转换编译器,它能将 ES6 转换成可以在浏览器中运行的代码.Babel 由来自澳大利亚的开发者Sebastian McKenzie创建.他的目标是使 Babel 可以处理 ES6 的所 ...
- github javascript相关项目star数排行榜(前30,截止2016.11.18):
github javascript相关项目star数排行榜(前30,截止2016.11.18): 前端开源框架 TOP 100 前端 TOP 100:::::https://www.awesomes. ...
- levelDB Block
http://blog.csdn.net/sparkliang/article/details/8635821 BlockBuilder的接口 首先从Block的构建开始,这就是BlockBuilde ...