【集合系列】TreeMap 集合

TreeMap 集合

    • 1. 概述
    • 2. 方法
    • 3. 遍历方式
    • 4. 排序方式
    • 5. 代码示例1
    • 6. 代码示例2
    • 7. 代码示例3
    • 8. 注意事项
    • 9. 源码分析

其他集合类

父类 Map

集合类的遍历方式

TreeSet 集合

具体信息请查看 API 帮助文档

1. 概述

TreeMap 是 Java 中的一个集合类,它实现了 SortedMap 接口。它是基于红黑树的数据结构实现的,它能够保持其中的元素处于有序状态。

  • TreeMap 集合中的元素是以键值对的形式存储的,其中的键用于排序和唯一性的保证,而值则用于存储具体的数据。

  • TreeMap 根据键的自然顺序或者自定义的比较器来进行排序,使得在遍历 TreeMap 集合时能够有序地访问其中的元素。

TreeMap 集合的特点

  1. TreeMap 中的键必须是可比较的,要么实现了 Comparable 接口,要么在构造 TreeMap 时提供了自定义的比较器。

  2. TreeMap 中的键是唯一的,不允许重复的键存在。

  3. TreeMap 是基于红黑树实现的,因此在插入、删除和查找操作的时间复杂度均为 O(logn),具有较高的效率。

  4. TreeMap 中的元素是有序的,可以根据键来进行排序。

  5. TreeMap 不是线程安全的,如果需要在多线程环境下使用,需要进行额外的同步处理。

2. 方法

TreeMap集合是Map集合的子类,因此Map集合的方法TreeMap集合都能使用。

Map集合

方法名说明
V put(K key,V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数

3. 遍历方式

与共有的 集合遍历方式 一样

4. 排序方式

TreeMap集合和TreeSet集合一样,底层都是红黑树,因此排序方式一样

TreeSet 集合排序方式详解

  • 默认排序规则/自然排序

  • 比较器排序

5. 代码示例1

  • 代码示例
    需求:键:整数表示id;值:字符串表示商品名称
    要求:按照id的升序排列,按照id的降序排列
package text.text02;
/*TreeMap基本应用:
需求:键:整数表示id值:字符串表示商品名称
要求:按照id的升序排列,按照id的降序排列
*/import java.util.Comparator;
import java.util.TreeMap;public class text52 {public static void main(String[] args) {//自然排序(升序排列)System.out.println("方法一:自然排序");method1();        //{1001=平板, 1002=汽车, 1003=手机, 1004=飞机, 1005=电脑}//比较器排序(降序排列)System.out.println("方法二:比较器排序");method2();        //{1005=电脑, 1004=飞机, 1003=手机, 1002=汽车, 1001=平板}}//自然排序(Java底层默认的自然排序就是按照升序排列)public static void method1() {//创建集合并添加数据TreeMap<Integer, String> tm = new TreeMap<>();tm.put(1003, "手机");tm.put(1005, "电脑");tm.put(1001, "平板");tm.put(1002, "汽车");tm.put(1004, "飞机");System.out.println(tm);}//比较器排序(当Java底层默认的自然排列不能满足需求时,采用比较器排列)public static void method2() {//创建集合(在创建对象的时候指定比较器规则)TreeMap<Integer, String> tm = new TreeMap<>(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});//添加数据tm.put(1003, "手机");tm.put(1005, "电脑");tm.put(1001, "平板");tm.put(1002, "汽车");tm.put(1004, "飞机");System.out.println(tm);}
}
  • 输出结果
    • 方法一:自然排序
      在这里插入图片描述

    • 方法二:比较器排序
      在这里插入图片描述

6. 代码示例2

  • 代码示例
    需求:键:学生对象;值:籍贯
    要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名同年龄视为同一个人
package text.text02;import java.util.*;/*
需求:键:学生对象值:籍贯
要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名同年龄视为同一个人*/
public class text53 {public static void main(String[] args) {//自然排序System.out.println("方法一:自然排序");method1();//比较器排序System.out.println("方法二:比较器排序");method2();}//自然排序 (Java底层默认的自然排序就是按照升序排列,自定义对象时,需要在Javabean类中实现Comparable接口并重写里面的CompareTo方法)public static void method1() {//创建学生对象Student8 student1 = new Student8("zhangsan", 10);Student8 student2 = new Student8("lisi", 10);Student8 student3 = new Student8("wangwu", 11);Student8 student4 = new Student8("liubei", 9);Student8 student5 = new Student8("guanyu", 13);Student8 student6 = new Student8("guanyu", 13);//创建集合对象TreeMap<Student8, String> tm = new TreeMap<>();//添加数据tm.put(student1, "陕西");tm.put(student2, "湖南");tm.put(student3, "河北");tm.put(student4, "江苏");tm.put(student5, "北京");tm.put(student6, "湖南");//遍历输出集合Set<Map.Entry<Student8, String>> entries = tm.entrySet();for (Map.Entry<Student8, String> entry : entries) {Student8 key = entry.getKey();String value = entry.getValue();System.out.println(key + " = " + value);}}//比较器排序(当Java底层默认的自然排列不能满足需求时,采用比较器排列,在创建对象时,指定比较规则)public static void method2() {//创建学生对象Student8 student1 = new Student8("zhangsan", 10);Student8 student2 = new Student8("lisi", 10);Student8 student3 = new Student8("wangwu", 11);Student8 student4 = new Student8("liubei", 9);Student8 student5 = new Student8("guanyu", 13);Student8 student6 = new Student8("guanyu", 13);//创建集合对象TreeMap<Student8, String> tm = new TreeMap<>(new Comparator<Student8>() {@Override//按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名同年龄视为同一个人public int compare(Student8 o1, Student8 o2) {//o1:表示当前要添加的元素//o2:表示已经在红黑树存在的元素//返回值://负数:表示当前要添加的数据是小的,存左边//正数:表示当前要添加的数据是大的,存右边//0:表示当前要添加的元素已经存在,舍弃int i = o1.getAge() - o2.getAge();i = i == 0 ? o1.getName().compareTo(o2.getName()) : i;return i;}});//添加数据tm.put(student1, "陕西");tm.put(student2, "湖南");tm.put(student3, "河北");tm.put(student4, "江苏");tm.put(student5, "北京");tm.put(student6, "湖南");//遍历输出集合Set<Map.Entry<Student8, String>> entries = tm.entrySet();for (Map.Entry<Student8, String> entry : entries) {Student8 key = entry.getKey();String value = entry.getValue();System.out.println(key + " = " + value);}}
}//学生对象
class Student8 implements Comparable<Student8> {private String name;private int age;public Student8() {}public Student8(String name, int age) {this.name = name;this.age = age;}/*** 获取** @return name*/public String getName() {return name;}/*** 设置** @param name*/public void setName(String name) {this.name = name;}/*** 获取** @return age*/public int getAge() {return age;}/*** 设置** @param age*/public void setAge(int age) {this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student8 student8 = (Student8) o;return age == student8.age && Objects.equals(name, student8.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}public String toString() {return "Student8{name = " + name + ", age = " + age + "}";}@Override//按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名同年龄视为同一个人public int compareTo(Student8 o) {//this:表示当前要添加的元素//o:表示已经在红黑树中的元素//返回值://负数:表示当前要添加的数据是小的,存左边//正数:表示当前要添加的数据是大的,存右边//0:表示当前要添加的元素已经存在,舍弃int i = this.getAge() - o.getAge();i = i == 0 ? this.getName().compareTo(o.getName()) : i;return i;}
}
  • 输出结果
    • 方法一:自然排序
      在这里插入图片描述

    • 方法二:比较器排序
      在这里插入图片描述

7. 代码示例3

  • 代码示例
    统计个数:
    需求:字符串“aababcabcdabcde”,请统计字符串中每一个字符出现的次数,并按照如下格式输出。
    输出结果:a(5)b(4)c(3)d(2)e(1)
package text.text02;import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeMap;/*
统计个数:
需求:字符串“aababcabcdabcde”,请统计字符串中每一个字符出现的次数,并按照如下格式输出。输出结果:a(5)b(4)c(3)d(2)e(1)新的统计思想:利用Map集合进行统计      (键:表示要统计的内容;值:表示次数)如果题目中没有要求对结果进行排序,默认使用HashMap如果题目中要求对结果进行排序,则使用TreeMap*/
public class text54 {public static void main(String[] args) {//创建数组存储每一个字符char[] arr = {'a', 'b', 'c', 'd', 'e'};//定义一个变量用于记录字符串String str = "aababcabcdabcde";//创建集合TreeMap<Character, Integer> tm = new TreeMap<>();for (int i = 0; i < str.length(); i++) {//如果双列集合中存在该字符,则获取双列集合中该字符的次数并将次数+1if (tm.containsKey(str.charAt(i))) {//获取双列集合中该字符的次数Integer value = tm.get(str.charAt(i));//将次数+1value++;//用新次数覆盖原次数tm.put(str.charAt(i), value);}//如果双列集合中存在该字符,则添加该字符并将次数改为1else {tm.put(str.charAt(i), 1);}}//遍历集合//1.利用StringBuilder修改输出格式//创建StringBuilder对象StringBuilder sb = new StringBuilder();Set<Map.Entry<Character, Integer>> entries = tm.entrySet();for (Map.Entry<Character, Integer> entry : entries) {//获取集合里的键Character key = entry.getKey();//获取集合里的值Integer value = entry.getValue();//将数据按照需求格式添加进StringBuilder集合sb.append(key).append("(").append(value).append(")");}System.out.println("1.利用StringBuilder修改输出格式:");System.out.println(sb);                  //a(5)b(4)c(3)d(2)e(1)//2.利用StringJoiner修改输出格式//创建StringJoiner对象StringJoiner sj = new StringJoiner("", "", "");Set<Character> set = tm.keySet();for (Character key : set) {Integer value = tm.get(key);//将数据按照需求格式添加进StringJoiner集合sj.add(key + "").add("(").add(value + "").add(")");//+" "是为了将key和value转换成字符串}System.out.println("2.利用StringJoiner修改输出格式:");System.out.println(sj);       //a(5)b(4)c(3)d(2)e(1)}
}
  • 输出结果
    • 1.利用StringBuilder修改输出格式:
      在这里插入图片描述

    • 2.利用StringJoiner修改输出格式:
      在这里插入图片描述

8. 注意事项

  1. 键的唯一性:TreeMap 中的键是唯一的,不允许重复的键存在。如果尝试插入一个已经存在的键,新的值将会覆盖旧的值。如果需要存储允许重复键的情况,可以考虑使用其他集合类如 ArrayList 或者 HashMap。

  2. 键的可比较性:TreeMap 要求集合中的键必须是可比较的,要么实现了 Comparable 接口,要么在构造 TreeMap 时提供了自定义的比较器。如果键没有实现 Comparable 接口,并且没有提供自定义的比较器,则在插入元素或者进行比较操作时会抛出 ClassCastException 异常。

  3. 线程安全性:TreeMap 不是线程安全的,如果需要在多线程环境下使用 TreeMap,需要进行额外的同步处理。可以考虑使用 Collections 类的 synchronizedSortedMap 方法包装 TreeMap,或者使用并发集合类如 ConcurrentHashMap。

  4. 迭代顺序:TreeMap 中的元素是有序的,可以根据键来进行排序。通过 iterator 或者 forEach 遍历 TreeMap 时,元素会按照键的顺序以升序进行遍历。

  5. 性能开销:由于 TreeMap 的底层是红黑树,插入、删除和查找操作的时间复杂度均为 O(logn),相比于其他集合类可能会有较高的性能开销。如果对性能有较高要求,可以考虑使用其他集合类。

9. 源码分析

  1. TreeMap中每一个节点的内部属性

    K key;					//键
    V value;				//值
    Entry<K,V> left;		//左子节点
    Entry<K,V> right;		//右子节点
    Entry<K,V> parent;		//父节点
    boolean color;			//节点的颜色
    
  2. TreeMap类中中要知道的一些成员变量

    public class TreeMap<K,V>{//比较器对象private final Comparator<? super K> comparator;//根节点private transient Entry<K,V> root;//集合的长度(节点的个数)private transient int size = 0;
  3. 空参构造

    //空参构造就是没有传递比较器对象
    public TreeMap() {comparator = null;
    }
    
  4. 带参构造

    	//带参构造就是传递了比较器对象。public TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}
    
  5. 添加元素

    	public V put(K key, V value) {return put(key, value, true);}//参数一:键//参数二:值//参数三:当键重复的时候,是否需要覆盖值//		true:覆盖//		false:不覆盖private V put(K key, V value, boolean replaceOld) {//获取根节点的地址值,赋值给局部变量tEntry<K,V> t = root;//判断根节点是否为null//如果为null,表示当前是第一次添加,会把当前要添加的元素,当做根节点//如果不为null,表示当前不是第一次添加,跳过这个判断继续执行下面的代码if (t == null) {//方法的底层,会创建一个Entry对象,把他当做根节点addEntryToEmptyMap(key, value);//表示此时没有覆盖任何的元素return null;}//表示两个元素的键比较之后的结果int cmp;//表示当前要添加节点的父节点Entry<K,V> parent;//表示当前的比较规则//如果我们是采取默认的自然排序,那么此时comparator记录的是null,cpr记录的也是null//如果我们是采取比较器排序方式,那么此时comparator记录的是就是比较器Comparator<? super K> cpr = comparator;//表示判断当前是否有比较器对象//如果传递了比较器对象,就执行if里面的代码,此时以比较器的规则为准//如果没有传递比较器对象,就执行else里面的代码,此时以自然排序的规则为准if (cpr != null) {do {parent = t;cmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;else {V oldValue = t.value;if (replaceOld || oldValue == null) {t.value = value;}return oldValue;}} while (t != null);} else {//把键进行强转,强转成Comparable类型的//要求:键必须要实现Comparable接口,如果没有实现这个接口//此时在强转的时候,就会报错。Comparable<? super K> k = (Comparable<? super K>) key;do {//把根节点当做当前节点的父节点parent = t;//调用compareTo方法,比较根节点和当前要添加节点的大小关系cmp = k.compareTo(t.key);if (cmp < 0)//如果比较的结果为负数//那么继续到根节点的左边去找t = t.left;else if (cmp > 0)//如果比较的结果为正数//那么继续到根节点的右边去找t = t.right;else {//如果比较的结果为0,会覆盖V oldValue = t.value;if (replaceOld || oldValue == null) {t.value = value;}return oldValue;}} while (t != null);}//就会把当前节点按照指定的规则进行添加addEntry(key, value, parent, cmp < 0);return null;}	private void addEntry(K key, V value, Entry<K, V> parent, boolean addToLeft) {Entry<K,V> e = new Entry<>(key, value, parent);if (addToLeft)parent.left = e;elseparent.right = e;//添加完毕之后,需要按照红黑树的规则进行调整fixAfterInsertion(e);size++;modCount++;}private void fixAfterInsertion(Entry<K,V> x) {//因为红黑树的节点默认就是红色的x.color = RED;//按照红黑规则进行调整//parentOf:获取x的父节点//parentOf(parentOf(x)):获取x的爷爷节点//leftOf:获取左子节点while (x != null && x != root && x.parent.color == RED) {//判断当前节点的父节点是爷爷节点的左子节点还是右子节点//目的:为了获取当前节点的叔叔节点if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {//表示当前节点的父节点是爷爷节点的左子节点//那么下面就可以用rightOf获取到当前节点的叔叔节点Entry<K,V> y = rightOf(parentOf(parentOf(x)));if (colorOf(y) == RED) {//叔叔节点为红色的处理方案//把父节点设置为黑色setColor(parentOf(x), BLACK);//把叔叔节点设置为黑色setColor(y, BLACK);//把爷爷节点设置为红色setColor(parentOf(parentOf(x)), RED);//把爷爷节点设置为当前节点x = parentOf(parentOf(x));} else {//叔叔节点为黑色的处理方案//表示判断当前节点是否为父节点的右子节点if (x == rightOf(parentOf(x))) {//表示当前节点是父节点的右子节点x = parentOf(x);//左旋rotateLeft(x);}setColor(parentOf(x), BLACK);setColor(parentOf(parentOf(x)), RED);rotateRight(parentOf(parentOf(x)));}} else {//表示当前节点的父节点是爷爷节点的右子节点//那么下面就可以用leftOf获取到当前节点的叔叔节点Entry<K,V> y = leftOf(parentOf(parentOf(x)));if (colorOf(y) == RED) {setColor(parentOf(x), BLACK);setColor(y, BLACK);setColor(parentOf(parentOf(x)), RED);x = parentOf(parentOf(x));} else {if (x == leftOf(parentOf(x))) {x = parentOf(x);rotateRight(x);}setColor(parentOf(x), BLACK);setColor(parentOf(parentOf(x)), RED);rotateLeft(parentOf(parentOf(x)));}}}//把根节点设置为黑色root.color = BLACK;}
    
  6. 课堂思考问题:

    1. TreeMap添加元素的时候,键是否需要重写hashCode和equals方法?

    此时是不需要重写的。

    1. HashMap是哈希表结构的,JDK8开始由数组,链表,红黑树组成的。
      既然有红黑树,HashMap的键是否需要实现Compareable接口或者传递比较器对象呢?

    不需要的。
    因为在HashMap的底层,默认是利用哈希值的大小关系来创建红黑树的

    1. TreeMap和HashMap谁的效率更高?

    如果是最坏情况,添加了8个元素,这8个元素形成了链表,此时TreeMap的效率要更高
    但是这种情况出现的几率非常的少。
    一般而言,还是HashMap的效率要更高。

    1. 你觉得在Map集合中,java会提供一个如果键重复了,不会覆盖的put方法呢?

    此时putIfAbsent本身不重要。

    传递一个思想:
    代码中的逻辑都有两面性,如果我们只知道了其中的A面,而且代码中还发现了有变量可以控制两面性的发生。
    那么该逻辑一定会有B面。

     习惯:boolean类型的变量控制,一般只有AB两面,因为boolean只有两个值int类型的变量控制,一般至少有三面,因为int可以取多个值。	
    
    1. 三种双列集合,以后如何选择?
      HashMap LinkedHashMap TreeMap

    默认:HashMap(效率最高)
    如果要保证存取有序:LinkedHashMap
    如果要进行排序:TreeMap

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/254659.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

修改SpringBoot中默认依赖版本

例如SpringBoot2.7.2中ElasticSearch版本是7.17.4 我希望把它变成7.6.1

机器学习算法之支持向量机(SVM)

SVM恐怕大家即使不熟悉&#xff0c;也听说过这个大名吧&#xff0c;这一节我们就介绍这相爱相杀一段内容。 前言&#xff1a;在介绍一个新内容之SVM前&#xff0c;我们不觉映入眼帘的问题是为什么要引入SVM&#xff1f;吃的香&#xff0c;睡的着的情况下&#xff0c;肯定不会是…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Slider组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Slider组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Slider组件 滑动条组件&#xff0c;通常用于快速调节设置值&#xff0c;如音量调…

揭开Markdown的秘籍:标题|文字样式|列表

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;Markdown指南、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️Markdown 标题二. ⛳️Markdown 文字样式2.1 &#x1f514;斜体2.2 &…

谷歌发布AI新品Gemini及收费模式;宜家推出基于GPT的AI家装助手

&#x1f989; AI新闻 &#x1f680; 谷歌发布AI新品Gemini及收费模式 摘要&#xff1a;谷歌宣布将原有的AI产品Bard更名为Gemini&#xff0c;开启了谷歌的AI新篇章。同时推出了强化版的聊天机器人Gemini Advanced&#xff0c;支持更复杂的任务处理&#xff0c;提供了两个月的…

【Makefile语法 01】程序编译与执行

目录 一、编译原理概述 二、编译过程分析 三、编译动静态库 四、执行过程分析 一、编译原理概述 make&#xff1a; 一个GCC工具程序&#xff0c;它会读 makefile 脚本来确定程序中的哪个部分需要编译和连接&#xff0c;然后发布必要的命令。它读出的脚本&#xff08;叫做 …

JavaWeb02-MyBatis

目录 一、MyBatis 1.概述 2.JavaEE三层架构简单介绍 &#xff08;1&#xff09;表现层 &#xff08;2&#xff09;业务层 &#xff08;3&#xff09;持久层 3.框架 4.优势 &#xff08;1&#xff09;JDBC的劣势 &#xff08;2&#xff09;MyBatis优化 5.使用 &#…

Linux操作系统基础(六):Linux常见命令(一)

文章目录 Linux常见命令 一、命令结构 二、ls命令 三、cd命令 四、mkdir命令 五、touch命令 六、rm命令 七、cp命令 八、mv命令 九、cat命令 十、more命令 Linux常见命令 一、命令结构 command [-options] [parameter]说明: command : 命令名, 相应功能的英文单词…

2024.2.4 awd总结

学习一下awd的靶机信息 防御阶段 感觉打了几次awd&#xff0c;前面阶段还算比较熟练 1.ssh连接 靶机登录 修改密码 [root8 ~]# passwd Changing password for user root. New password: Retype new password: 2.xftp连接 备份网站源码 xftp可以直接拖过来 我觉得这步还…

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

题目描述 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 题目示例 输入&#xff1a;inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出&a…

【前沿技术杂谈:多模态文档基础模型】使用多模态文档基础模型彻底改变文档 AI

【前沿技术杂谈&#xff1a;多模态文档基础模型】使用多模态文档基础模型彻底改变文档 AI 从文本到多模态模型&#xff1a;文档 AI 逐渐发展新技能。行业领先的型号Document AI 的下一步&#xff1a;开发通用和统一框架 您是否曾经被包含不同信息&#xff08;如应付账款、日期、…

k8s-常用工作负载控制器(更高级管理Pod)

一、工作负载控制器是什么&#xff1f; 二、Deploymennt控制器&#xff1a;介绍与部署应用 部署 三、Deployment控制器&#xff1a;滚动升级、零停机 方式一&#xff1a; 通个加入健康检查可以&#xff0c;看到&#xff0c;nginx容器逐个被替代&#xff0c;最终每个都升级完成&…

【k8s系列】(202402) 证书apiserver_client_certificate_expiration_seconds

apiserver_client_certificate_expiration_second证书定义的位置&#xff1a;kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509.go at 244fbf94fd736e94071a77a8b7c91d81163249d4 kubernetes/kubernetes (github.com) apiserver_client_certi…

【51单片机】外部中断和定时器中断

目录 中断系统中断介绍中断概念 中断结构及相关寄存器中断结构中断相关寄存器 外部中断实验外部中断配置软件设计实验现象 定时器中断定时器介绍51 单片机定时器原理51 单片机定时/计数器结构51 单片机定时/计数器的工作方式 定时器配置硬件设计软件设计实验现象 中断系统 本章…

【http】2、http request header Origin 属性、跨域 CORS、同源、nginx 反向代理、预检请求

文章目录 一、Origin 含义二、跨源资源共享&#xff1a;**Cross-Origin Resource Sharing** CORS2.1 跨域的定义2.2 功能概述2.3 场景示例2.3.1 简单请求2.3.2 Preflighted requests&#xff1a;预检请求 2.4 header2.4.1 http request header2.4.1.1 Origin2.4.1.2 Access-Con…

[每周一更]-(第86期):PostgreSQL入门学习和对比MySQL

入门学习PostgreSQL可以遵循以下步骤&#xff1a; 安装 PostgreSQL&#xff1a; 首先&#xff0c;你需要在你的计算机上安装 PostgreSQL。你可以从 PostgreSQL 官方网站 下载适合你操作系统的安装包&#xff0c;并按照官方文档的指导进行安装。 学习 SQL&#xff1a; PostgreS…

【分布式】雪花算法学习笔记

雪花算法学习笔记 来源 https://pdai.tech/md/algorithm/alg-domain-id-snowflake.html概述 雪花算法是推特开源的分布式ID生成算法&#xff0c;以划分命名空间的方式将64位分割成多个部分&#xff0c;每一个部分代表不同的含义&#xff0c;这种就是将64位划分成不同的段&…

按键扫描16Hz-单片机通用模板

按键扫描16Hz-单片机通用模板 一、按键扫描的原理1、直接检测高低电平类型2、矩阵扫描类型3、ADC检测类型二、key.c的实现1、void keyScan(void) 按键扫描函数①void FHiKey(void) 按键按下功能②void FSameKey(void) 按键长按功能③void FLowKey(void) 按键释放功能三、key.h的…

pycharm像jupyter一样在控制台查看后台变量

更新下&#xff1a;这个一劳永逸不用一个一个改 https://blog.csdn.net/Onlyone_1314/article/details/109347481 右上角运行

力扣刷题之旅:进阶篇(三)

力扣&#xff08;LeetCode&#xff09;是一个在线编程平台&#xff0c;主要用于帮助程序员提升算法和数据结构方面的能力。以下是一些力扣上的入门题目&#xff0c;以及它们的解题代码。 --点击进入刷题地址 一、动态规划&#xff08;DP&#xff09; 首先&#xff0c;让我们来…