随笔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" 的头文件里 ...
随机推荐
- Java称霸编程语言排行榜
笔者精挑细选了本周研发频道的热门看点,供您在这个周末阅读欣赏.内容涵盖TIOBE编程语言8月份排行榜.开源挑战.WebGL演示.HTML5在线工具.IT职业身涯的14个建议,还有即将举行的SDCC(中 ...
- winform最小化及添加右键
private void PrintService_SizeChanged(object sender, EventArgs e) { if (this.WindowState == FormWind ...
- 阶段1 语言基础+高级_1-2 -面向对象和封装_15练习使用private关键字定义
练习使用private关键字定义一个学生类.通过这个联系说明一种特殊情况 先定义了name个age分别再定义getter和setter的方法 boolean类型的getter方法不能叫做get开头的. ...
- 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第5节 String类_10_练习:统计输入的字符串中
char类型在发生数学运算的时候,可以提升为int类型 这就表示char在A到Z之间的
- Docker安装及部署实例.Net Core
1.什么是Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱 ...
- Microsoft SQL Server 2008 R2官方中文版(SQL2008下载)
Microsoft SQL Server 2008 R2官方中文版(SQL2008下载) http://www.2cto.com/database/201308/235349.html
- python程序的模块与包
python的程序是由模块组成的,一个python文件就是一个模块,而模块一般由代码,函数,或者类组成.创建baiduHq.py模块(文件),在该模块中编写变量,函数,类,来说明在一个模块中,变量的输 ...
- Apache httpclient拦截器对请求进行签名
Apahce httpclient 提供HttpRequestInterceptor和HttpResponseInterceptor两种拦截器分别处理请求和响应数据,下面讲一下如何对http请求进行拦 ...
- MethodBase.GetCurrentMethod 方法
如果当前正在执行的方法定义泛型类型上MethodInfo返回GetCurrentMethod通过泛型类型定义 (即,MethodInfo.ContainsGenericParameters返回true ...
- Centos 7下Hadoop分布式集群搭建
一.关闭防火墙(直接用root用户) #关闭防火墙 sudo systemctl stop firewalld.service #关闭开机启动 sudo systemctl disable firew ...