当前位置: 首页 > news >正文

Java数据结构——Map和Set

目录

  • 引言
  • 1. 搜索树
    • 1.1 二叉搜索树的概念
    • 1.2 二叉搜索树的操作
    • 1.2.1 查找
      • 1.2.2 插入
      • 1.2.3 删除
  • 2. Map
    • 2.1 Map的概念
    • 2.2 Map接口内部的Entry接口(Map.Entry<K, V>)
    • 2.3 Map的常用方法
  • 3. Set
    • 3.1 Set 概念
    • 3.2 Set常见方法
  • 4. 总结

引言

本篇文章介绍Map和Set类和其实现类TreeMap和TreeSet类的使用。

1. 搜索树

在讲述TreeMap和TreeSet之前,先介绍一下搜索树,java中利用搜索树来实现Map和Set。在这里介绍一下二叉搜索树。

1.1 二叉搜索树的概念

二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树,也叫二叉排序树。具有如下性质:

  1. 左子树上所有节点的值都小于其根节点的值。
  2. 右子树上所有节点的值都大于其根节点的值。
  3. 左子树和右子树也都是二叉搜索树。

1.2 二叉搜索树的操作

二叉搜索树的定义和二叉树一致

    static class TreeNode {
        public int val;
        public TreeNode left;//左孩子的引用
        public TreeNode right;//右孩子的引用

        public TreeNode(int val) {
            this.val = val;
        }
    }

1.2.1 查找

从根节点开始,比较当前节点的值与目标值。如果目标值小于当前节点的值,则移动到左子树;如果目标值大于当前节点的值,则移动到右子树;如果相等,则返回当前节点。循环继续,直到找到目标值或到达树的末端。

    public TreeNode search(int val) {
        TreeNode cur = root;
        while (cur != null) {
            if (cur.val < val) {
                cur = cur.right;
            } else if (cur.val > val) {
                cur = cur.left;
            } else {
                return cur;
            }
        }
        return null;
    }

1.2.2 插入

  1. 从根节点开始。
  2. 如果树为空,则新节点作为根节点。
  3. 否则,比较新节点的值与当前节点的值:
    如果新节点的值小于当前节点的值,则移动到左子树。
    如果新节点的值大于当前节点的值,则移动到右子树。
  4. 重复步骤3,直到找到合适的插入位置。
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) {
                parent = cur;
                cur = cur.left;
            } else {
                return;
            }
        }
        if (parent.val < val) {
            parent.right = new TreeNode(val);
        } else {
            parent.left = new TreeNode(val);
        }

    }

1.2.3 删除

二叉搜索树的删除操作较为复杂。

  1. 查找要删除的节点:从根节点开始,找到要删除的节点及其父节点。
  2. 删除节点:
    1. 要删除的节点没有左子节点:
      如果要删除的节点是根节点,直接将根节点设为其右子节点。
      否则,更新父节点的指针,将其指向要删除节点的右子节点。
    2. 要删除的节点没有右子节点:
      如果要删除的节点是根节点,直接将根节点设为其左子节点。
      否则,更新父节点的指针,将其指向要删除节点的左子节点。
    3. 要删除的节点有两个子节点:
      找到要删除节点的后继节点(右子树中最小的节点)。
      用后继节点的值替代要删除节点的值。
      删除后继节点,更新其父节点的指针。

    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) {
                parent = cur;
                cur = cur.left;
            }else {
                removeNode(parent,cur);
                return;
            }
        }
    }

    private void removeNode(TreeNode parent, TreeNode cur) {
        if (cur.left == null){
            if(cur == root){
                root = cur.right;
            }else if(cur == parent.left){
                parent.left = cur.right;
            }else{
                parent.right = cur.right;
            }
        }else if (cur.right == null){
            if(cur == root){
                root = cur.left;
            }else if(cur == parent.left){
                parent.left = cur.left;
            }else{
                parent.right = cur.left;
            }
        }else{
            TreeNode target = cur.right;
            TreeNode targetParent = cur;
            while(target.left != null){
                targetParent = target;
                target = target.left;
            }
            if (target == targetParent.left){
                targetParent.left = target.right;
            }else{
                targetParent.right = target.right;
            }

        }
    }


2. Map

2.1 Map的概念

Map是一个接口类,是一种键值对的集合,用于存储键值对的映射关系。该类存储的是<K,V>结构的键值对。
Map接口定义了一系列方法,用于操作键值对,包括插入、删除、获取和遍历等操作。在Map中,每个键对应一个值,键(K)是唯一的,值(V)可以重复。

2.2 Map接口内部的Entry接口(Map.Entry<K, V>)

Map.Entry接口表示Map中的一个键值对(entry),它是Map接口的内部接口。Map.Entry接口定义了操作键值对的方法,允许访问键和值,以及对它们进行操作。
Map.Entry接口包含以下常用方法:

  1. getKey(): 返回该键值对中的键。
  2. getValue(): 返回该键值对中的值。
  3. setValue(V value): 设置该键值对中的值为指定的值。

2.3 Map的常用方法

  1. V get(Object key):
    根据指定的键获取对应的值。如果键不存在,则返回 null。
  2. V getOrDefault(Object key, V defaultValue):
    根据指定的键获取对应的值。如果键不存在,则返回默认值 defaultValue。
  3. V put(K key, V value):
    将指定的键值对插入到 Map 中。如果键已经存在,则更新对应的值,并返回旧值。
  4. V remove(Object key):
    根据指定的键删除对应的键值对,并返回被删除的值。如果键不存在,则返回 null。
  5. Set keySet():
    返回 Map 中所有键的集合。
  6. Collection values():
    返回 Map 中所有值的集合。
  7. Set<Map.Entry<K, V>> entrySet():
    返回 Map 中所有键值对的集合。
  8. boolean containsKey(Object key):
    判断 Map 中是否包含指定的键。
  9. boolean containsValue(Object value):
    判断 Map 中是否包含指定的值。

TreeMap示例代码:

public class MapExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new TreeMap<>();

        // put
        map.put("one", 1);
        map.put("two", 2);

        // get
        System.out.println("Value for key 'one': " + map.get("one")); // 1

        // getOrDefault
        System.out.println("Value for key 'three' (default 0): " + map.getOrDefault("three", 0)); // 0

        // remove
        System.out.println("Removed value for key 'one': " + map.remove("one"));// 1

        // keySet
        Set<String> keys = map.keySet();
        System.out.println("Keys: " + keys); // [two]

        // values
        Collection<Integer> values = map.values();
        System.out.println("Values: " + values); // [2]

        // entrySet
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        System.out.println("Entries: " + entries); // [two=2]

        // containsKey
        System.out.println("Contains key 'two': " + map.containsKey("two")); // true

        // containsValue
        System.out.println("Contains value 2: " + map.containsValue(2)); // true
    }
}

3. Set

3.1 Set 概念

Set 是 Java 集合框架中的一个接口,它表示一个不包含重复元素的集合。Set 接口继承自 Collection 接口,相较于Map不同的是它只存储了Key。

3.2 Set常见方法

  1. boolean add(E e):
    将指定的元素添加到集合中(如果该元素尚不存在于集合中)。如果集合中已存在该元素,则返回 false。
  2. void clear():
    移除集合中的所有元素。
  3. boolean contains(Object o):
    如果集合中包含指定的元素,则返回 true。
  4. Iterator iterator():
    返回集合中元素的迭代器。
  5. boolean remove(Object o):
    如果集合中存在指定的元素,则将其移除,并返回 true。
  6. int size():
    返回集合中的元素数量。
  7. boolean isEmpty():
    如果集合为空,则返回 true。
  8. Object[] toArray():
    返回包含集合中所有元素的数组。
  9. boolean containsAll(Collection<?> c):
    如果集合包含指定集合中的所有元素,则返回 true。
  10. boolean addAll(Collection<? extends E> c):
    将指定集合中的所有元素添加到集合中(如果这些元素尚不存在于集合中)。如果集合因调用此方法而发生更改,则返回 true。

TreeSet示例代码:

public class SetExample {
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();

        // add
        set.add("one");
        set.add("two");

        // contains
        System.out.println("Contains 'one': " + set.contains("one")); // true

        // iterator
        Iterator<String> iterator = set.iterator();
        System.out.print("Set elements: ");
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " "); // one two
        }
        System.out.println();

        // remove
        set.remove("one");
        System.out.println("After removing 'one', contains 'one': " + set.contains("one")); // false

        // size
        System.out.println("Set size: " + set.size()); // 1

        // isEmpty
        System.out.println("Is set empty: " + set.isEmpty()); // false

        // toArray
        Object[] array = set.toArray();
        System.out.print("Array elements: ");
        for (Object obj : array) {
            System.out.print(obj + " "); // two
        }
        System.out.println();

        // containsAll
        Set<String> otherSet = new HashSet<>();
        otherSet.add("two");
        System.out.println("Contains all elements of otherSet: " + set.containsAll(otherSet)); // true

        // addAll
        otherSet.add("three");
        set.addAll(otherSet);
        System.out.print("After addAll, set elements: ");
        for (String element : set) {
            System.out.print(element + " "); // two three
        }
        System.out.println();

        // clear
        set.clear();
        System.out.println("After clear, is set empty: " + set.isEmpty()); // true
    }
}

4. 总结

以上是对搜索树,Map,Set 的简单介绍,在后面会经常用到Map和Set接口,将会更深入的进行介绍。

相关文章:

  • 【C++项目】Rpc通信框架设计
  • Dest1ny漏洞库: 美团代付微信小程序系统任意文件读取漏洞
  • Linux相关概念和易错知识点(28)(线程控制、Linux下线程的底层)
  • unity学习46:反向动力学IK
  • 《Operating System Concepts》阅读笔记:p17-p25
  • 碰一碰发视频@技术原理与实现开发步骤
  • PaddlePaddle的OCR模型转onnx-转rknn模型_笔记4
  • 字节跳动AI编辑器Trae基本配置教程
  • Web安全|渗透测试|网络安全
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_alloc函数
  • SpringCloud系列教程:微服务的未来(二十四)Direct交换机、Topic交换机、声明队列交换机
  • 单片机常见bug记录(长期更新)
  • 【含文档+PPT+源码】基于SpringBoot+Vue的个性化健身助手系统
  • 商淘云连锁企业管理系统如何实现多门店统一管理
  • 机器学习_19 集成学习知识点总结
  • 赶AI大潮:在VSCode中使用DeepSeek及近百种模型的极简方法
  • 【射频仿真技巧学习笔记】Cadence修改图表背景、曲线颜色
  • ScoreFlow:通过基于分数的偏好优化掌握 LLM 智体工作流程
  • 架构师面试(三):订阅模型
  • Ubuntu中使用yum命令出现错误提示:Command ‘yum‘ not found
  • 人形机器人灵犀X2将走出实验室,首轮预售推出3个版本
  • 浙江台州女厅官林虹被决定逮捕,曾因直播带货广受关注
  • 全红婵旧伤复发,缺席全国跳水冠军赛
  • 深一度|有望冲击首轮秀?杨瀚森走出舒适圈站上大舞台
  • 盘中五味和人生五味,北京人艺《天下第一楼》将演第600场
  • 中国社科院国际合作局副局长廖凡调任世界经济与政治研究所所长