最近想把查找树、B树、红黑树都用java实现一遍,在JDK中TreeMap类是红黑树的具体实现,其定义如下:
public class TreeMap extends AbstractMap
implements NavigableMap, Cloneable, java.io.Serializable{...}
jdk提供的抽象类AbstractMap
public abstract class AbstractMap implements Map {...}
AbstractMap
内部接口Entry
/**
* map中存储的键值对所需要实现的接口
*/
interface Entry {
K getKey();
V getValue();
V setValue(V value); //替换
/**
* (e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey())) &&
* (e1.getValue()==null ? e2.getValue()==null : e1.getValue().equals(e2.getValue()))
*/
boolean equals(Object o);
/**
* 返回该entry的hashcode,map中entry的hashcode定义为:
*
* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
* (e.getValue()==null ? 0 : e.getValue().hashCode())
*
* 保证对于任意两个entry,当e1.equals(e2)时,e1.hashCode()==e2.hashCode()
*/
int hashCode();
/**
* 返回一个对entry的key自然排序的比较器,该段代码使用了jdk8引入的Lambda表达式,等同于
* return (Comparator> & Serializable)
new Comparator>() {
@Override
public int compare(Entry c1, Entry c2) {
return c1.getKey().compareTo(c2.getKey());
}
};
*/
public static , V> Comparator> comparingByKey() {
return (Comparator> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
/**
* 返回一个对entry的value自然排序的比较器,其他同上
*/
public static > Comparator> comparingByValue() {
return (Comparator> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
}
/**
* 返回一个对entry的key使用传入的比较器进行比较排序的比较器
*/
public static Comparator> comparingByKey(Comparator super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator> & Serializable)
(c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
}
/**
*返回一个对entry的value使用传入的比较器进行比较排序的比较器
*/
public static Comparator> comparingByValue(Comparator super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator> & Serializable)
(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
}
}
查询操作:
/** **************** 查询操作********************* */
int size();//返回map容器中key-value对的格式,如果其数量超过Integer.MAX_VALUE,就返回Integer.MAX_VALUE
boolean isEmpty();//返回map是不是空的
boolean containsKey(Object key); //map包含键为key的键值对时,返回true,否则返回false,map中的键不可重复
boolean containsValue(Object value);// map中至少包含一个值为value的键值对时,返回true,否则返回false
V get(Object key);//查找map中以key为键的键值对,若存在,返回其值,否则返回null
修改操作 :
/** *************** 修改操作 ********************* */
/**
* 若map当前已经包含以key为键的键值对,则将旧value替换为传入的value,并将旧value返回
* 若不存在,则将传入的键值对添加到map中,并返回null
*/
V put(K key, V value);
/**
* 查找以key为键的键值对,若存在,移除该键值对,并返回该键值对的value(可能为null),若不存在,则返回null
*/
V remove(Object key);
/** **************** 块操作(批量操作)**************** */
/**
* 复制m中的所有键值对到当前的map对象中,该操作存在线程安全问题,若在此方法执行时,
* m被其他线程修改,则结果具有不确定性
*/
void putAll(Map extends K, ? extends V> m);
void clear(); // 移除所有键值对
视图:对于视图,个人理解有些像mysql中视图的作用,主要还是用于查询操作,但对视图的修改会造成源map内容的变化
/**
* 返回当前map中键的集合,keyset由map中的信息支撑,对keyset的更改,会导致map本身的修改,
* 对map的修改,同样会导致keyset内容的变化。
* 如果通过keyset获得迭代器iteration,在迭代过程中若成功对keyset或map进行修改,则结果不确定,
* 会引发java.util.ConcurrentModificationException异常
* keyset不支持add(),addAll()操作
*/
Set keySet();
/**
* 返回当前map中值的集合,对该集合进行各种操作的影响同keyset
*/
Collection values();
/**
*返回当前map中的键值对集合,各种修改操作影响同上
*/
Set> entrySet();
批量操作:通过一张map添加和清除操作
/**
* 复制m中的所有键值对到当前的map对象中,该操作存在线程安全问题,若在此方法执行时,
* m被其他线程修改,则结果具有不确定性
*/
void putAll(Map extends K, ? extends V> m);
void clear(); // 移除所有键值对
比较和散列:主要还是定义了hashcode的计算方法
boolean equals(Object o);
/**
* 返回当前map的hashcode,map的hashcode定义为entrySet()中所有entry对应的hashcode的和.
*/
int hashCode();
大量的默认方法作为操作工具:用了很多jdk函数编程的新特性
/** ************************* 默认方法 *********************************** */
/**
* get(Object key) 方法返回值为null时有两种情况:
* 一种是map中没有以key为键的entry,另一种是以key为键的entry的value为null,
* 下面这个默认方法提供了解决返回值为null时区分两种结果的方法,在调用取值方法时,传入一个默认值defaultValue,
* 若key存在,则返回key对应的value,否则返回defaultValue
*/
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
/**
* forEach()是对外提供的Lambda编程接口,用于定义消费者行为,可以在外部这样使用:
* map.forEach((k,v)->{
* System.out.println("key:" + k + " value:" + v);
* });
* @since 1.8
*/
default void forEach(BiConsumer super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry 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);
}
}
/**
* 用给定的方式替换所有entry的value,类似上一个默认方法
* @since 1.8
*/
default void replaceAll(BiFunction super K, ? super V, ? extends V> function) {
Objects.requireNonNull(function);
for (Map.Entry 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);
}
}
}
/**
* 若不存在则添加,若存在,则返回
* @since 1.8
*/
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); // 得到key对应的value,此时返回值有可能是null
if (!Objects.equals(curValue, value) || // 如果key对应的值与传入的value不相等
(curValue == null && !containsKey(key))) { // 不存在该key并且get()方法取得的值为null
return false;
}
remove(key);
return true;
}
/**
* 若当前存在key-oldValue,则替换为key-newValue
* @since 1.8
*/
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;
}
/**
* 若存在key,则将其value属性置为value.
* @since 1.8
*/
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
/**
* 当key存在,若其value属性为null,使用传入的方法计算得到的新值newValue,若newValue不为null,
* 则将key对应的value属性置为该值,并返回该值
* 若value属性不为null、key不存在或newValue为null,则返回null
* @since 1.8
*/
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;
}
/**
* 类似上面的方法,但是计算的新值若为null,则会将该键删除
* @since 1.8
*/
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;
}
}
/**
* 例如,要将msg创建或附加到值映射:
* map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}
* @since 1.8
*/
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)) {
remove(key); // something to remove
return null;
} else {
return null;// nothing to do. Leave things as they were.
}
} else {
put(key, newValue);// 添加或替换旧值
return newValue;
}
}
/**
* 举例, 为一个key对应的value创建或append值为msg的字符串:
* map.merge(key, msg, String::concat)
* @since 1.8
*/
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;
}
jdk8的Map接口中用了很多新引入的函数式编程的特性。