本篇中学习所用源码为 java8 版本。
首先看 Map 这个接口,Map 中一共有14个抽象方法
Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法
//返回当前 Map 中元素的个数
int size();
//Map 是否包含指定的 key
boolean containsKey(Object key);
// Map 是否包含指定的 value
boolean containsValue(Object value);
//返回 key 对应的 value
V get(Object key);
//放入 键值对
V put(K key, V value);
//移除键值对
V remove(Object key);
void putAll(Map<? extends K, ? extends V> m);
// 清空Map
void clear();
Set<K> keySet();
//获取Map集合的value集合
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();
interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
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());
}
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());
}
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());
}
}
boolean equals(Object o);
int hashCode();
// 扩展方法 在Map 中没有找到指定键对应的值时返回一个默认值 具体参考例一
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
//扩展方法 遍历Map 具体参考示例二
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 中相应键对应的值 具体参考实例三
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为空或则键值对不存在,则用参数value覆盖
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
//移除一个元素
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;
}
//当键值对存在时 替换 value
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 返回,不存在时返回 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为空,函数才起作用。使用remappingFunction根据key计算出value,如果value不为null,则赋值或者添加;value为空则方法失效,不做任何改变
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;
}
//对应的key存在且value不为空,方法生效,通过键值对计算出新的value,不为空则赋值,为空就删去原有的键值对
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;
}
}
//使用remappingFunction根据键值对计算一个新的value,不为空就覆盖,或者添加;为空则删除原键值对
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;
}
}
//通过key得到集合中value,如果value不为空,则使用 remappingFunction根据旧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;
}
}
例一:getOrDefault 方法使用 以及和之前的对比
// JDK8之前的实现方法
String capitalGeorgia = statesAndCapitals.get("Georgia");
if (capitalGeorgia == null)
{
capitalGeorgia = "Unknown";
}
// JDK8的实现方法
final String capitalWisconsin = statesAndCapitals.getOrDefault("Wisconsin", "Unknown");
示例二:Map 接口中默认方法 forEach 使用方式 以及和之前的对比
Map<String,String> map = new HashMap<String,String>();
map.put("a", "q");
map.put("b", "w");
map.put("c", "e");
//之前的遍历方式 1
for (Map.Entry<String,String> entry : map.entrySet()) {
System.out.println("key:"+entry.getKey()+";value:"+entry.getValue());
}
//之前的遍历方式 2
Set<String> keySet = map.keySet();
for (String entry : keySet) {
System.out.println("key:"+ entry +";value:" + map.get(entry));
}
//新式 forEach 应用1
map.forEach((k, v) -> System.out.println("key" + ":" + k + ";" + "value" + ":" + v));
//新式 forEach 应用2
map.forEach((m, n) -> {
if (m.equals("a")) {
System.out.println("条件判断");
} else {
System.out.println(n);
}
});
实例三:Map 接口中默认方法 replaceAll使用方式
Map<String,String> map = new HashMap<String,String>();
map.put("a", "q");
map.put("b", "w");
map.put("c", "e");
map.replaceAll((k, v) -> k.length() + "");