赞
踩
目录
Map和set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。Set我们可以理解为集合,Map我们可以理解为字典。其中Set继承自collection接口,Map独立存在。Set中的基本元素为Key。Map中的基本元素为Key-value对。无论在Set还是在Map中,Key的值都不允许重复。
Map和Set可以通过什么来实现呢?我们也可以通过List来实现,但是我们发现效率太低,于是我们引出两种经典的数据结构以实现Set和Map。分别是二叉搜索树(Binary Search Tree)和哈希表(Hash Table)。其中二叉搜索树我们比较熟悉。
Set接口:
方法 | 解释 |
void clear() | 清空集合 |
boolean add(E e) | 添加元素,但重复元素不会被添加成功 |
boolean contains(Object o) | 判断 o 是否在集合中 |
boolean remove(Object o) | 删除集合中的 o |
int size() | 返回set中元素的个数 |
boolean isEmpty() | 检测set是否为空,空返回true,否则返回false |
Iterator iterator() | 返回迭代器 |
Object[] toArray() | 将set中的元素转换为数组返回 |
boolean containsAll(Collection c) | 集合c中的元素是否在set中全部存在,是返回true,否则返回 false |
boolean addAll(Collection c) | 将集合c中的元素添加到set中,可以达到去重的效果 |
对于Set的两种实现方式比较
Set底层结构 | TreeSet | HashSet |
底层结构 | 红黑树 | 哈希桶 |
插入/删除/查找时间 复杂度 | O(log n) | O(1) |
是否有序 | 关于Key有序 | 不一定有序 |
线程安全 | 不安全 | 不安全 |
插入/删除/查找区别 | 按照红黑树的特性来进行插入和删除 | 1. 先计算key哈希地址 2. 然后进行 插入和删除 |
比较与覆写 | key必须能够比较,否则会抛出 ClassCastException异常 | 自定义类型需要覆写equals和 hashCode方法 |
应用场景 | 需要Key有序场景下 | Key是否有序不关心,需要更高的 时间性能 |
Map接口:
方法 | 解释 |
V get(Object key) | 返回 key 对应的 value |
V getOrDefault(Object key, V defaultValue) | 返回 key 对应的 value,key 不存在,返回默认值 |
V put(K key, V value) | 设置 key 对应的 value |
V remove(Object key) | 删除 key 对应的映射关系 |
Set keySet() | 返回所有 key 的不重复集合 |
Collection values() | 返回所有 value 的可重复集合 |
Set<Map.Entry<K,V>> entrySet() | 返回所有的 key-value 映射关系 |
boolean containsKey(Object key) | 判断是否包含 key |
boolean containsValue(Object value) | 判断是否包含 value |
对于Map的两种实现方式的比较
Map底层结构 | TreeMap | HashMap |
底层结构 | 红黑树 | 哈希桶 |
插入/删除/查找时间 复杂度 | O(log n) | O(1) |
是否有序 | 关于Key有序 | 无序 |
线程安全 | 不安全 | 不安全 |
插入/删除/查找区别 | 需要进行元素比较 | 通过哈希函数计算哈希地址 |
比较与覆写 | key必须能够比较,否则会抛出 ClassCastException异常 | 自定义类型需要覆写equals和 hashCode方法 |
应用场景 | 需要Key有序场景下 | Key是否有序不关心,需要更高的 时间性能 |
二叉搜索树满足如下性质:
1、若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
2、 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
3、它的左右子树也分别为二叉搜索树
我们自定义一个TreeNode类方便我们手动实现,我们只是对一些简单的基础功能进行实现,实现的结果如下:
- package set_map.set.treeSet;
-
- public class TreeNode {
- int key;
- TreeNode left;
- TreeNode right;
-
- public TreeNode(int key) {
- this.key = key;
- }
-
- @Override
- public String toString() {
- return "TreeNode{" +
- "key=" + key +
- ", left=" + left +
- ", right=" + right +
- '}';
- }
- }
- package set_map.set.treeSet;
-
- public class BSTree {
- private TreeNode root=null;
-
- public boolean contains(int dest){
- TreeNode cur=root;
- while (cur!=null){
- if(cur.key==dest){
- return true;
- }else if(cur.key<dest){
- cur=cur.right;
- }else{
- cur=cur.left;
- }
- }
- return false;
- }
-
-
- //给定顺序不同,得到的搜索树的结构也不同
- public boolean add(int dest){
- TreeNode treeNode = new TreeNode(dest);
- TreeNode parent=null;//定义一个节点用于记录双亲结点
-
- if(root==null){
- root=treeNode;
- return true;
- }
-
- TreeNode cur=root;
- while(cur!=null){
- if(cur.key==dest){
- return false;
- }else if(dest<cur.key){
- parent=cur;
- cur=cur.left;
- }else {
- parent=cur;
- cur=cur.right;
- }
- }
- //此时到了null的位置,是插入的时候了
- if(dest<parent.key){
- parent.left=treeNode;
- }else {
- parent.right=treeNode;
- }
- return true;
- }
- public boolean remove(int key){
- TreeNode parent=null;
- TreeNode cur=root;
- while(cur!=null){
- if(cur.key==key){
- deleteKey(parent,cur,key);
- return true;
- }else if(key< cur.key){
- parent=cur;
- cur=cur.left;
- }else{
- parent=cur;
- cur=cur.right;
- }
- }
- return false;
- }
-
- private void deleteKey(TreeNode parent,TreeNode node, int key) {
- if(node.left==null){
- if(node==root){
- root=root.right;
- }else if(node==parent.left){
- parent.left=node.right;
- }else{
- parent.right=node.right;
- }
- }else if(node.right==null){
- if(node==root){
- root=root.left;
- }else if(node==parent.left){
- parent.left=node.left;
- }else {
- parent.left=node.left;
- }
- }else{
- replaceDelete(parent,node);
- }
- }
-
- private void replaceDelete(TreeNode parent, TreeNode node) {
- TreeNode canparent=node;
- TreeNode candidate =node.left;
- while (candidate.right!=null){
- canparent=candidate;
- candidate=candidate.right;
- }
- //将值进行替换
- node.key= candidate.key;
- //删除候选人的节点
- if(canparent==node){
- canparent.left=candidate.left;
- }else {
- canparent.right=null;
- }
- }
-
- public static void main(String[] args) {
- int[] keys={9,7,13,21,5,8,16,32,4,0,1,6,2,3};
- BSTree bsTree = new BSTree();
- for (int key : keys) {
- bsTree.add(key);
- }
- System.out.println(true);
- int[] re={2,6,7,13,9};
- for (int i : re) {
- bsTree.remove(i);
- }
- System.out.println(true);
- }
-
- }
这些方法一定要牢记于心。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。