提及TreeMap及 TreeSet,我们首先来了解他们底层是用什么来实现的,通过观看Java的源码,我们知道他们的底层都是由二叉搜索树实现的,那我们先来了解一下二叉搜索树
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树
:
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
它的左右子树也分别为二叉搜索树
看完二叉搜索时的性质,我们来自己创建一个二叉搜索数
public class BinarySearchTree {
static class TreeNode{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val){
this.val = val;
}
}
public TreeNode root = null;
}
首先实现查找(val)
/**
* 查找二叉搜索树中指定的val值
* @param val
* @return
*/
public TreeNode find(int val){
TreeNode cur = root;
while (cur != null){
if(cur.val < val){
cur = cur.right;
}else if(cur.val == val){
return cur;
}else {
cur = cur.left;
}
}
return null;
}
思路:利用二叉搜索树性质,右侧树比左侧大,直接砍掉一半,然后用==确认val值。
接下来就是二叉搜索树的插入代码实现
/**
* 插入(val)
* @param val
*/
public void insert(int val){
if(root == null){
root = new TreeNode(val);
return;
}
TreeNode cur = root;
TreeNode parent = null;
while (cur != null){
if(cur.val < val){
parent = cur;
cur = cur.right;
}else if(cur.val == val){
return;
}else {
parent = cur;
cur = cur.left;
}
}
TreeNode node = new TreeNode(val);
if(parent.val < val){
parent.right = node;
}else {
parent.left = node;
}
}
public void inorder(TreeNode root) {
if(root == null) {
return;
}
inorder(root.left);
System.out.print(root.val+" ");
inorder(root.right);
}
思路:
删除操作(val)
/**
* 删除关键字(val)
* @param val
*/
public void remove(int val){
TreeNode cur = root;
TreeNode parent = null;
while (cur != null){
if (cur.val < val){
parent = cur;
cur = cur.right;
}else if(cur.val == val){
removeNode(parent,cur);
return;
}else {
parent = cur;
cur = cur.left;
}
}
}
private void removeNode(TreeNode parent,TreeNode cur){
if(cur.left == null){
if(cur == root){
root = cur.right;
}else if(parent.left == cur){
parent.left = cur.right;
}else {
parent.right = cur.right;
}
}else if(cur.right == null){
if(cur == root){
root = cur.left;
}else if(parent.left == cur){
parent.left = cur.left;
}else {
parent.right = cur.left;
}
}else {
TreeNode targetP = cur;
TreeNode target = cur.right;
while (target.left != null){
targetP = target;
target = target.left;
}
cur.val = target.val;
if (targetP.left == target){
targetP.left = target.right;
}else {
targetP.right = target.right;
}
}
}
思路:
Map
和
set
是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关
。
2.2
模型
一般把搜索的数据称为关键字(
Key
),和关键字对应的称为值(
Value
),将其称之为
Key-value
的键值对,所以
模型会有两种:
1.
纯
key
模型
,比如:
有一个英文词典,快速查找一个单词是否在词典中
快速查找某个名字在不在通讯录中
2.
Key-Value
模型
,比如:
统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数:
<
单词,单词出现的次数
>
梁山好汉的江湖绰号:每个好汉都有自己的江湖绰号
而
Map
中存储的就是
key-value
的键值对,
Set
中只存储了
Key
。
3.1 关于Map的说明
Map
是一个接口类,该类没有继承自
Collection
,该类中存储的是
<K,V>
结构的键值对,并且
K
一定是唯一的,不
能重复
。
3.3 Map 的常用方法说明
注意:
1.
Map
是一个接口,不能直接实例化对象
,如果
要实例化对象只能实例化其实现类
TreeMap
或者
HashMap
2.
Map
中存放键值对的
Key
是唯一的,
value
是可以重复的
3.
在
TreeMap
中插入键值对时,
key
不能为空,否则就会抛
NullPointerException
异常
,
value
可以为空。但是HashMap
的
key
和
value
都可以为空。
4.
Map
中的
Key
可以全部分离出来,存储到
Set
中
来进行访问
(
因为
Key
不能重复
)
。
5.
Map
中的
value
可以全部分离出来,存储在
Collection
的任何一个子集合中
(value
可能有重复
)
。
6. Map
中键值对的
Key
不能直接修改,
value
可以修改,如果要修改
key
,只能先将该
key
删除掉,然后再来进行 重新插入。
代码实现
public static void main(String[] args) {
Map<String,Integer> treeMap = new TreeMap<>();
treeMap.put("zeq",22);
treeMap.put("zjr",21);
treeMap.put("zbb",0);
System.out.println(treeMap.get("zeq"));
//treeMap.put("zjr",28);
System.out.println(treeMap);
Set<String> keySet = treeMap.keySet();
System.out.println(keySet);
Set<Map.Entry<String,Integer>> Set = treeMap.entrySet();
for (Map.Entry<String,Integer> entry:Set) {
System.out.println("key:"+entry.getKey()+" value:"+entry.getValue());
}
}
运行结果
4. Set
的说明
Set
与
Map
主要的不同有两点:
Set
是继承自
Collection
的接口类,
Set
中只存储了
Key
。
4.1
常见方法说明
代码演示
public static void main(String[] args) {
Set<String> set = new TreeSet<>();
set.add("i");
set.add("love");
set.add("you");
System.out.println(set);
System.out.println(set.contains("love"));
}
运行结果:
注意:
1. Set
是继承自
Collection
的一个接口类
2. Set
中只存储了
key
,并且要求
key
一定要唯一
3. TreeSet
的底层是使用
Map
来实现的,其使用
key
与
Object
的一个默认对象作为键值对插入到
Map
中的
4. Set最大的功能就是对集合中的元素进行去重
5.
实现
Set
接口的常用类有
TreeSet
和
HashSet
,还有一个
LinkedHashSet
,
LinkedHashSet
是在
HashSet
的基础
上维护了一个双向链表来记录元素的插入次序。
6. Set
中的
Key
不能修改,如果要修改,先将原来的删除掉,然后再重新插入
7. TreeSet
中不能插入
null
的
key
,
HashSet
可以。