{
    "version": "https://jsonfeed.org/version/1",
    "title": "欢迎访问小站",
    "subtitle": "Notes & Sharing",
    "icon": "https://blog.ceciljxsu.icu/images/favicon.ico",
    "description": "",
    "home_page_url": "https://blog.ceciljxsu.icu",
    "items": [
        {
            "id": "https://blog.ceciljxsu.icu/2023/11/12/%E8%BF%91%E4%B8%96%E4%BB%A3%E6%95%B0/%E8%BF%91%E4%B8%96%E4%BB%A3%E6%95%B0-%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5/",
            "url": "https://blog.ceciljxsu.icu/2023/11/12/%E8%BF%91%E4%B8%96%E4%BB%A3%E6%95%B0/%E8%BF%91%E4%B8%96%E4%BB%A3%E6%95%B0-%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5/",
            "title": "近世代数-基础概念",
            "date_published": "2023-11-12T13:49:00.000Z",
            "content_html": "<h1 id=\"集合\"><a class=\"anchor\" href=\"#集合\">#</a> 集合</h1>\n<h2 id=\"概念与符号表示\"><a class=\"anchor\" href=\"#概念与符号表示\">#</a> 概念与符号表示</h2>\n<ul>\n<li>集合：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo separator=\"true\">,</mo><mi>B</mi><mo separator=\"true\">,</mo><mi>C</mi></mrow><annotation encoding=\"application/x-tex\">A, B, C</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8777699999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span></span></span></span></li>\n<li>元素：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>a</mi><mo separator=\"true\">,</mo><mi>b</mi><mo separator=\"true\">,</mo><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">a, b, c</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">c</span></span></span></span></li>\n<li>空集：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∅</mi></mrow><annotation encoding=\"application/x-tex\">\\varnothing</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.66334em;vertical-align:-0.08167em;\"></span><span class=\"mord amsrm\">∅</span></span></span></span></li>\n<li>元素与集合的关系：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>∈</mo><mo separator=\"true\">,</mo><mo>∉</mo></mrow><annotation encoding=\"application/x-tex\">\\in, \\not\\in</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mrel\">∈</span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\"><span class=\"mord vbox\"><span class=\"thinbox\"><span class=\"rlap\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"inner\"><span class=\"mrel\"></span></span><span class=\"fix\"></span></span></span></span></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mrel\">∈</span></span></span></span></li>\n<li>集合之间的关系：\n<ul>\n<li>子集和超集：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>⊆</mo><mo separator=\"true\">,</mo><mo>⊇</mo></mrow><annotation encoding=\"application/x-tex\">\\subseteq, \\supseteq</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719400000000001em;vertical-align:-0.13597em;\"></span><span class=\"mrel\">⊆</span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8304100000000001em;vertical-align:-0.19444em;\"></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">⊇</span></span></span></span></li>\n<li>真子集和真超集：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>⫋</mo><mo separator=\"true\">,</mo><mo>⫌</mo></mrow><annotation encoding=\"application/x-tex\">\\subsetneqq, \\supsetneqq</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.07864em;vertical-align:-0.28481em;\"></span><span class=\"mrel amsrm\">⫋</span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.07864em;vertical-align:-0.28481em;\"></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel amsrm\">⫌</span></span></span></span> 或简写 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>⊊</mo><mo separator=\"true\">,</mo><mo>⊋</mo></mrow><annotation encoding=\"application/x-tex\">\\subsetneq, \\supsetneq</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719400000000001em;vertical-align:-0.13597em;\"></span><span class=\"mrel amsrm\">⊊</span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8304100000000001em;vertical-align:-0.19444em;\"></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel amsrm\">⊋</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>⊂</mo></mrow><annotation encoding=\"application/x-tex\">\\subset</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mrel\">⊂</span></span></span></span>（子集或真子集），<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>⊃</mo></mrow><annotation encoding=\"application/x-tex\">\\supset</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mrel\">⊃</span></span></span></span>（超集或真超集）</li>\n</ul>\n</li>\n<li>集合运算：\n<ul>\n<li>并集：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>∪</mo></mrow><annotation encoding=\"application/x-tex\">\\cup</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.55556em;vertical-align:0em;\"></span><span class=\"mord\">∪</span></span></span></span></li>\n<li>交集：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>∩</mo></mrow><annotation encoding=\"application/x-tex\">\\cap</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.55556em;vertical-align:0em;\"></span><span class=\"mord\">∩</span></span></span></span></li>\n</ul>\n</li>\n</ul>\n<h3 id=\"定理-1\"><a class=\"anchor\" href=\"#定理-1\">#</a> 定理 1</h3>\n<p>两个集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo separator=\"true\">,</mo><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A, B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8777699999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 相等的充要条件：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>A</mi><mo>=</mo><mi>B</mi><mo>⇔</mo><mi>A</mi><mo>⊂</mo><mi>B</mi><mo separator=\"true\">,</mo><mi>B</mi><mo>⊂</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A = B \\Leftrightarrow A \\subset B, B \\subset A\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">⇔</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.72243em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">⊂</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8777699999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">⊂</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span></span></p>\n<h2 id=\"定义-1-集合的积\"><a class=\"anchor\" href=\"#定义-1-集合的积\">#</a> 定义 1 - 集合的积</h2>\n<p>我们称</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub><mo>×</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>×</mo><msub><mi>A</mi><mi>n</mi></msub><mo>=</mo><mo stretchy=\"false\">{</mo><mo stretchy=\"false\">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">∣</mi><msub><mi>a</mi><mi>i</mi></msub><mo>∈</mo><msub><mi>A</mi><mi>i</mi></msub><mo stretchy=\"false\">}</mo></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2 \\times ... \\times A_n = \\{(a_1, a_2, ..., a_n) | a_i \\in A_i\\}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mord\">∣</span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.31166399999999994em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">i</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.31166399999999994em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">i</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">}</span></span></span></span></span></p>\n<p>为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 个集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>A</mi><mn>2</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>A</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">A_1, A_2, ..., A_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8777699999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 的<strong>积（或笛卡尔积）</strong>。</p>\n<h3 id=\"定理-2\"><a class=\"anchor\" href=\"#定理-2\">#</a> 定理 2</h3>\n<p>一般地，如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∣</mi><mi>A</mi><mi mathvariant=\"normal\">∣</mi><mo>=</mo><mi>m</mi><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">∣</mi><mi>B</mi><mi mathvariant=\"normal\">∣</mi><mo>=</mo><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">|A| = m, |B| = n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∣</span><span class=\"mord mathnormal\">A</span><span class=\"mord\">∣</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">∣</span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mord\">∣</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span>，那么<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∣</mi><mi>A</mi><mo>×</mo><mi>B</mi><mi mathvariant=\"normal\">∣</mi><mo>=</mo><mi>m</mi><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">|A \\times B| = mn</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∣</span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mord\">∣</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord mathnormal\">n</span></span></span></span>。</p>\n<h2 id=\"习题\"><a class=\"anchor\" href=\"#习题\">#</a> 习题</h2>\n<ol>\n<li class=\"quiz essay\">\n<p>设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi><mo>⊂</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">B \\subset A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.72243em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">⊂</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span>，但 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 不是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 的真子集，这种情况什么情形下出现？</p>\n<blockquote>\n<p>当 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>=</mo><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A = B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span> 时。</p>\n</blockquote>\n</li>\n<li class=\"quiz fill\">\n<p>设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>⊂</mo><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">A \\subset B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.72243em;vertical-align:-0.0391em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">⊂</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span>，则 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>∩</mo><mi>B</mi><mo>=</mo></mrow><annotation encoding=\"application/x-tex\">A \\cap B =</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∩</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span></span></span></span> <span class=\"gap\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span></span>，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>∪</mo><mi>B</mi><mo>=</mo></mrow><annotation encoding=\"application/x-tex\">A \\cup B =</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∪</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span></span></span></span> <span class=\"gap\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>B</mi></mrow><annotation encoding=\"application/x-tex\">B</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span></span></span></span></span></p>\n</li>\n</ol>\n<h1 id=\"映射\"><a class=\"anchor\" href=\"#映射\">#</a> 映射</h1>\n<h2 id=\"定义-1-映射\"><a class=\"anchor\" href=\"#定义-1-映射\">#</a> 定义 1 - 映射</h2>\n<p>设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϕ</mi></mrow><annotation encoding=\"application/x-tex\">\\phi</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">ϕ</span></span></span></span> 是从笛卡尔积 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub><mo>×</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>×</mo><msub><mi>A</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2 \\times ... \\times A_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 到集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的一个法则，如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub><mo>×</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>×</mo><msub><mi>A</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2 \\times ... \\times A_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 中的每一个元素 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">(a_1, a_2, ..., a_n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span> 都有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 中唯一的元素 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">d</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">d</span></span></span></span> 与之对应，那么则称 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϕ</mi></mrow><annotation encoding=\"application/x-tex\">\\phi</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">ϕ</span></span></span></span> 是从 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub><mo>×</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>×</mo><msub><mi>A</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2 \\times ... \\times A_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的一个<strong>映射</strong>。</p>\n<h2 id=\"定义-2-传统定义\"><a class=\"anchor\" href=\"#定义-2-传统定义\">#</a> 定义 2 - 传统定义</h2>\n<p>设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϕ</mi></mrow><annotation encoding=\"application/x-tex\">\\phi</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">ϕ</span></span></span></span> 是从集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 到集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的一个法则，如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 中的每一个元素 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>a</mi></mrow><annotation encoding=\"application/x-tex\">a</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">a</span></span></span></span> 都有 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 中唯一的元素 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">d</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">d</span></span></span></span> 与之对应，那么则称 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϕ</mi></mrow><annotation encoding=\"application/x-tex\">\\phi</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">ϕ</span></span></span></span> 是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的一个<strong>映射</strong>。</p>\n<p><strong>定义 1 和定义 2 可以互相推导，两者是等价的。</strong></p>\n<p><strong>推导：</strong></p>\n<ol>\n<li>定义 1 中，当 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">n=1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span> 时，推导出定义 2。</li>\n<li>定义 2 中的集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span>，可以看成是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub><mo>×</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>×</mo><msub><mi>A</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2 \\times ... \\times A_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 的笛卡尔积结果，笛卡尔积的结果也是一个集合，则可推导出定义 1。</li>\n</ol>\n<h3 id=\"例子\"><a class=\"anchor\" href=\"#例子\">#</a> 例子</h3>\n<ul>\n<li>\n<p><strong>例 1</strong> 设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>=</mo><msub><mi>A</mi><mn>2</mn></msub><mo>=</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>=</mo><msub><mi>A</mi><mi>n</mi></msub><mo>=</mo><mi>D</mi><mo>=</mo><mi mathvariant=\"double-struck\">R</mi></mrow><annotation encoding=\"application/x-tex\">A_1 = A_2 = ... = A_n = D = \\mathbb{R}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.36687em;vertical-align:0em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68889em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord mathbb\">R</span></span></span></span></span>，则</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>ϕ</mi><mo stretchy=\"false\">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy=\"false\">)</mo><mo>=</mo><msubsup><mi>a</mi><mn>1</mn><mn>2</mn></msubsup><mo>+</mo><msubsup><mi>a</mi><mn>2</mn><mn>2</mn></msubsup><mo>+</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>+</mo><msubsup><mi>a</mi><mi>n</mi><mn>2</mn></msubsup></mrow><annotation encoding=\"application/x-tex\">\\phi(a_1, a_2, ..., a_n) = a_1^2 + a_2^2 + ... + a_n^2\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ϕ</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.1111079999999998em;vertical-align:-0.247em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641079999999999em;\"><span style=\"top:-2.4530000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.247em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.1111079999999998em;vertical-align:-0.247em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641079999999999em;\"><span style=\"top:-2.4530000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.247em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.1111079999999998em;vertical-align:-0.247em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641079999999999em;\"><span style=\"top:-2.4530000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.247em;\"><span></span></span></span></span></span></span></span></span></span></span></p>\n<p>是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub><mo>×</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>×</mo><msub><mi>A</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2 \\times ... \\times A_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的映射。<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϕ</mi></mrow><annotation encoding=\"application/x-tex\">\\phi</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">ϕ</span></span></span></span> 实际上就是一个多元函数。</p>\n</li>\n<li>\n<p><strong>例 2</strong> 设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>=</mo><mo stretchy=\"false\">{</mo><mtext>东，西</mtext><mo stretchy=\"false\">}</mo><mo separator=\"true\">,</mo><msub><mi>A</mi><mn>2</mn></msub><mo>=</mo><mo stretchy=\"false\">{</mo><mtext>南</mtext><mo stretchy=\"false\">}</mo><mo separator=\"true\">,</mo><mi>D</mi><mo>=</mo><mo stretchy=\"false\">{</mo><mtext>高</mtext><mo separator=\"true\">,</mo><mtext>低</mtext><mo stretchy=\"false\">}</mo></mrow><annotation encoding=\"application/x-tex\">A_1 = \\{东，西\\}, A_2 = \\{南\\}, D = \\{高, 低\\}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{</span><span class=\"mord cjk_fallback\">东</span><span class=\"mord cjk_fallback\">，</span><span class=\"mord cjk_fallback\">西</span><span class=\"mclose\">}</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{</span><span class=\"mord cjk_fallback\">南</span><span class=\"mclose\">}</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{</span><span class=\"mord cjk_fallback\">高</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord cjk_fallback\">低</span><span class=\"mclose\">}</span></span></span></span>，则</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><msub><mi>ϕ</mi><mn>1</mn></msub><mo stretchy=\"false\">(</mo><mtext>西</mtext><mo separator=\"true\">,</mo><mtext>南</mtext><mo stretchy=\"false\">)</mo><mo>=</mo><mtext>高</mtext></mrow><annotation encoding=\"application/x-tex\">\\phi_1(西, 南) = 高\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord cjk_fallback\">西</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord cjk_fallback\">南</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord cjk_fallback\">高</span></span></span></span></span></p>\n<p>不是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的映射。而</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><msub><mi>ϕ</mi><mn>2</mn></msub><mo stretchy=\"false\">(</mo><mtext>西</mtext><mo separator=\"true\">,</mo><mtext>南</mtext><mo stretchy=\"false\">)</mo><mo>=</mo><mtext>高</mtext><mo separator=\"true\">,</mo><msub><mi>ϕ</mi><mn>2</mn></msub><mo stretchy=\"false\">(</mo><mtext>东</mtext><mo separator=\"true\">,</mo><mtext>南</mtext><mo stretchy=\"false\">)</mo><mo>=</mo><mtext>低</mtext></mrow><annotation encoding=\"application/x-tex\">\\phi_2(西, 南) = 高, \\phi_2(东, 南) = 低\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord cjk_fallback\">西</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord cjk_fallback\">南</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord cjk_fallback\">高</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord cjk_fallback\">东</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord cjk_fallback\">南</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord cjk_fallback\">低</span></span></span></span></span></p>\n<p>是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的映射。</p>\n</li>\n<li>\n<p><strong>例 3</strong> 设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>=</mo><mi>D</mi><mo>=</mo><mi mathvariant=\"double-struck\">R</mi></mrow><annotation encoding=\"application/x-tex\">A_1 = D = \\mathbb{R}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68889em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord mathbb\">R</span></span></span></span></span>，则</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>ϕ</mi><mo stretchy=\"false\">(</mo><mi>a</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mn>1</mn><mo separator=\"true\">,</mo><mi>a</mi><mo mathvariant=\"normal\">≠</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">\\phi(a) = 1, a \\neq 1\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ϕ</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">a</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\"><span class=\"mrel\"><span class=\"mord vbox\"><span class=\"thinbox\"><span class=\"rlap\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"inner\"><span class=\"mrel\"></span></span><span class=\"fix\"></span></span></span></span></span><span class=\"mrel\">=</span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span></span></p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>ϕ</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>=</mo><mi>b</mi><mo separator=\"true\">,</mo><msup><mi>b</mi><mn>2</mn></msup><mo>=</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">\\phi(1) = b, b^2 = 1\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ϕ</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0585479999999998em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">b</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641079999999999em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span></span></p>\n<p>不是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub></mrow><annotation encoding=\"application/x-tex\">A_1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的映射。因为<strong>像必须要唯一</strong>，而 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϕ</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>=</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">\\phi(1) = 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ϕ</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span> 或 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ϕ</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>=</mo><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">\\phi(1) = -1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ϕ</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.72777em;vertical-align:-0.08333em;\"></span><span class=\"mord\">−</span><span class=\"mord\">1</span></span></span></span>。</p>\n</li>\n<li>\n<p><strong>例 4</strong> 设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>=</mo><mi>D</mi><mo>=</mo><msub><mi mathvariant=\"double-struck\">Z</mi><mo>+</mo></msub></mrow><annotation encoding=\"application/x-tex\">A_1 = D = \\mathbb{Z}_+</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.897221em;vertical-align:-0.208331em;\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathbb\">Z</span></span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.25833100000000003em;\"><span style=\"top:-2.5500000000000003em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.208331em;\"><span></span></span></span></span></span></span></span></span></span>，则</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>ϕ</mi><mo stretchy=\"false\">(</mo><mi>a</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>a</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">\\phi(a) = a - 1\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ϕ</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">a</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span></span></p>\n<p>不是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub></mrow><annotation encoding=\"application/x-tex\">A_1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的映射。因为当 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>a</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">a = 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span> 时，对应的像为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">0</span></span></span></span>，但这个像 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">0</span></span></span></span> 不在 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi mathvariant=\"double-struck\">Z</mi><mo>+</mo></msub></mrow><annotation encoding=\"application/x-tex\">\\mathbb{Z}_+</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.897221em;vertical-align:-0.208331em;\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathbb\">Z</span></span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.25833100000000003em;\"><span style=\"top:-2.5500000000000003em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mbin mtight\">+</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.208331em;\"><span></span></span></span></span></span></span></span></span></span> 中。</p>\n</li>\n</ul>\n<h2 id=\"定义-3-映射相等\"><a class=\"anchor\" href=\"#定义-3-映射相等\">#</a> 定义 3 - 映射相等</h2>\n<p>设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>ϕ</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>ϕ</mi><mn>2</mn></msub></mrow><annotation encoding=\"application/x-tex\">\\phi_1, \\phi_2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 都是从笛卡尔积 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub><mo>×</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>×</mo><msub><mi>A</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2 \\times ... \\times A_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 到集合 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 的映射，如果对于 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo>×</mo><msub><mi>A</mi><mn>2</mn></msub><mo>×</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo>×</mo><msub><mi>A</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">A_1 \\times A_2 \\times ... \\times A_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.83333em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">A</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 中的每个元素 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">(a_1, a_2, ..., a_n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span>，都有</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><msub><mi>ϕ</mi><mn>1</mn></msub><mo stretchy=\"false\">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy=\"false\">)</mo><mo>=</mo><msub><mi>ϕ</mi><mn>2</mn></msub><mo stretchy=\"false\">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\\phi_1(a_1, a_2, ..., a_n) = \\phi_2(a_1, a_2, ..., a_n)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p>则称这两个映射 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>ϕ</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><msub><mi>ϕ</mi><mn>2</mn></msub></mrow><annotation encoding=\"application/x-tex\">\\phi_1, \\phi_2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> <strong>相等</strong>。</p>\n<p>注：两个映射相等的要求：</p>\n<ol>\n<li>定义域相等；</li>\n<li>作用效果相同。</li>\n</ol>\n<h3 id=\"例子-2\"><a class=\"anchor\" href=\"#例子-2\">#</a> 例子</h3>\n<ul>\n<li><strong>例 5</strong> 设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>=</mo><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">A = D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 都表示正整数的集合，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>ϕ</mi><mn>1</mn></msub><mo>:</mo><mi>A</mi><mo>→</mo><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">\\phi_1: A \\rightarrow D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">:</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 定义为：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>ϕ</mi><mn>1</mn></msub><mo stretchy=\"false\">(</mo><mi>a</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mn>1</mn><mo separator=\"true\">,</mo><msub><mi>ϕ</mi><mn>2</mn></msub><mo>:</mo><mi>A</mi><mo>→</mo><mi>D</mi></mrow><annotation encoding=\"application/x-tex\">\\phi_1(a) = 1, \\phi_2: A \\rightarrow D</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">a</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">:</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">D</span></span></span></span> 定义为：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>ϕ</mi><mn>2</mn></msub><mo stretchy=\"false\">(</mo><mi>a</mi><mo stretchy=\"false\">)</mo><mo>=</mo><msup><mi>a</mi><mn>0</mn></msup></mrow><annotation encoding=\"application/x-tex\">\\phi_2(a) = a^0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">a</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8141079999999999em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">a</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">0</span></span></span></span></span></span></span></span></span></span></span>，则 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>ϕ</mi><mn>1</mn></msub><mo>=</mo><msub><mi>ϕ</mi><mn>2</mn></msub></mrow><annotation encoding=\"application/x-tex\">\\phi_1 = \\phi_2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">ϕ</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>.</li>\n</ul>\n<h2 id=\"习题-2\"><a class=\"anchor\" href=\"#习题-2\">#</a> 习题</h2>\n<ul>\n<li><strong>例 6</strong> 设 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>=</mo><mo stretchy=\"false\">{</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>2</mn><mo separator=\"true\">,</mo><mn>3</mn><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><mn>100</mn><mo stretchy=\"false\">}</mo></mrow><annotation encoding=\"application/x-tex\">A = \\{ 1, 2, 3, ..., 100 \\}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">{</span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">2</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">3</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">1</span><span class=\"mord\">0</span><span class=\"mord\">0</span><span class=\"mclose\">}</span></span></span></span>，找一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>A</mi><mo>×</mo><mi>A</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding=\"application/x-tex\">A \\times A \\rightarrow A</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.76666em;vertical-align:-0.08333em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">A</span></span></span></span> 的映射。</li>\n</ul>\n<h1 id=\"代数运算\"><a class=\"anchor\" href=\"#代数运算\">#</a> 代数运算</h1>\n<h1 id=\"结合律-交换律\"><a class=\"anchor\" href=\"#结合律-交换律\">#</a> 结合律、交换律</h1>\n<h1 id=\"消去律\"><a class=\"anchor\" href=\"#消去律\">#</a> 消去律</h1>\n<h1 id=\"分配律\"><a class=\"anchor\" href=\"#分配律\">#</a> 分配律</h1>\n<h1 id=\"映射与变换\"><a class=\"anchor\" href=\"#映射与变换\">#</a> 映射与变换</h1>\n<h1 id=\"同态\"><a class=\"anchor\" href=\"#同态\">#</a> 同态</h1>\n<h1 id=\"同构与自同构\"><a class=\"anchor\" href=\"#同构与自同构\">#</a> 同构与自同构</h1>\n<h1 id=\"等价关系与集合的分类\"><a class=\"anchor\" href=\"#等价关系与集合的分类\">#</a> 等价关系与集合的分类</h1>\n",
            "tags": [
                "math",
                "algebra",
                "math",
                "algebra",
                "concept"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/11/09/java/source/%E9%98%9F%E5%88%97%E8%AF%A6%E8%A7%A3%E5%92%8C%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/",
            "url": "https://blog.ceciljxsu.icu/2023/11/09/java/source/%E9%98%9F%E5%88%97%E8%AF%A6%E8%A7%A3%E5%92%8C%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/",
            "title": "队列详解和源码分析",
            "date_published": "2023-11-09T06:43:00.000Z",
            "content_html": "<h1 id=\"队列分类\"><a class=\"anchor\" href=\"#队列分类\">#</a> 队列分类</h1>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">package</span> <span class=\"token namespace\">java<span class=\"token punctuation\">.</span>util</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">interface</span> <span class=\"token class-name\">Queue</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">E</span><span class=\"token punctuation\">></span></span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Collection</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">E</span><span class=\"token punctuation\">></span></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">//true - 入队成功；异常 IllegalStateException - 容量不足</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// ClassCastException、NullPointerException、IllegalArgumentException</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">boolean</span> <span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">E</span> e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token comment\">//true - 入队成功；false - 容量不足</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// ClassCastException、NullPointerException、IllegalArgumentException</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">boolean</span> <span class=\"token function\">offer</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">E</span> e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token comment\">// E - 队头元素出队；异常 NoSuchElementException - 队列为空</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token class-name\">E</span> <span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token comment\">// E - 队头元素出队；null - 队列为空</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token class-name\">E</span> <span class=\"token function\">poll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token comment\">// E - 查看队头元素；异常 NoSuchElementException - 队列为空</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token class-name\">E</span> <span class=\"token function\">element</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token comment\">// E - 查看队头元素；null - 队列为空</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token class-name\">E</span> <span class=\"token function\">peek</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">package</span> <span class=\"token namespace\">java<span class=\"token punctuation\">.</span>util</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// Xxx => First 或 Last</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">interface</span> <span class=\"token class-name\">Deque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">E</span><span class=\"token punctuation\">></span></span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Queue</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">E</span><span class=\"token punctuation\">></span></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">boolean</span> <span class=\"token function\">addXxx</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">E</span> e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">boolean</span> <span class=\"token function\">offerXxx</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">E</span> e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token class-name\">E</span> <span class=\"token function\">removeXxx</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token class-name\">E</span> <span class=\"token function\">pollXxx</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token comment\">//get 对应 Queue 的 element</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token class-name\">E</span> <span class=\"token function\">getXxx</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token class-name\">E</span> <span class=\"token function\">peekXxx</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token comment\">//------- 新增 -------</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token comment\">// 在 Queue 基础上新增的</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token comment\">// 移除 [第一次 / 最后] 出现 的元素。</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token comment\">// ClassCastException、NullPointerException</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token comment\">//false - 元素不存在；true - 移除成功</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token keyword\">boolean</span> <span class=\"token function\">removeXxxOccurrence</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Object</span> o<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><pre><code class=\"language-java\"></code></pre>\n",
            "tags": [
                "java",
                "source",
                "java",
                "source",
                "queue"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/06/11/java/jvm/%E7%B1%BB%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84/",
            "url": "https://blog.ceciljxsu.icu/2023/06/11/java/jvm/%E7%B1%BB%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84/",
            "title": "类文件结构",
            "date_published": "2023-06-11T10:03:20.000Z",
            "content_html": "<h1 id=\"参考资料\"><a class=\"anchor\" href=\"#参考资料\">#</a> 参考资料</h1>\n<ol>\n<li><span class=\"exturl\" data-url=\"aHR0cHM6Ly9kb2NzLm9yYWNsZS5jb20vamF2YXNlL3NwZWNzL2p2bXMvc2U3L2h0bWwvanZtcy00Lmh0bWw=\">Chapter 4. The class File Format, oracle 官方技术规范</span></li>\n<li><span class=\"exturl\" data-url=\"aHR0cHM6Ly9kb2NzLm9yYWNsZS5jb20vamF2YXNlL3NwZWNzL2p2bXMvc2U3L2h0bWwvanZtcy02Lmh0bWwjanZtcy02LjU=\">Chapter 6. The Java Virtual Machine Instruction Set</span></li>\n<li><span class=\"exturl\" data-url=\"aHR0cHM6Ly9kb2NzLm9yYWNsZS5jb20vamF2YXNlL3NwZWNzL2p2bXMvc2U3L2h0bWwvanZtcy03Lmh0bWw=\">Chapter 7. Opcode Mnemonics by Opcode</span></li>\n</ol>\n<h1 id=\"无关性的基石\"><a class=\"anchor\" href=\"#无关性的基石\">#</a> 无关性的基石</h1>\n<p>字节码（ByteCode）</p>\n<p><img data-src=\"jvm_language_independence.jpg\" alt=\"jvm_language_independence\" title=\"语言无关性\" width=\"80%\" /></p>\n<h1 id=\"class类文件的结构\"><a class=\"anchor\" href=\"#class类文件的结构\">#</a> Class 类文件的结构</h1>\n<p><strong>查看类文件结构的命令</strong></p>\n<blockquote>\n<p>javap -verbose &lt;类文件&gt;</p>\n</blockquote>\n<table>\n<thead>\n<tr>\n<th>类型</th>\n<th>名称</th>\n<th>数量</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>u4</td>\n<td>magic</td>\n<td>1</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>minor_version</td>\n<td>1</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>major_version</td>\n<td>1</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>constant_pool_count</td>\n<td>1</td>\n</tr>\n<tr>\n<td>cp_info</td>\n<td>constant_pool</td>\n<td>constant_pool_count - 1</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>access_flags</td>\n<td>1</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>this_class</td>\n<td>1</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>super_class</td>\n<td>1</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>interfaces_count</td>\n<td>1</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>interfaces</td>\n<td>interfaces_count</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>fields_count</td>\n<td>1</td>\n</tr>\n<tr>\n<td>field_info</td>\n<td>fields</td>\n<td>fields_count</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>methods_count</td>\n<td>1</td>\n</tr>\n<tr>\n<td>method_info</td>\n<td>methods</td>\n<td>methods_count</td>\n</tr>\n<tr>\n<td>u2</td>\n<td>attributes_count</td>\n<td>1</td>\n</tr>\n<tr>\n<td>attribute_info</td>\n<td>attributes</td>\n<td>attributes_count</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"魔数与版本号\"><a class=\"anchor\" href=\"#魔数与版本号\">#</a> 魔数与版本号</h2>\n<p>魔数：固定 <code>0xCAFEBABE</code> （咖啡宝贝）</p>\n<p>Class 文件的主版本号：</p>\n<ul>\n<li>Java SE 9 = 53 [hex: 35]</li>\n<li>Java SE 8 = 52 [hex: 34]</li>\n<li>Java SE 7 = 51 [hex: 33]</li>\n<li>Java SE 6.0 = 50 [hex: 32]</li>\n<li>Java SE 5.0 = 49 [hex: 31]</li>\n<li>JDK 1.4 = 48</li>\n<li>JDK 1.3 = 47</li>\n<li>JDK 1.2 = 46</li>\n<li>JDK 1.1 = 45</li>\n</ul>\n<h2 id=\"常量池\"><a class=\"anchor\" href=\"#常量池\">#</a> 常量池</h2>\n<p>常量池从 #1 开始表示，常量池数量会比实际数量多 1，实际数量是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mi>o</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>a</mi><mi>n</mi><mi>t</mi><mi mathvariant=\"normal\">_</mi><mi>p</mi><mi>o</mi><mi>o</mi><mi>l</mi><mi mathvariant=\"normal\">_</mi><mi>c</mi><mi>o</mi><mi>u</mi><mi>n</mi><mi>t</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">constant\\_pool\\_count - 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.00444em;vertical-align:-0.31em;\"></span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mord\" style=\"margin-right:0.02778em;\">_</span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord\" style=\"margin-right:0.02778em;\">_</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span></p>\n<h3 id=\"存储内容\"><a class=\"anchor\" href=\"#存储内容\">#</a> 存储内容</h3>\n<p><strong>字面量：</strong></p>\n<ul>\n<li>文本字符串</li>\n<li>声明为 final 的常量值等</li>\n</ul>\n<p><strong>符号引用（Symbolic References）：</strong></p>\n<ul>\n<li>类和接口的全限定名（Fully Qualified Name）</li>\n<li>字段的名称和描述符（Descriptor）</li>\n<li>方法的名称和描述符</li>\n</ul>\n<h3 id=\"常量池格式\"><a class=\"anchor\" href=\"#常量池格式\">#</a> 常量池格式</h3>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>cp_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u1 info[];</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>&#125;</pre></td></tr></table></figure><h3 id=\"tag-标记\"><a class=\"anchor\" href=\"#tag-标记\">#</a> tag 标记</h3>\n<table style=\"margin-bottom: 1.5em\">\n<thead>\n<tr>\n<th>类型</th>\n<th>标志</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>CONSTANT_Utf8</td>\n<td>1</td>\n<td>UTF8 字符串</td>\n</tr>\n<tr>\n<td>CONSTANT_Integer</td>\n<td>3</td>\n<td>整型</td>\n</tr>\n<tr>\n<td>CONSTANT_Float</td>\n<td>4</td>\n<td>单精度浮点型</td>\n</tr>\n<tr>\n<td>CONSTANT_Long</td>\n<td>5</td>\n<td>长整型</td>\n</tr>\n<tr>\n<td>CONSTANT_Double</td>\n<td>6</td>\n<td>双精度浮点型</td>\n</tr>\n<tr>\n<td>CONSTANT_Class</td>\n<td>7</td>\n<td>类或接口</td>\n</tr>\n<tr>\n<td>CONSTANT_String</td>\n<td>8</td>\n<td>字符串</td>\n</tr>\n<tr>\n<td>CONSTANT_Fieldref</td>\n<td>9</td>\n<td>类的字段</td>\n</tr>\n<tr>\n<td>CONSTANT_Methodref</td>\n<td>10</td>\n<td>类的方法</td>\n</tr>\n<tr>\n<td>CONSTANT_InterfaceMethodref</td>\n<td>11</td>\n<td>类的接口方法</td>\n</tr>\n<tr>\n<td>CONSTANT_NameAndType</td>\n<td>12</td>\n<td>字段或方法</td>\n</tr>\n<tr>\n<td>CONSTANT_MethodHandle</td>\n<td>15</td>\n<td>方法句柄</td>\n</tr>\n<tr>\n<td>CONSTANT_MethodType</td>\n<td>16</td>\n<td>方法类型</td>\n</tr>\n<tr>\n<td>CONSTANT_InvokeDynamic</td>\n<td>18</td>\n<td>动态方法调用点</td>\n</tr>\n</tbody>\n</table>\n<p>CONSTANT_MethodHandle、CONSTANT_MethodType、CONSTANT_InvokeDynamic 动态调用</p>\n<h3 id=\"info-信息\"><a class=\"anchor\" href=\"#info-信息\">#</a> info 信息</h3>\n<h4 id=\"utf8\"><a class=\"anchor\" href=\"#utf8\">#</a> Utf8</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_Utf8_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2 length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u1 bytes[length];</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>length: bytes 的个数。</li>\n<li>bytes: 不是 null-terminated，即不是以 '\\0' 结尾的字符串，没有结尾符。</li>\n</ul>\n<h4 id=\"intefer-float\"><a class=\"anchor\" href=\"#intefer-float\">#</a> Intefer, Float</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_Integer_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 bytes;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>CONSTANT_Float_info &#123;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u4 bytes;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>bytes: 两者都是 big-endian 存储方式；Float 的按 IEEE 754 floating-point single format 存储。</li>\n</ul>\n<h4 id=\"long-double\"><a class=\"anchor\" href=\"#long-double\">#</a> Long, Double</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_Long_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 high_bytes;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u4 low_bytes;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>CONSTANT_Double_info &#123;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    u4 high_bytes;</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    u4 low_bytes;</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>high_bytes, low_bytes: 两者都是 big-endian 存储方式；Double 的按 IEEE 754 floating-point double format 存储</li>\n</ul>\n<h4 id=\"class\"><a class=\"anchor\" href=\"#class\">#</a> Class</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_Class_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2 name_index;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>name_index: 指向的常量池下标对应的内容是 CONSTANT_Utf8 类型的，类名称的字符串。</li>\n</ul>\n<h4 id=\"string\"><a class=\"anchor\" href=\"#string\">#</a> String</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_String_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2 string_index;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>string_index: 指向的常量池下标对应的内容是 CONSTANT_Utf8 类型的，字符串。</li>\n</ul>\n<h4 id=\"fieldref-methodref-interfacemethodref\"><a class=\"anchor\" href=\"#fieldref-methodref-interfacemethodref\">#</a> Fieldref, Methodref, InterfaceMethodref</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_Fieldref_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2 class_index;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 name_and_type_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>CONSTANT_Methodref_info &#123;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    u2 class_index;</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    u2 name_and_type_index;</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>CONSTANT_InterfaceMethodref_info &#123;</pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    u2 class_index;</pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    u2 name_and_type_index;</pre></td></tr><tr><td data-num=\"17\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>class_index: 指向的常量池下标对应的内容是 CONSTANT_Class 类型的，所属的类。</li>\n<li>name_and_type_index: 指向的常量池下标对应的内容是 CONSTANT_NameAndType 类型的</li>\n</ul>\n<h4 id=\"nameandtype\"><a class=\"anchor\" href=\"#nameandtype\">#</a> NameAndType</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_NameAndType_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2 name_index;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 descriptor_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>name_index: 指向的常量池下标对应的内容是 CONSTANT_Utf8 类型的，字段或方法的名称。</li>\n<li>descriptor_index: 指向的常量池下标对应的内容是 CONSTANT_Utf8 类型的，字段或方法描述符。</li>\n</ul>\n<h4 id=\"methodhandle\"><a class=\"anchor\" href=\"#methodhandle\">#</a> MethodHandle</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_MethodHandle_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u1 reference_kind;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 reference_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>\n<p>reference_kind: 值必须在 1～9 范围，方法句柄的类型，类型表示方法句柄的字节码行为，参考（<span class=\"exturl\" data-url=\"aHR0cHM6Ly9kb2NzLm9yYWNsZS5jb20vamF2YXNlL3NwZWNzL2p2bXMvc2U3L2h0bWwvanZtcy01Lmh0bWwjanZtcy01LjQuMy41\">§5.4.3.5</span>）。</p>\n</li>\n<li>\n<p>reference_index: 常量池的引用下标：</p>\n<ul>\n<li>如果 reference_kind 的值是 1～4，则引用的常量池下标对应的内容是 CONSTANT_Fieldref 类型</li>\n<li>如果 reference_kind 的值是 5～8，则引用的常量池下标对应的内容是 CONSTANT_Methodref 类型</li>\n<li>如果 reference_kind 的值是 9，则引用的常量池下标对应的内容是 CONSTANT_InterfaceMethodref 类型</li>\n<li>如果 reference_kind 的值是 5，6，7 或 9，则方法或接口的名称一定不是 <code>&lt;init&gt;</code>  或  <code>&lt;clinit&gt;</code></li>\n<li>如果 reference_kind 的值是 8，则方法的名称一定是 <code>&lt;init&gt;</code></li>\n</ul>\n</li>\n</ul>\n<h4 id=\"methodtype\"><a class=\"anchor\" href=\"#methodtype\">#</a> MethodType</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_MethodType_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2 descriptor_index;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>descriptor_index: 引用的常量池下标对应的内容是 CONSTANT_Utf8 类型的，方法的描述符。</li>\n</ul>\n<h4 id=\"invokedynamic\"><a class=\"anchor\" href=\"#invokedynamic\">#</a> InvokeDynamic</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CONSTANT_InvokeDynamic_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2 bootstrap_method_attr_index;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 name_and_type_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>bootstrap_method_attr_index: 当前类文件中引导方法表的 bootstrap_methods [] 数组的有效索引。</li>\n<li>name_and_type_index: 引用的常量池下标的内容是 CONSTANT_NameAndType 类型的，字段或方法的描述符。</li>\n</ul>\n<h2 id=\"访问标志\"><a class=\"anchor\" href=\"#访问标志\">#</a> 访问标志</h2>\n<table style=\"margin-bottom: 1.5em\">\n<thead>\n<tr>\n<th>标志名称</th>\n<th>标志值</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ACC_PUBLIC</td>\n<td>0x0001</td>\n<td>public 类型</td>\n</tr>\n<tr>\n<td>ACC_FINAL</td>\n<td>0x0010</td>\n<td>final 类型</td>\n</tr>\n<tr>\n<td>ACC_SUPER</td>\n<td>0x0020</td>\n<td>使用 invokespecial 新指令语义</td>\n</tr>\n<tr>\n<td>ACC_INTERFACE</td>\n<td>0x0200</td>\n<td>接口</td>\n</tr>\n<tr>\n<td>ACC_ABSTRACT</td>\n<td>0x0400</td>\n<td>抽象类</td>\n</tr>\n<tr>\n<td>ACC_SYNTHETIC</td>\n<td>0x1000</td>\n<td>表明由编译器产生</td>\n</tr>\n<tr>\n<td>ACC_ANNOTATION</td>\n<td>0x2000</td>\n<td>注解</td>\n</tr>\n<tr>\n<td>ACC_ENUM</td>\n<td>0x4000</td>\n<td>枚举</td>\n</tr>\n</tbody>\n</table>\n<p>invokespecial 语义在 JDK 1.0.2 发生改变，因此 JDK 1.0.2 之后编译出的类，ACC_SUPER 一定设置。</p>\n<h2 id=\"类父类索引接口索引集合\"><a class=\"anchor\" href=\"#类父类索引接口索引集合\">#</a> 类 / 父类索引，接口索引集合</h2>\n<h3 id=\"类索引和父类索引\"><a class=\"anchor\" href=\"#类索引和父类索引\">#</a> 类索引和父类索引</h3>\n<p>引用常量池下标，对应的内容是 CONSTANT_Class 类型的结构，该结构中的 name_index 指向 CONSTANT_Utf8 类型的结构，从中可以获取类的全限定名字符串。</p>\n<h3 id=\"接口索引集合\"><a class=\"anchor\" href=\"#接口索引集合\">#</a> 接口索引集合</h3>\n<p><strong>interfaces_count</strong><br />\n 接口计数器，表示索引表的容量，如果没实现任何接口，则该项为 0，以及接下来的接口集合也为空，不再占字节。</p>\n<p>接口也是引用常量池下标，对应的内容也是是 CONSTANT_Class 的结构。</p>\n<h2 id=\"字段表集合\"><a class=\"anchor\" href=\"#字段表集合\">#</a> 字段表集合</h2>\n<h3 id=\"fields_count\"><a class=\"anchor\" href=\"#fields_count\">#</a> fields_count</h3>\n<p>字段计数器，表明字段表集合包含字段信息的数量。</p>\n<h3 id=\"字段表结构\"><a class=\"anchor\" href=\"#字段表结构\">#</a> 字段表结构</h3>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>field_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2             access_flags;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2             name_index;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2             descriptor_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    u2             attributes_count;</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    attribute_info attributes[attributes_count];</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"access_flags\"><a class=\"anchor\" href=\"#access_flags\">#</a> access_flags</h4>\n<table>\n<thead>\n<tr>\n<th>标志名称</th>\n<th>标志值</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ACC_PUBLIC</td>\n<td>0x0001</td>\n<td>public 修饰符</td>\n</tr>\n<tr>\n<td>ACC_PRIVATE</td>\n<td>0x0002</td>\n<td>private 修饰符</td>\n</tr>\n<tr>\n<td>ACC_PROTECTED</td>\n<td>0x0004</td>\n<td>protected 修饰符</td>\n</tr>\n<tr>\n<td>ACC_STATIC</td>\n<td>0x0008</td>\n<td>static 修饰符</td>\n</tr>\n<tr>\n<td>ACC_FINAL</td>\n<td>0x0010</td>\n<td>final 修饰符</td>\n</tr>\n<tr>\n<td>ACC_VOLATILE</td>\n<td>0x0040</td>\n<td>volatile 修饰符</td>\n</tr>\n<tr>\n<td>ACC_TRANSIENT</td>\n<td>0x0080</td>\n<td>transient 修饰符</td>\n</tr>\n<tr>\n<td>ACC_SYNTHETIC</td>\n<td>0x1000</td>\n<td>表明是由编译器生成</td>\n</tr>\n<tr>\n<td>ACC_ENUM</td>\n<td>0x4000</td>\n<td>enum 类型</td>\n</tr>\n</tbody>\n</table>\n<h4 id=\"name_index\"><a class=\"anchor\" href=\"#name_index\">#</a> name_index</h4>\n<p>字段的名称引用，CONSTANT_Utf8 类型。</p>\n<h4 id=\"descriptor_index\"><a class=\"anchor\" href=\"#descriptor_index\">#</a> descriptor_index</h4>\n<p>字段的全限定描述符引用，CONSTANT_Utf8 类型。</p>\n<h4 id=\"attributes_count\"><a class=\"anchor\" href=\"#attributes_count\">#</a> attributes_count</h4>\n<p>属性表计数。</p>\n<h4 id=\"attributes\"><a class=\"anchor\" href=\"#attributes\">#</a> attributes</h4>\n<p><a href=\"#%E5%B1%9E%E6%80%A7%E8%A1%A8%E9%9B%86%E5%90%88\">属性表集合</a>。</p>\n<h2 id=\"方法表集合\"><a class=\"anchor\" href=\"#方法表集合\">#</a> 方法表集合</h2>\n<h3 id=\"methods_count\"><a class=\"anchor\" href=\"#methods_count\">#</a> methods_count</h3>\n<p>方法表集合的计数，表明方法表集合包含方法信息的数量。</p>\n<h3 id=\"方法表结构\"><a class=\"anchor\" href=\"#方法表结构\">#</a> 方法表结构</h3>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>method_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2             access_flags;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u2             name_index;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2             descriptor_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    u2             attributes_count;</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    attribute_info attributes[attributes_count];</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"access_flags-2\"><a class=\"anchor\" href=\"#access_flags-2\">#</a> access_flags</h4>\n<table>\n<thead>\n<tr>\n<th>标志名称</th>\n<th>标志值</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ACC_PUBLIC</td>\n<td>0x0001</td>\n<td>public 修饰符</td>\n</tr>\n<tr>\n<td>ACC_PRIVATE</td>\n<td>0x0002</td>\n<td>private 修饰符</td>\n</tr>\n<tr>\n<td>ACC_PROTECTED</td>\n<td>0x0004</td>\n<td>protected 修饰符</td>\n</tr>\n<tr>\n<td>ACC_STATIC</td>\n<td>0x0008</td>\n<td>static 修饰符</td>\n</tr>\n<tr>\n<td>ACC_FINAL</td>\n<td>0x0010</td>\n<td>final 修饰符</td>\n</tr>\n<tr>\n<td>ACC_SYNCHRONIZED</td>\n<td>0x0020</td>\n<td>synchronized 修饰符</td>\n</tr>\n<tr>\n<td>ACC_BRIDGE</td>\n<td>0x0040</td>\n<td>表明由编译器产生的桥接方法</td>\n</tr>\n<tr>\n<td>ACC_VARARGS</td>\n<td>0x0080</td>\n<td>表明方法接收不定参数</td>\n</tr>\n<tr>\n<td>ACC_NATIVE</td>\n<td>0x0100</td>\n<td>native 修饰符</td>\n</tr>\n<tr>\n<td>ACC_ABSTRACT</td>\n<td>0x0400</td>\n<td>abstract 修饰符</td>\n</tr>\n<tr>\n<td>ACC_STRICT</td>\n<td>0x0800</td>\n<td>strictfp 修饰符</td>\n</tr>\n<tr>\n<td>ACC_SYNTHETIC</td>\n<td>0x1000</td>\n<td>表明由编译器生成</td>\n</tr>\n</tbody>\n</table>\n<p>strictfp 修饰符，floating-point mode is FP-strict，浮点数使用精确模式</p>\n<h4 id=\"name_index-2\"><a class=\"anchor\" href=\"#name_index-2\">#</a> name_index</h4>\n<p>方法名，CONSTANT_Utf8 类型。</p>\n<h4 id=\"descriptor_index-2\"><a class=\"anchor\" href=\"#descriptor_index-2\">#</a> descriptor_index</h4>\n<p>方法全限定名描述符，CONSTANT_Utf8 类型。</p>\n<h4 id=\"attributes_count-2\"><a class=\"anchor\" href=\"#attributes_count-2\">#</a> attributes_count</h4>\n<p>属性表集合计数</p>\n<h4 id=\"attributes-2\"><a class=\"anchor\" href=\"#attributes-2\">#</a> attributes</h4>\n<p><a href=\"#%E5%B1%9E%E6%80%A7%E8%A1%A8%E9%9B%86%E5%90%88\">属性表集合</a></p>\n<h2 id=\"属性表集合\"><a class=\"anchor\" href=\"#属性表集合\">#</a> 属性表集合</h2>\n<p>属性表集合会在 ClassFile, field_info, method_info, 和 Code_attribute 结构中使用。</p>\n<h3 id=\"attributes_count-3\"><a class=\"anchor\" href=\"#attributes_count-3\">#</a> attributes_count</h3>\n<p>属性表集合计数</p>\n<h3 id=\"属性表结构\"><a class=\"anchor\" href=\"#属性表结构\">#</a> 属性表结构</h3>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>attribute_info &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u1 info[attribute_length];</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"attribute_name_index\"><a class=\"anchor\" href=\"#attribute_name_index\">#</a> attribute_name_index</h4>\n<p>属性名，引用常量池的下标，对应的内容是 CONSTANT_Utf8 类型的，固定值如<a href=\"#%E9%A2%84%E5%AE%9A%E4%B9%89%E7%9A%84%E7%B1%BB%E6%96%87%E4%BB%B6%E5%B1%9E%E6%80%A7%E9%9B%86%E5%90%88\">下表</a>。</p>\n<h4 id=\"attribute_length\"><a class=\"anchor\" href=\"#attribute_length\">#</a> attribute_length</h4>\n<p>表明 info 字节的数量</p>\n<h3 id=\"预定义的类文件属性集合\"><a class=\"anchor\" href=\"#预定义的类文件属性集合\">#</a> 预定义的类文件属性集合</h3>\n<table>\n<thead>\n<tr>\n<th>属性</th>\n<th>since</th>\n<th>class file</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ConstantValue</td>\n<td>1.0.2</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>Code</td>\n<td>1.0.2</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>StackMapTable</td>\n<td>6</td>\n<td>50.0</td>\n</tr>\n<tr>\n<td>Exceptions</td>\n<td>1.0.2</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>InnerClasses</td>\n<td>1.1</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>EnclosingMethod</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>Synthetic</td>\n<td>1.1</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>Signature</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>SourceFile</td>\n<td>1.0.2</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>SourceDebugExtension</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>LineNumberTable</td>\n<td>1.0.2</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>LocalVariableTable</td>\n<td>1.0.2</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>LocalVariableTypeTable</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>Deprecated</td>\n<td>1.1</td>\n<td>45.3</td>\n</tr>\n<tr>\n<td>RuntimeVisibleAnnotations</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>RuntimeInvisibleAnnotations</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>RuntimeVisibleParameterAnnotations</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>RuntimeInvisibleParameterAnnotations</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>AnnotationDefault</td>\n<td>5.0</td>\n<td>49.0</td>\n</tr>\n<tr>\n<td>BootstrapMethods</td>\n<td>7</td>\n<td>51.0</td>\n</tr>\n</tbody>\n</table>\n<h4 id=\"constantvalue\"><a class=\"anchor\" href=\"#constantvalue\">#</a> ConstantValue</h4>\n<p>位置：field_info</p>\n<p>field_info 结构中的 access_flags 是 ACC_STATIC 才有该属性；</p>\n<p>Sun javac 的实现是字段被 static 和 final 修饰才有该属性，其它的初始化是在 <code>&lt;cinit&gt;</code>  中赋值。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>ConstantValue_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 constantvalue_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>constantvalue_index</strong><br />\n 引用常量池的下标，对应的内容的类型根据字段类型不同而不同，类型对应下面的表格。</p>\n<table>\n<thead>\n<tr>\n<th>字段类型</th>\n<th>常量类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>long</td>\n<td>CONSTANT_Long</td>\n</tr>\n<tr>\n<td>float</td>\n<td>CONSTANT_Float</td>\n</tr>\n<tr>\n<td>double</td>\n<td>CONSTANT_Double</td>\n</tr>\n<tr>\n<td>int, short, char, byte, boolean</td>\n<td>CONSTANT_Integer</td>\n</tr>\n<tr>\n<td>String</td>\n<td>CONSTANT_String</td>\n</tr>\n</tbody>\n</table>\n<h4 id=\"code\"><a class=\"anchor\" href=\"#code\">#</a> Code</h4>\n<p>位置：method_info</p>\n<p>如果方法是 native 或 abstract，则 method_info 中不会有 Code 属性；否则至少存在一个。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Code_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 max_stack;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    u2 max_locals;</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    u4 code_length;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    u1 code[code_length];</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u2 exception_table_length;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    Exception_info exception_table[exception_table_length];</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    u2 attributes_count;</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    attribute_info attributes[attributes_count];</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>Exception_info &#123;</pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    u2 start_pc;</pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    u2 end_pc;</pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    u2 handler_pc;</pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    u2 catch_type;</pre></td></tr><tr><td data-num=\"19\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>max_stack</strong><br />\n 方法执行时的最大操作数堆栈 (Operand Stacks) 深度，虚拟机根据这个值来分配栈帧的操作数深度。</p>\n<p><strong>max_locals</strong><br />\n 局部变量表所需的存储空间，单位是 Slot；boolean, byte, char, short, int, float, reference 和 returnAddress 占 1 个 Slot，long 和 double 占 2 个 Slot。</p>\n<p><strong>code_length</strong><br />\n 字节码（code）长度。</p>\n<p><strong>code</strong><br />\n 字节码</p>\n<p><strong>exception_table_length</strong><br />\nexception_table 的数量。</p>\n<p><strong>exception_table</strong><br />\n 异常处理使用异常表实现，而不是简单的跳转。</p>\n<ul>\n<li>[start_pc, end_pc): 记录的是 try-catch 之间的代码行范围，在 code 数组中的下标，异常处理器（exception handler）在该范围的代码行中激活，如果该范围的代码出现了 catch_type 类型的异常，则会跳到 handler_pc 处理异常。</li>\n<li>handler_pc: 记录的是开始处理异常的代码行，在 code 数组中的下标。</li>\n<li>catch_type: 捕获的异常，指向常量池的下标，对应的内容类型是 CONSTANT_Class；可以指定 0，则必定跳到 handler_pc 中处理，因此，可以作为 finally 的实现。</li>\n</ul>\n<p><strong>attributes_count</strong><br />\nattributes 中的数量。</p>\n<p><strong>attributes</strong><br />\n 该节是讨论属性集合的，参考</p>\n<ul>\n<li><a href=\"#LineNumberTable\">LineNumberTable</a></li>\n<li><a href=\"#LocalVariableTable\">LocalVariableTable</a></li>\n<li><a href=\"#LocalVariableTypeTable\">LocalVariableTypeTable</a></li>\n<li><a href=\"#StackMapTable\">StackMapTable</a></li>\n</ul>\n<h4 id=\"stackmaptable\"><a class=\"anchor\" href=\"#stackmaptable\">#</a> StackMapTable</h4>\n<p>位置：Code 属性</p>\n<p><span class=\"exturl\" data-url=\"aHR0cHM6Ly9kb2NzLm9yYWNsZS5jb20vamF2YXNlL3NwZWNzL2p2bXMvc2U3L2h0bWwvanZtcy00Lmh0bWwjanZtcy00LjcuNA==\">参考</span></p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>StackMapTable_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2              attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4              attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2              number_of_entries;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    stack_map_frame entries[number_of_entries];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>number_of_entries</strong><br />\nentries 的数量。</p>\n<p><strong>entries</strong></p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>union stack_map_frame &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    same_frame;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    same_locals_1_stack_item_frame;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    same_locals_1_stack_item_frame_extended;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    chop_frame;</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    same_frame_extended;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    append_frame;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    full_frame;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"exceptions\"><a class=\"anchor\" href=\"#exceptions\">#</a> Exceptions</h4>\n<p>位置：method_info</p>\n<p>表明该方法可能抛出哪些异常；在 Java 中，throws 关键字的实现。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Exceptions_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 number_of_exceptions;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    u2 exception_index_table[number_of_exceptions];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>number_of_exceptions</strong><br />\nexception_index_table 的数量。</p>\n<p><strong>exception_index_table</strong><br />\n 抛出的异常，引用常量池的下标，对应的内容类型是 CONSTANT_Class。</p>\n<h4 id=\"innerclasses\"><a class=\"anchor\" href=\"#innerclasses\">#</a> InnerClasses</h4>\n<p>位置：ClassFile</p>\n<p>内部类。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>InnerClasses_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 number_of_classes;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    Class_info classes[number_of_classes];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>Class_info &#123;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    u2 inner_class_info_index;</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    u2 outer_class_info_index;</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    u2 inner_name_index;</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    u2 inner_class_access_flags;</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>number_of_classes</strong><br />\nclasses 的数量。</p>\n<p><strong>classes</strong></p>\n<ul>\n<li>inner_class_info_index: 内部类；引用常量池的下标，对应的内容类型是 CONSTANT_Class。</li>\n<li>outer_class_info_index: 宿主类，也是引用 CONSTANT_Class 类型的常量池下标，如果该类是顶级（top-level）的类或接口，以及或者是本地类（方法内部的类）、匿名类，则该项为 0。</li>\n<li>inner_name_index: 内部类的名称，如果是匿名内部类，则该值为 0；否则引用 CONSTANT_Utf8 类型的常量池下标。</li>\n</ul>\n<p>inner_class_access_flags，访问权限</p>\n<table>\n<thead>\n<tr>\n<th>标志名称</th>\n<th>标志值</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ACC_PUBLIC</td>\n<td>0x0001</td>\n<td>public 修饰符</td>\n</tr>\n<tr>\n<td>ACC_PRIVATE</td>\n<td>0x0002</td>\n<td>private 修饰符</td>\n</tr>\n<tr>\n<td>ACC_PROTECTED</td>\n<td>0x0004</td>\n<td>protected 修饰符</td>\n</tr>\n<tr>\n<td>ACC_STATIC</td>\n<td>0x0008</td>\n<td>static 修饰符</td>\n</tr>\n<tr>\n<td>ACC_FINAL</td>\n<td>0x0010</td>\n<td>final 修饰符</td>\n</tr>\n<tr>\n<td>ACC_INTERFACE</td>\n<td>0x0200</td>\n<td>interface 类</td>\n</tr>\n<tr>\n<td>ACC_ABSTRACT</td>\n<td>0x0400</td>\n<td>abstract 修饰符</td>\n</tr>\n<tr>\n<td>ACC_SYNTHETIC</td>\n<td>0x1000</td>\n<td>表明是由编译器生成</td>\n</tr>\n<tr>\n<td>ACC_ANNOTATION</td>\n<td>0x2000</td>\n<td>annotation 类型</td>\n</tr>\n<tr>\n<td>ACC_ENUM</td>\n<td>0x4000</td>\n<td>enum 类型</td>\n</tr>\n</tbody>\n</table>\n<h4 id=\"enclosingmethod\"><a class=\"anchor\" href=\"#enclosingmethod\">#</a> EnclosingMethod</h4>\n<p>位置：ClassFile</p>\n<p>如果是匿名类或本地类 (local class) 才会存在该属性。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>EnclosingMethod_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 class_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    u2 method_index;</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>class_index</strong><br />\n 该类的全限定名引用，引用常量池下标，对应的内容类型是 CONSTANT_Class</p>\n<p><strong>method_index</strong><br />\n 如果该类不被方法或构造器包围，则该项为 0；否则引用 CONSTANT_NameAndType 类型的常量池。</p>\n<h4 id=\"synthetic\"><a class=\"anchor\" href=\"#synthetic\">#</a> Synthetic</h4>\n<p>位置：ClassFile, field_info, 或 method_info</p>\n<p>ACC_SYNTHETIC 标记编译器生成的，不显示在源文件上的类、字段、方法，这些的属性集合里都会存在该属性</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Synthetic_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>attribute_length: 固定为 0。</li>\n</ul>\n<h4 id=\"signature\"><a class=\"anchor\" href=\"#signature\">#</a> Signature</h4>\n<p>位置：ClassFile, field_info, 或 method_info</p>\n<p>签名，Java 通过反射机制获取泛型类型；</p>\n<p>因为采用擦除法实现伪泛型，编译后就没有信息了，Signature 是弥补该缺点。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Signature_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 signature_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>signature_index: 引用常量池下标，对应的内容类型是 CONSTANT_Utf8。</li>\n</ul>\n<h4 id=\"sourcefile\"><a class=\"anchor\" href=\"#sourcefile\">#</a> SourceFile</h4>\n<p>位置：ClassFile，可选</p>\n<p><code>javac -g:none / -g:source</code>  关闭或开启生成源码文件名称。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>SourceFile_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 sourcefile_index;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>sourcefile_index</strong><br />\n 源码文件名称，引用常量池的下标，对应的内容类型是 CONSTANT_Utf8。</p>\n<h4 id=\"sourcedebugextension\"><a class=\"anchor\" href=\"#sourcedebugextension\">#</a> SourceDebugExtension</h4>\n<p>位置：ClassFile，可选</p>\n<p>保存额外的调试信息，JSP 调试用到。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>SourceDebugExtension_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u1 debug_extension[attribute_length];</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>debug_extension</strong><br />\nUTF8 字节，没有结尾符 '\\0'。</p>\n<h4 id=\"linenumbertable\"><a class=\"anchor\" href=\"#linenumbertable\">#</a> LineNumberTable</h4>\n<p>位置：Code，可选</p>\n<p><code>javac -g:none / -g:lines</code>  关闭和开启，保存代码的行号，抛异常时可以查看到对应行号。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>LineNumberTable_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 line_number_table_length;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    LineNumberTable line_number_table[line_number_table_length];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>LineNumberTable &#123;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u2 start_pc;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    u2 line_number;\t</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>start_pc: 字节码行号</li>\n<li>line_number: 源码行号</li>\n</ul>\n<h4 id=\"localvariabletable\"><a class=\"anchor\" href=\"#localvariabletable\">#</a> LocalVariableTable</h4>\n<p>位置：Code，可选</p>\n<p><code>javac -g:none / -g:vars</code>  关闭和开启，保存局部变量的名称；如果没保存，则 IDE 使用 arg0、arg1 等类似的占位符。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>LocalVariableTable_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 local_variable_table_length;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    LocalVariableTable local_variable_table[local_variable_table_length];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>LocalVariableTable &#123;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u2 start_pc;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    u2 length;</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    u2 name_index;</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    u2 descriptor_index;</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    u2 index;</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>[start_pc, start_pc + length): 该局部变量作用域的范围。</li>\n<li>name_index: 变量名，引用 CONSTANT_Utf8 类型的常量池。</li>\n<li>descriptor_index: 变量的全限定名称，引用 CONSTANT_Utf8 类型的常量池。</li>\n<li>index: 在栈帧局部变量表中 Slot 的位置，如果是 long 或 double 类型，则占用 Slot 的 index 和 index + 1。</li>\n</ul>\n<h4 id=\"localvariabletypetable\"><a class=\"anchor\" href=\"#localvariabletypetable\">#</a> LocalVariableTypeTable</h4>\n<p>位置：Code，可选</p>\n<p>泛型中使用，签名。</p>\n<p>与 LocalVariableTable 类似，仅 signature_index 不一样。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>LocalVariableTypeTable_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2 local_variable_type_table_length;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    LocalVariableTypeTable local_variable_type_table[local_variable_type_table_length];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>LocalVariableTypeTable &#123;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u2 start_pc;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    u2 length;</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    u2 name_index;</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    u2 signature_index;</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    u2 index;</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>signature_index: 引用 CONSTANT_Utf8 类型的常量池。</li>\n</ul>\n<h4 id=\"deprecated\"><a class=\"anchor\" href=\"#deprecated\">#</a> Deprecated</h4>\n<p>位置：ClassFile, field_info, 或 method_info</p>\n<p>@deprecated 表明一个类、字段或方法已经不推荐使用了。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Deprecated_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"runtimevisibleannotations\"><a class=\"anchor\" href=\"#runtimevisibleannotations\">#</a> RuntimeVisibleAnnotations</h4>\n<p>位置：ClassFile, field_info, 或 method_info</p>\n<p>记录在运行时，可见的注解；通过 Java 反射 API 可以获取注解信息。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>RuntimeVisibleAnnotations_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2         attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4         attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2         num_annotations;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    annotation annotations[num_annotations];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>annotation &#123;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u2 type_index;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    u2 num_element_value_pairs;</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    ElementValuePair element_value_pairs[num_element_value_pairs];</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>ElementValuePair &#123;</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    u2 element_name_index;</pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    element_value value;</pre></td></tr><tr><td data-num=\"15\"></td><td><pre>&#125;</pre></td></tr></table></figure><ul>\n<li>type_index: CONSTANT_Utf8 类型的常量池的下标，注解的全限定名称。</li>\n<li>element_value_pairs: 注解中的元素。</li>\n<li>element_name_index: 元素名称，CONSTANT_Utf8 类型的常量池的下标。</li>\n<li>element_value: 参考下面。</li>\n</ul>\n<h4 id=\"element_value\"><a class=\"anchor\" href=\"#element_value\">#</a> element_value</h4>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>element_value &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u1 tag;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    Value value;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>union Value &#123;</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    u2 const_value_index;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    EnumConst enum_const_value;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    u2 class_info_index;</pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    annotation annotation_value;</pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    ArrayValue array_value;</pre></td></tr><tr><td data-num=\"15\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"16\"></td><td><pre>EnumConst &#123;</pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    u2 type_name_index;</pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    u2 const_name_index;</pre></td></tr><tr><td data-num=\"19\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"20\"></td><td><pre>ArrayValue &#123;</pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    u2            num_values;</pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    element_value values[num_values];</pre></td></tr><tr><td data-num=\"23\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>tag</strong><br />\n 元素值对的类型</p>\n<p>基本类型:</p>\n<table style=\"margin-bottom: 1.5em\">\n<thead>\n<tr>\n<th>类型</th>\n<th>描述</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>B</td>\n<td>byte</td>\n<td>C</td>\n<td>char</td>\n</tr>\n<tr>\n<td>D</td>\n<td>double</td>\n<td>F</td>\n<td>float</td>\n</tr>\n<tr>\n<td>I</td>\n<td>int</td>\n<td>J</td>\n<td>long</td>\n</tr>\n<tr>\n<td>S</td>\n<td>short</td>\n<td>Z</td>\n<td>boolean</td>\n</tr>\n</tbody>\n</table>\n<p>其它类型：</p>\n<table style=\"margin-bottom: 1.5em\">\n<thead>\n<tr>\n<th>类型</th>\n<th>描述</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>s</td>\n<td>String</td>\n<td>e</td>\n<td>enum constant</td>\n</tr>\n<tr>\n<td>c</td>\n<td>class</td>\n<td>@</td>\n<td>annotation type</td>\n</tr>\n<tr>\n<td>[</td>\n<td>array</td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p><strong>value</strong><br />\n 根据 tag 的不同取值，使用 value 中对应的字段。</p>\n<p><strong>const_value_index</strong><br />\n 如果 tag 是 B, C, D, F, I, J, S, Z, 或 s 其中一个，则 const_value_index 引用对应类型的常量池。</p>\n<p><strong>enum_const_value</strong><br />\n 如果 tag 是 e，则由 type_name_index 和 const_name_index 组成，记录的是枚举类型的元素。</p>\n<ul>\n<li>type_name_index: 枚举的类型全限定名，引用 CONSTANT_Utf8 类型的常量池下标。</li>\n<li>const_name_index: 枚举中定义的名称，引用 CONSTANT_Utf8 类型的常量池下标。</li>\n</ul>\n<p><strong>class_info_index</strong><br />\n 如果 tag 是 c，则记录的是 class，引用 CONSTANT_Utf8 类型的常量池下标，类的全限定名称；比如：V 代表 Void.class, Ljava/lang/Object; 代表 Object。</p>\n<p><strong>annotation_value</strong><br />\n 如果 tag 是 @，则记录的是注解，嵌套使用，参考这节的 element_value。</p>\n<p><strong>array_value</strong><br />\n 如果 tag 是 [，记录的是数组，由 num_values 和 values 组成。</p>\n<ul>\n<li>values: element_value，参考该节。</li>\n</ul>\n<h4 id=\"runtimeinvisibleannotations\"><a class=\"anchor\" href=\"#runtimeinvisibleannotations\">#</a> RuntimeInvisibleAnnotations</h4>\n<p>位置：ClassFile, field_info, or method_info</p>\n<p>与 RuntimeVisibleAnnotations 类似，这个是不可见的注解，调用 java 反射 API 时，获取不到。</p>\n<p>java 中的 Retention 注解配置。</p>\n<ul>\n<li>RetentionPolicy.SOURCE: 源码可见，比如：@Override，编译之后则不存在。</li>\n<li>RetentionPolicy.CLASS: 留在 class 文件，但忽略不处理，即记录在 RuntimeInvisibleAnnotations。</li>\n<li>RetentionPolicy.RUNTIME: 通过反射机制可以获取，即存储在 RuntimeVisibleAnnotations。</li>\n</ul>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>RuntimeInvisibleAnnotations_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2         attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4         attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2         num_annotations;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    annotation annotations[num_annotations];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"runtimevisibleparameterannotations\"><a class=\"anchor\" href=\"#runtimevisibleparameterannotations\">#</a> RuntimeVisibleParameterAnnotations</h4>\n<p>位置：method_info</p>\n<p>方法参数列表里的注解，通过反射机制可以获取到这部分注解信息。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>RuntimeVisibleParameterAnnotations_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u1 num_parameters;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    ParameterAnnotation parameter_annotations[num_parameters];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>ParameterAnnotation &#123;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u2         num_annotations;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    annotation annotations[num_annotations];</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"runtimeinvisibleparameterannotations\"><a class=\"anchor\" href=\"#runtimeinvisibleparameterannotations\">#</a> RuntimeInvisibleParameterAnnotations</h4>\n<p>位置：method_info</p>\n<p>方法参数列表里的注解，不能通过反射机制可以获取到这部分注解信息。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>RuntimeInvisibleParameterAnnotations &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2 attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4 attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u1 num_parameters;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    ParameterAnnotation parameter_annotations[num_parameters];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>ParameterAnnotation &#123;</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    u2         num_annotations;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    annotation annotations[num_annotations];</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"annotationdefault\"><a class=\"anchor\" href=\"#annotationdefault\">#</a> AnnotationDefault</h4>\n<p>位置：method_info</p>\n<p>注解类默认值。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>AnnotationDefault_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2            attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4            attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    element_value default_value;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&#125;</pre></td></tr></table></figure><h4 id=\"bootstrapmethods\"><a class=\"anchor\" href=\"#bootstrapmethods\">#</a> BootstrapMethods</h4>\n<p>位置：ClassFile</p>\n<p>invokedynamic 指引的引导方法限定符。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>BootstrapMethods_attribute &#123;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    u2              attribute_name_index;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    u4              attribute_length;</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    u2              num_bootstrap_methods;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    _bootstrap_method bootstrap_methods[num_bootstrap_methods];</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>_bootstrap_method &#123;</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    u2 bootstrap_method_ref;</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    u2 num_bootstrap_arguments;</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    u2 bootstrap_arguments[num_bootstrap_arguments];</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>&#125;</pre></td></tr></table></figure><p><strong>bootstrap_method_ref</strong><br />\n 引用 CONSTANT_MethodHandle 类型的常量池下标</p>\n<p><strong>bootstrap_arguments</strong><br />\n 可以引用以下类型的常量：</p>\n<ul>\n<li>CONSTANT_String_info</li>\n<li>CONSTANT_Class_info</li>\n<li>CONSTANT_Integer_info</li>\n<li>CONSTANT_Long_info</li>\n<li>CONSTANT_Float_info</li>\n<li>CONSTANT_Double_info</li>\n<li>CONSTANT_MethodHandle_info</li>\n<li>CONSTANT_MethodType_info</li>\n</ul>\n<h1 id=\"字节码指令\"><a class=\"anchor\" href=\"#字节码指令\">#</a> 字节码指令</h1>\n<p>指令：操作码（Opcode）+ 0 至多个操作数（Operands）</p>\n<p><span class=\"exturl\" data-url=\"aHR0cHM6Ly9kb2NzLm9yYWNsZS5jb20vamF2YXNlL3NwZWNzL2p2bXMvc2U3L2h0bWwvanZtcy03Lmh0bWw=\">Opcode 表</span></p>\n<h2 id=\"加载和存储指令\"><a class=\"anchor\" href=\"#加载和存储指令\">#</a> 加载和存储指令</h2>\n<h3 id=\"将局部变量加载到操作栈\"><a class=\"anchor\" href=\"#将局部变量加载到操作栈\">#</a> 将局部变量加载到操作栈</h3>\n<p>对应类型：</p>\n<ul>\n<li>（i, l, f, d, a）-&gt;（int, long, float, double, reference）</li>\n<li>（b, c, s）-&gt;（byte / boolean, char, short）</li>\n</ul>\n<hr />\n<p><strong>指令：</strong>  <code>iload，lload，fload，dload，aload</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt; &lt;index&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., value</code> <br />\n<strong> 变化：</strong></p>\n<ol>\n<li>将本地变量数组下标 index 下的 value 压入操作数栈；</li>\n<li>如果是 l 和 d 类型的指令，则 index 和 index + 1 都入栈，因为占 2 个 Slot。</li>\n</ol>\n<p><strong>描述：</strong> index 是本地变量数组 (local variable array) 的下标。<br />\n<strong>注意：</strong> aload 指令的 value 是 objectref，且不能用于 returnAddress 类型的加载；相反，存储指令 astore 可以存储该类型。</p>\n<hr />\n<p><strong>指令：</strong>  <code>iload_n，lload_n，fload_n，dload_n，aload_n</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., value</code> <br />\n<strong> 变化：</strong></p>\n<ol>\n<li>将本地变量数组下标 n 下的 value 压入操作数栈。</li>\n<li>如果是 l 和 d 类型的指令，则 n 和 n + 1 都入栈，因为占 2 个 Slot。</li>\n</ol>\n<p><strong>描述：</strong> 代表一组指令，n 可取的值为（0, 1, 2, 3）；n 为 index，用 n 代替 index，隐式指定 index，不带操作数；例如 iload_0 和 iload 0 语义一样。<br />\n<strong>注意：</strong> aload_n 指令的 value 是 objectref，且不能用于 returnAddress 类型的加载；相反，存储指令 astore_n 可以存储该类型。</p>\n<hr />\n<p><strong>指令：</strong></p>\n<blockquote>\n<p>iaload，laload，faload，daload，aaload, baload，caload，saload</p>\n</blockquote>\n<p><strong>格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., arrayref, index --&gt; ..., value</code> <br />\n<strong> 变化：</strong> 将操作数栈中的 arrayref 和 index 推出栈，然后将 arrayref 中 index 下的 value 压入操作数栈。<br />\n<strong>描述：</strong> 加载对应类型的数组下的值。<br />\n<strong>运行时异常：</strong></p>\n<ol>\n<li>arrayref 是 null，抛 NullPointerException 异常；</li>\n<li>index 越界，抛 ArrayIndexOutOfBoundsException 异常。</li>\n</ol>\n<h3 id=\"2-将一个数从操作数栈存储到局部变量表\"><a class=\"anchor\" href=\"#2-将一个数从操作数栈存储到局部变量表\">#</a> 2. 将一个数从操作数栈存储到局部变量表</h3>\n<p><strong>指令：</strong>  <code>istore，lstore，fstore，dstore，astore</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt; &lt;index&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value --&gt; ...</code> <br />\n<strong> 变化：</strong></p>\n<ol>\n<li>将操作数栈的 value 推出栈，然后设置本地变量数组下标 index 下的 value；</li>\n<li>如果是 l 和 d 类型的指令，则设置 index 和 index+1 下标的值，因为占 2 个 Slot。</li>\n</ol>\n<p><strong>注意：</strong> astore 指令的 value 是 objectref，且可以存储 returnAddress 类型。</p>\n<hr />\n<p><strong>指令：</strong>  <code>istore_n，lstore_n，fstore_n，dstore_n，astore_n</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value --&gt; ...</code> <br />\n<strong> 变化：</strong></p>\n<ol>\n<li>将操作数栈的 value 推出栈，然后设置本地变量数组下标 n 下的 value。</li>\n<li>如果是 l 和 d 类型，则设置 n 和 n+1 下标的值，因为占 2 个 Slot。</li>\n</ol>\n<p><strong>描述：</strong> 代表一组指令，n 可取的值为（0, 1, 2, 3）；n 为 index，用 n 代替 index，隐式指定 index，不带操作数；例如 istore_0 和 istore 0 语义一样。<br />\n<strong>注意：</strong> astore_n 指令的 value 是 objectref，且可以存储 returnAddress 类型。</p>\n<hr />\n<p><strong>指令：</strong></p>\n<blockquote>\n<p>iastore，lastore，fastore，dastore，aastore, bastore，castore，sastore</p>\n</blockquote>\n<p><strong>格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., arrayref, index, value --&gt; ...</code> <br />\n<strong> 变化：</strong> 将操作数栈中的 arrayref, index 和 value 推出栈，然后设置 arrayref 中 index 下的 value。<br />\n<strong>描述：</strong> 存储到指定位置，对应类型的数组。<br />\n<strong>运行时异常：</strong></p>\n<ol>\n<li>arrayref 是 null，抛 NullPointerException 异常；</li>\n<li>index 越界，抛 ArrayIndexOutOfBoundsException 异常；</li>\n<li>如果是 aastore 指令，源类型与目标类型不兼容（不同类型，不是子类等），抛 ArrayStoreException 异常。</li>\n</ol>\n<h3 id=\"扩展局部变量表的访问索引的指令wide\"><a class=\"anchor\" href=\"#扩展局部变量表的访问索引的指令wide\">#</a> 扩展局部变量表的访问索引的指令 wide</h3>\n<p><strong>指令：</strong>  <code>wide</code> <br />\n<strong> 格式：</strong></p>\n<blockquote>\n<p>wide &lt;opcode&gt; indexbyte1 indexbyte2<br />\nwide iinc indexbyte1 indexbyte2 constbyte1 constbyte2</p>\n</blockquote>\n<p><strong>描述：</strong></p>\n<ol>\n<li>opcode 是其中一个，iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, ret。</li>\n<li>iinc 是另外一个指令，格式不一样。</li>\n</ol>\n<h3 id=\"将一个常量加载到操作数栈中\"><a class=\"anchor\" href=\"#将一个常量加载到操作数栈中\">#</a> 将一个常量加载到操作数栈中</h3>\n<p><strong>指令：</strong>  <code>aconst_null</code> <br />\n<strong> 格式：</strong>  <code>aconst_null</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., null</code> <br />\n<strong> 描述：</strong> Push null.</p>\n<hr />\n<p><strong>指令：</strong>  <code>bipush</code> <br />\n<strong> 格式：</strong>  <code>bipush byte</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., value</code> <br />\n<strong> 描述：</strong> 将 byte 常量压入操作数栈；byte 会符合扩展成 int。</p>\n<hr />\n<p><strong>指令：</strong>  <code>sipush</code> <br />\n<strong> 格式：</strong>  <code>sipush byte1 byte2</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., value</code> <br />\n<strong> 描述：</strong> 将 byte1 和 byte2 常量组合成 short（(byte1 &lt;&lt; 8) | byte2）一起压入操作数栈；short 会符合扩展成 int。</p>\n<hr />\n<p><strong>指令：</strong>  <code>ldc</code> <br />\n<strong> 格式：</strong>  <code>ldc index</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., value</code> <br />\n<strong> 描述：</strong><br />\n将 item 从运行时常量池中加载到操作数栈：</p>\n<ol>\n<li>int 或 float 类型常量，按对应类型加载数值到操作数栈；</li>\n<li>字符串字面量的引用（reference to a string literal），将 reference 实例压入到栈中；</li>\n<li>类的符号引用（symbolic reference to a class），将类的实例压入到栈中；</li>\n<li>method type，method handle：java.lang.invoke.MethodType，java.lang.invoke.MethodHandle 对应的实例压入栈中。</li>\n</ol>\n<p><strong>异常：</strong> 解析类的符号引用（symbolic reference to a class）、method type、method handle 时，可能会抛出对应解析异常。</p>\n<hr />\n<p><strong>指令：</strong>  <code>ldc_w</code> <br />\n<strong> 格式：</strong>  <code>ldc_w indexbyte1 indexbyte2</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., value</code> <br />\n<strong> 描述：</strong> 扩展下标（(indexbyte1 &lt;&lt; 8) | indexbyte2），和 ldc 描述一致。<br />\n<strong>异常：</strong> 和 ldc 描述一致</p>\n<hr />\n<p><strong>指令：</strong>  <code>ldc2_w</code> <br />\n<strong> 格式：</strong>  <code>ldc2_w indexbyte1 indexbyte2</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., value</code> <br />\n<strong> 描述：</strong> 扩展下标（(indexbyte1 &lt;&lt; 8) | indexbyte2），将 long 和 double 类型从运行时常量池中加载到操作数栈中。</p>\n<hr />\n<p><strong>指令：</strong>  <code>iconst_&lt;i&gt;</code> <br />\n<strong> 格式：</strong>  <code>iconst_&lt;i&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., &lt;i&gt;</code> <br />\n<strong> 描述：</strong> &lt;i&gt; 可取（m1, 0, 1, 2, 3, 4, 5），m1 即 - 1；将 int 类型常量 - 1 ～ 5 其中一个压入到操作数栈中。</p>\n<hr />\n<p><strong>指令：</strong>  <code>lconst_&lt;l&gt;</code> <br />\n<strong> 格式：</strong>  <code>lconst_&lt;l&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., &lt;l&gt;</code> <br />\n<strong> 描述：</strong> &lt;l&gt; 可取（0，1），将 long 类型常量 0 或 1 压入到操作数栈中。</p>\n<hr />\n<p><strong>指令：</strong>  <code>fconst_&lt;f&gt;</code> <br />\n<strong> 格式：</strong>  <code>fconst_&lt;f&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., &lt;f&gt;</code> <br />\n<strong> 描述：</strong> &lt;f&gt; 可取（0，1，2），将 float 类型常量 0.0，1.0 或 2.0 压入到操作数栈中。</p>\n<hr />\n<p><strong>指令：</strong>  <code>dconst_&lt;d&gt;</code> <br />\n<strong> 格式：</strong>  <code>dconst_&lt;d&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., &amp;lt;d&amp;gt;</code> <br />\n<strong> 描述：</strong> &lt;d&gt; 可取（0，1），将 double 类型常量 0.0 或 1.0 压入到操作数栈中。</p>\n<h2 id=\"运算指令\"><a class=\"anchor\" href=\"#运算指令\">#</a> 运算指令</h2>\n<h3 id=\"加法指令\"><a class=\"anchor\" href=\"#加法指令\">#</a> 加法指令</h3>\n<p><strong>指令：</strong>  <code>iadd，ladd，fadd，dadd</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1, value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 将操作数栈中的两个值弹出栈然后<strong>相加</strong>，最后将结果压入栈中。int 和 long 的结果使用补码格式存储。</p>\n<h3 id=\"减法指令\"><a class=\"anchor\" href=\"#减法指令\">#</a> 减法指令</h3>\n<p><strong>指令：</strong>  <code>isub，lsub，fsub，dsub</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1, value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 将操作数栈中的两个值弹出栈然后<strong>相减</strong>，最后将结果压入栈中。int 和 long 的结果使用补码格式存储。</p>\n<h3 id=\"乘法指令\"><a class=\"anchor\" href=\"#乘法指令\">#</a> 乘法指令</h3>\n<p><strong>指令：</strong>  <code>imul，lmul，fmul，dmul</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1, value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 将操作数栈中的两个值弹出栈然后<strong>相乘</strong>，最后将结果压入栈中。int 和 long 的结果使用补码格式存储。</p>\n<h3 id=\"除法指令\"><a class=\"anchor\" href=\"#除法指令\">#</a> 除法指令</h3>\n<p><strong>指令：</strong>  <code>idiv，ldiv，fdiv，ddiv</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1, value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 将操作数栈中的两个值弹出栈然后<strong>相除</strong>，最后将结果压入栈中。<br />\n<strong>异常：</strong> int 或 long 类型导致 ArithmeticException（除 0 导致的异常）。</p>\n<h3 id=\"求余指令\"><a class=\"anchor\" href=\"#求余指令\">#</a> 求余指令</h3>\n<p><strong>指令：</strong>  <code>irem，lrem，frem，drem</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1, value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 将操作数栈中的两个值弹出栈然后<strong>求余</strong>，最后将结果压入栈中。<br />\n<strong>异常：</strong> int 或 long 类型导致 ArithmeticException（除数为 0 导致的异常）。</p>\n<h3 id=\"取反指令\"><a class=\"anchor\" href=\"#取反指令\">#</a> 取反指令</h3>\n<p><strong>指令：</strong>  <code>ineg，lneg，fneg，dneg</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 将操作数栈中的值弹出栈然后<strong>取反</strong>，最后将结果压入栈中。</p>\n<p>int 或 long 类型：-x = (~x)+1 （补码）。</p>\n<h3 id=\"移位指令\"><a class=\"anchor\" href=\"#移位指令\">#</a> 移位指令</h3>\n<p><strong>指令：</strong>  <code>ishl，lshl，ishr，lshr，iushr，lushr</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1，value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong></p>\n<ol>\n<li>左移，右移，无符号右移。</li>\n<li>int 类型，取 value2 的低 5 位（从 0 开始），value2 &amp; 0x1f，移位范围 [0, 31]。</li>\n<li>long 类型，取 value2 的低 6 位（从 0 开始），value2 &amp; 0x3f，移位范围 [0, 63]。</li>\n<li>无符合右移：左边用 0 填充移动后的空位。</li>\n</ol>\n<h3 id=\"按位与指令\"><a class=\"anchor\" href=\"#按位与指令\">#</a> 按位与指令</h3>\n<p><strong>指令：</strong>  <code>iand，land</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1，value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 按位布尔与运算。</p>\n<h3 id=\"按位或指令\"><a class=\"anchor\" href=\"#按位或指令\">#</a> 按位或指令</h3>\n<p><strong>指令：</strong>  <code>ior，lor</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1，value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 按位布尔或运算。</p>\n<h3 id=\"按位异或指令\"><a class=\"anchor\" href=\"#按位异或指令\">#</a> 按位异或指令</h3>\n<p><strong>指令：</strong>  <code>ixor，lxor</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1，value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong> 按位布尔异或运算。</p>\n<h3 id=\"局部变量自增指令\"><a class=\"anchor\" href=\"#局部变量自增指令\">#</a> 局部变量自增指令</h3>\n<p><strong>指令：</strong>  <code>iinc</code> <br />\n<strong> 格式：</strong>  <code>iinc index const</code> <br />\n<strong> 操作数栈：</strong> 无变化<br />\n<strong>描述：</strong></p>\n<ol>\n<li>index：当前帧的本地变量数组下标。</li>\n<li>const：下标对应的变量增加 const 数量。</li>\n<li>支持 wide，宽字节指令；wide iinc indexbyte1 indexbyte2 constbyte1 constbyte2。</li>\n</ol>\n<h2 id=\"操作数栈管理指令\"><a class=\"anchor\" href=\"#操作数栈管理指令\">#</a> 操作数栈管理指令</h2>\n<p>类别 1 计算类型（category 1 computational type）</p>\n<p>类别 2 计算类型（category 2 computational type）</p>\n<table>\n<thead>\n<tr>\n<th>Actual type</th>\n<th>Computational type</th>\n<th>Category</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>boolean</td>\n<td>int</td>\n<td>1</td>\n</tr>\n<tr>\n<td>byte</td>\n<td>int</td>\n<td>1</td>\n</tr>\n<tr>\n<td>char</td>\n<td>int</td>\n<td>1</td>\n</tr>\n<tr>\n<td>short</td>\n<td>int</td>\n<td>1</td>\n</tr>\n<tr>\n<td>int</td>\n<td>int</td>\n<td>1</td>\n</tr>\n<tr>\n<td>float</td>\n<td>float</td>\n<td>1</td>\n</tr>\n<tr>\n<td>reference</td>\n<td>reference</td>\n<td>1</td>\n</tr>\n<tr>\n<td>returnAddress</td>\n<td>returnAddress</td>\n<td>1</td>\n</tr>\n<tr>\n<td>long</td>\n<td>long</td>\n<td>2</td>\n</tr>\n<tr>\n<td>double</td>\n<td>double</td>\n<td>2</td>\n</tr>\n</tbody>\n</table>\n<h3 id=\"出栈\"><a class=\"anchor\" href=\"#出栈\">#</a> 出栈</h3>\n<p><strong>指令：</strong>  <code>pop，pop2</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong></p>\n<blockquote>\n<p>..., value --&gt; ... (pop、pop2 支持)<br />\n..., value1, value2 --&gt; ... （pop2 支持）</p>\n</blockquote>\n<p><strong>描述：</strong></p>\n<ol>\n<li>pop 弹出 1 个栈顶的值，仅类别 1 的计算类型使用；</li>\n<li>pop2 弹出 1 个或 2 个栈顶的值，个数的计算是根据类型计算的，long 和 double 占 2 个 Slot；类别 1 和 2 的计算类型使用。</li>\n</ol>\n<h3 id=\"复制\"><a class=\"anchor\" href=\"#复制\">#</a> 复制</h3>\n<p><strong>指令：</strong></p>\n<blockquote>\n<p>dup，dup_x1，dup_x2, dup2，dup2_x1，dup2_x2</p>\n</blockquote>\n<p><strong>格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 描述：</strong> 复制栈顶的 1 或 2 个值；根据不同的类别计算类型，操作数栈也有多种形式。<br />\n<strong>操作数栈：</strong></p>\n<p>dup: value 是类别 1，复制栈顶 1 格的值</p>\n<blockquote>\n<p>..., value --&gt; ..., value, value</p>\n</blockquote>\n<hr />\n<p>dup_x1: value1 和 value2 是类别 1；复制的值 value1 下移 1 格【不包括被复制的值的位置】</p>\n<blockquote>\n<p>..., value2, value1 --&gt; ..., value1, value2, value1</p>\n</blockquote>\n<hr />\n<p>dup_x2:</p>\n<ol>\n<li>全是类别 1；复制的值 value1 下移 2 格【不包括被复制的值的位置】\n<blockquote>\n<p>..., value3, value2, value1 --&gt; ..., value1, value3, value2, value1</p>\n</blockquote>\n</li>\n<li>value2 是类别 2，value1 是类别 1；复制的值 value1 下移 2 格【不包括被复制的值的位置】，因为 value2 直接占 2 格了\n<blockquote>\n<p>..., value2, value1 --&gt; ..., value1, value2, value1</p>\n</blockquote>\n</li>\n</ol>\n<hr />\n<p>dup2:</p>\n<ol>\n<li>全是类别 1；复制栈顶 2 格的值\n<blockquote>\n<p>..., value2, value1 --&gt; ..., value2, value1, value2, value1</p>\n</blockquote>\n</li>\n<li>全是类别 2；复制栈顶 2 格的值，因为类别 2 占 2 格\n<blockquote>\n<p>..., value --&gt; ..., value, value</p>\n</blockquote>\n</li>\n</ol>\n<hr />\n<p>dup2_x1:</p>\n<ol>\n<li>全是类别 1；复制的值 value2 和 value1 下移 1 格【不包括被复制的值的位置】\n<blockquote>\n<p>..., value3, value2, value1 --&gt; ..., value2, value1, value3, value2, value1</p>\n</blockquote>\n</li>\n<li>value1 是类别 2；value2 是类别 1，复制的值 value1 下移 1 格【不包括被复制的值的位置】，因为 value1 占 2 格\n<blockquote>\n<p>..., value2, value1 --&gt; ..., value1, value2, value1</p>\n</blockquote>\n</li>\n</ol>\n<hr />\n<p>dup2_x2:</p>\n<ol>\n<li>全是类别 1；复制的值 value2 和 value1 下移 2 格【不包括被复制的值的位置】\n<blockquote>\n<p>..., value4, value3, value2, value1 --&gt; ..., value2, value1, value4, value3, value2, value1</p>\n</blockquote>\n</li>\n<li>value1 是类别 2，其它是类别 1；复制的值 value1 下移 2 格【不包括被复制的值的位置】，因为 value1 占 2 格\n<blockquote>\n<p>..., value3, value2, value1 --&gt; ..., value1, value3, value2, value1</p>\n</blockquote>\n</li>\n<li>value3 是类别 2，其它是类别 1；复制的值 value2 和 value1 下移 2 格【不包括被复制的值的位置】，因为 value3 占 2 格\n<blockquote>\n<p>..., value3, value2, value1 --&gt; ..., value2, value1, value3, value2, value1</p>\n</blockquote>\n</li>\n<li>全是类别 2；复制的 value1 下移 2 格【不包括被复制的值的位置，因为 value1 和 value2 占 2 格\n<blockquote>\n<p>..., value2, value1 --&gt; ..., value1, value2, value1</p>\n</blockquote>\n</li>\n</ol>\n<h3 id=\"交换\"><a class=\"anchor\" href=\"#交换\">#</a> 交换</h3>\n<p><strong>指令：</strong>  <code>swap</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value2, value1 --&gt; ..., value1, value2</code> <br />\n<strong> 描述：</strong><br />\n交换栈顶的第 1 和第 2 格的值；仅支持类别 1 的操作，没有类别 2 的交换指令。</p>\n<h2 id=\"类型转换指令\"><a class=\"anchor\" href=\"#类型转换指令\">#</a> 类型转换指令</h2>\n<p><strong>指令：</strong></p>\n<blockquote>\n<p>i2l，i2f，i2d<br />\nl2i，l2f，l2d<br />\nf2i，f2l，f2d<br />\nd2i，d2l，d2f</p>\n</blockquote>\n<p><strong>格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value --&gt; ..., result</code> <br />\n<strong> 描述：</strong> i，l，f，d 相互转换。</p>\n<hr />\n<p><strong>指令：</strong>  <code>i2b，i2c，i2s</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value --&gt; ..., result</code> <br />\n<strong> 描述：</strong> int 转换成 byte、char、short 类型。</p>\n<h2 id=\"比较运算指令\"><a class=\"anchor\" href=\"#比较运算指令\">#</a> 比较运算指令</h2>\n<h3 id=\"比较大小\"><a class=\"anchor\" href=\"#比较大小\">#</a> 比较大小</h3>\n<p><strong>指令：</strong>  <code>lcmp，fcmpl，fcmpg，dcmpl，dcmpg</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt;</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1, value2 --&gt; ..., result</code> <br />\n<strong> 描述：</strong><br />\n比较 value1 与 value2 的大小：</p>\n<ol>\n<li>value1 &gt; value2 =&gt; result = 1</li>\n<li>value1 = value2 =&gt; result = 0</li>\n<li>value1 &lt; value2 =&gt; result = -1</li>\n</ol>\n<p>fcmpl 与 fcmpg，dcmpl 与 dcmpg 的区别的是：如果 value1、value2 中任意 1 个是 NaN，则 fcmpl 和 dcmpl 的值是 - 1，而 fcmpg 和 dcmpg 的值是 1。</p>\n<h2 id=\"条件分支\"><a class=\"anchor\" href=\"#条件分支\">#</a> 条件分支</h2>\n<p><strong>指令：</strong>  <code>ifeq，ifne，iflt，ifge，ifgt，ifle</code> <br />\n<strong> 格式：</strong>  <code>&lt;指令&gt; branchbyte1 branchbyte2</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value --&gt; ...</code> <br />\n<strong> 描述：</strong></p>\n<ol>\n<li>value 与 0 比较，包括符号位，value 的类型是 int；</li>\n<li>如果成立，则构造 16 位的无符号偏移量，即 (branchbyte1 &lt;&lt; 8) | branchbyte2，然后跳到（address + 偏移量）的位置执行指令；</li>\n<li>不成立则继续执行 if&lt;cond&gt; 后面的指令。</li>\n</ol>\n<ul>\n<li>eq =&gt; value = 0</li>\n<li>ne =&gt; value ≠ 0</li>\n<li>lt =&gt; value &lt; 0</li>\n<li>le =&gt; value ≤ 0</li>\n<li>gt =&gt; value &gt; 0</li>\n<li>ge =&gt; value ≥ 0</li>\n</ul>\n<hr />\n<p><strong>指令：</strong></p>\n<blockquote>\n<p>if_icmpeq，if_icmpne，if_icmplt，if_icmpge，if_icmpgt，if_icmple<br />\nif_acmpeq，if_acmpne</p>\n</blockquote>\n<p><strong>格式：</strong>  <code>&lt;指令&gt; branchbyte1 branchbyte2</code> <br />\n<strong> 操作数栈：</strong>  <code>..., value1, value2 --&gt; ...</code> <br />\n<strong> 描述：</strong></p>\n<ol>\n<li>i 代表 value1 和 value2 是 int 类型；a 代表 value1 和 value2 是 reference 类型；</li>\n<li>value1 与 value2 比较；</li>\n<li>如果成立，则构造 16 位的无符号偏移量，即 (branchbyte1 &lt;&lt; 8) | branchbyte2，然后跳到（address + 偏移量）的位置执行指令；</li>\n<li>不成立则继续执行 if_&lt;cond&gt; 后面的指令。</li>\n</ol>\n<ul>\n<li>eq =&gt; value1 = value2</li>\n<li>ne =&gt; value1 ≠ value2</li>\n<li>lt =&gt; value1 &lt; value2</li>\n<li>le =&gt; value1 ≤ value2</li>\n<li>gt =&gt; value1 &gt; value2</li>\n<li>ge =&gt; value1 ≥ value2</li>\n</ul>\n<h2 id=\"引用相关指令\"><a class=\"anchor\" href=\"#引用相关指令\">#</a> 引用相关指令</h2>\n<h3 id=\"创建类示例\"><a class=\"anchor\" href=\"#创建类示例\">#</a> 创建类示例</h3>\n<p><strong>指令：</strong>  <code>new</code> <br />\n<strong> 格式：</strong>  <code>new indexbyte1 indexbyte2</code> <br />\n<strong> 操作数栈：</strong>  <code>... --&gt; ..., objectref</code> <br />\n<strong> 描述：</strong></p>\n<ol>\n<li>index = (indexbyte1 &lt;&lt; 8) | indexbyte2；运行时常量池；</li>\n<li>在垃圾回收堆内存中分配并初始化，然后 objectref 引用该内存，最后将 objectref 压入操作栈。</li>\n</ol>\n<h3 id=\"创建数组的指令\"><a class=\"anchor\" href=\"#创建数组的指令\">#</a> 创建数组的指令</h3>\n<h3 id=\"访问类字段\"><a class=\"anchor\" href=\"#访问类字段\">#</a> 访问类字段</h3>\n<h3 id=\"方法调用\"><a class=\"anchor\" href=\"#方法调用\">#</a> 方法调用</h3>\n<h3 id=\"获取数组长度\"><a class=\"anchor\" href=\"#获取数组长度\">#</a> 获取数组长度</h3>\n<h3 id=\"检查实例类型\"><a class=\"anchor\" href=\"#检查实例类型\">#</a> 检查实例类型</h3>\n<h3 id=\"异常处理\"><a class=\"anchor\" href=\"#异常处理\">#</a> 异常处理</h3>\n<h3 id=\"同步指令\"><a class=\"anchor\" href=\"#同步指令\">#</a> 同步指令</h3>\n<h2 id=\"其它指令\"><a class=\"anchor\" href=\"#其它指令\">#</a> 其它指令</h2>\n<p><strong>指令：</strong>  <code>nop</code> <br />\n<strong> 格式：</strong>  <code>nop</code> <br />\n<strong> 描述：</strong> 不做任何处理。</p>\n",
            "tags": [
                "java",
                "jvm",
                "java",
                "jvm",
                "class",
                "struct"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/04/16/rust/6.%20%E5%8C%85%E5%92%8Ccrate/",
            "url": "https://blog.ceciljxsu.icu/2023/04/16/rust/6.%20%E5%8C%85%E5%92%8Ccrate/",
            "title": "6. 包和crate",
            "date_published": "2023-04-16T11:20:20.000Z",
            "content_html": "<h1 id=\"包和-crate\"><a class=\"anchor\" href=\"#包和-crate\">#</a> 包和 Crate</h1>\n<p>一个包，包含一个或多个 crate，并且只有一个 Cargo.toml 文件，阐述如何构建这些 crate。</p>\n<h2 id=\"模块\"><a class=\"anchor\" href=\"#模块\">#</a> 模块</h2>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// src/lib.rs</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">front_of_house</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">hosting</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">seat_at_table</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">serving</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">take_order</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">server_order</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">take_payment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>相当于路径</p>\n<pre><code>crate\n    front_of_house\n        hosting\n            add_to_waitlist\n            seat_at_table\n        serving\n            take_order\n            server_order\n            take_payment\n</code></pre>\n<p><span class=\"exturl\" data-url=\"aHR0cDovL21haW4ucnM=\">main.rs</span> 和 <span class=\"exturl\" data-url=\"aHR0cDovL2xpYi5ycw==\">lib.rs</span> 都称为 crate 根</p>\n<p>整个模块数都植根于隐式模块 crate 下</p>\n<h2 id=\"引用模块树的项\"><a class=\"anchor\" href=\"#引用模块树的项\">#</a> 引用模块树的项</h2>\n<ol>\n<li>相对路径：以 self、super 来标识</li>\n<li>绝对路径：以 crate 来标识</li>\n</ol>\n<p>使用：：分隔</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">front_of_house</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">hosting</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">eat_at_restaurant</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token comment\">// 绝对路径</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">crate</span><span class=\"token module-declaration namespace\"><span class=\"token punctuation\">::</span>front_of_house<span class=\"token punctuation\">::</span>hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 相对路径</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token namespace\">front_of_house<span class=\"token punctuation\">::</span>hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>建议使用绝对路径，因为项目结构调整是经常的。</p>\n<h2 id=\"私有性边界\"><a class=\"anchor\" href=\"#私有性边界\">#</a> 私有性边界</h2>\n<p>上面的代码编译会失败，因为知道路径，但有些是私有的，不给使用。</p>\n<ul>\n<li>Rust 中所有的条目默认是私有的：函数、方法、struct、enum、模块、常量</li>\n<li>父级不能使用子级的东西，而子级可以使用父级的东西。</li>\n</ul>\n<h2 id=\"pub-使公有化\"><a class=\"anchor\" href=\"#pub-使公有化\">#</a> pub - 使公有化</h2>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">front_of_house</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">pub</span> <span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">hosting</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">eat_at_restaurant</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token comment\">// 绝对路径</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">crate</span><span class=\"token module-declaration namespace\"><span class=\"token punctuation\">::</span>front_of_house<span class=\"token punctuation\">::</span>hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 相对路径</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token namespace\">front_of_house<span class=\"token punctuation\">::</span>hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>内部的每一层都要加 pub 才能访问内部</p>\n<p>同级是可以直接访问的</p>\n<h2 id=\"super-相对路径\"><a class=\"anchor\" href=\"#super-相对路径\">#</a> super - 相对路径</h2>\n<p>super 可以改变模块访问边界，类似目录系统中的  <code>../</code>  上一层</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">server_order</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">back_of_house</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">fix_incorrect_order</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token function\">cook_order</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token comment\">//super 改变路径位置</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token comment\">// 注意：fn 不算是一层路径</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token comment\">//mod 才是路径边界</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token comment\">// 所以 super 是 back_of_house 的上一层</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">super</span><span class=\"token module-declaration namespace\"><span class=\"token punctuation\">::</span>server_order</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">cook_order</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"pub-struct\"><a class=\"anchor\" href=\"#pub-struct\">#</a> pub struct</h2>\n<ul>\n<li>pub 放在 struct 前：\n<ul>\n<li>struct 是公共的</li>\n<li>struct 内的字段默认是私有的</li>\n</ul>\n</li>\n<li>struct 字段前添加 pub 设置为公共的</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">back_of_house</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">pub</span> <span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Breakfast</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">pub</span> toast<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        seasonal_fruit<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">impl</span> <span class=\"token class-name\">Breakfast</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">summer</span><span class=\"token punctuation\">(</span>toast<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Breakfast</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            <span class=\"token class-name\">Breakfast</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>                toast<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span>toast<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>                seasonal_fruit<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"peaches\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">eat_at_restuarant</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> meal <span class=\"token operator\">=</span> <span class=\"token namespace\">back_of_house<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Breakfast</span><span class=\"token punctuation\">::</span><span class=\"token function\">summer</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Rye\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token comment\">//toast 字段是公共的，外部可以访问</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    meal<span class=\"token punctuation\">.</span>toast <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Wheat\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"I'd like &#123;&#125; toast please\"</span><span class=\"token punctuation\">,</span> meal<span class=\"token punctuation\">.</span>toast<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token comment\">// 这里 seasonal_fruit 会报错，因为此字段是私有的，外部不可访问</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    meal<span class=\"token punctuation\">.</span>seasonal_fruit <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"blueberries\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"pub-enum\"><a class=\"anchor\" href=\"#pub-enum\">#</a> pub enum</h2>\n<p>把 pub 放在 enum 前：</p>\n<ul>\n<li>enum 是公共的</li>\n<li>enum 的变体也都是公共的</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">back_of_house</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">pub</span> <span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">Appetizer</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token comment\">// 以下变体，默认为公有的，此规则是例外；因为枚举在公共时才有意义</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token class-name\">Soup</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token class-name\">Salad</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"use-关键词\"><a class=\"anchor\" href=\"#use-关键词\">#</a> use - 关键词</h2>\n<p>使用 use 关键字将路径导入到作用域内</p>\n<ul>\n<li>可导入绝对路径或相对路径</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">front_of_house</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">pub</span> <span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">hosting</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 导入绝对路径，建议绝对路径</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token keyword\">crate</span><span class=\"token module-declaration namespace\"><span class=\"token punctuation\">::</span>front_of_house<span class=\"token punctuation\">::</span></span>hosting<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\">// 以下一行是导入相对路径</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\">// use front_of_house::hosting;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">eat_at_restuarant</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token namespace\">hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token namespace\">hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token namespace\">hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"use-惯用用法\"><a class=\"anchor\" href=\"#use-惯用用法\">#</a> use - 惯用用法</h3>\n<ol>\n<li>函数：将函数的父级模块引入作用域（指定到父级），目的：方便知道函数是外部还是当前文件定义的。</li>\n<li>struct、enum，其它：指定完整路径（指定到本身）</li>\n<li>同名条目：指定到父级</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>fmt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>io<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">// Result 同名，需要指定到父级</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token namespace\">fmt<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Result</span> <span class=\"token punctuation\">&#123;</span><span class=\"token comment\">/*impl*/</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">f2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token namespace\">io<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Result</span> <span class=\"token punctuation\">&#123;</span><span class=\"token comment\">/*impl*/</span><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"as-别名\"><a class=\"anchor\" href=\"#as-别名\">#</a> as - 别名</h3>\n<p>as 关键字可以为 use 引入的路径指定本地的别名</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>fmt<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Result</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>io<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Result</span> <span class=\"token keyword\">as</span> <span class=\"token class-name\">IoResult</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span> <span class=\"token punctuation\">&#123;</span><span class=\"token comment\">/*impl*/</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">f2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">IoResult</span> <span class=\"token punctuation\">&#123;</span><span class=\"token comment\">/*impl*/</span><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"pub-use-重新导出名称\"><a class=\"anchor\" href=\"#pub-use-重新导出名称\">#</a> pub use - 重新导出名称</h3>\n<p>在 use 前面添加 pub，重导出模块</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 外部不能访问</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">front_of_house</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">pub</span> <span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">hosting</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 重导出，这样外部能访问 hosting</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">use</span> <span class=\"token keyword\">crate</span><span class=\"token module-declaration namespace\"><span class=\"token punctuation\">::</span>front_of_house<span class=\"token punctuation\">::</span></span>hosting<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\">// 外部能访问</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">eat_at_restuarant</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token namespace\">hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token namespace\">hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token namespace\">hosting<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"package-使用外部包\"><a class=\"anchor\" href=\"#package-使用外部包\">#</a> package - 使用外部包</h3>\n<ol>\n<li>Cargo.toml 添加依赖的包（package）：国内建议配置镜像\n<ul>\n<li><span class=\"exturl\" data-url=\"aHR0cHM6Ly9jcmF0ZXMuaW8=\">https://crates.io</span></li>\n</ul>\n</li>\n<li>use 将依赖包内特定的条目引入到作用域</li>\n</ol>\n<h3 id=\"嵌套路径-优化-use-语句\"><a class=\"anchor\" href=\"#嵌套路径-优化-use-语句\">#</a> 嵌套路径 - 优化 use 语句</h3>\n<p>如果使用同一个包或模块下的多个条目，则导致多条 use 语句。可以提取公共部分，把不同的部分放到嵌套路径上。</p>\n<ul>\n<li><code>路径相同部分::&#123;路径差异的部分&#125;</code></li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// use std::cmp::Ordering;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// use std::io;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">// 使用嵌套路径优化</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span><span class=\"token punctuation\">&#123;</span><span class=\"token namespace\">cmp<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">,</span> io<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><ul>\n<li>如果两个 use 路径之一是另外一个的子路径时：</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// use std::io;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// use std::io::Write;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">// 使用嵌套路径，以及 self 优化路径</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>io<span class=\"token punctuation\">::</span></span><span class=\"token punctuation\">&#123;</span><span class=\"token keyword\">self</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Write</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"通配符\"><a class=\"anchor\" href=\"#通配符\">#</a> 通配符 *</h3>\n<ul>\n<li>使用 * 可以把路径中所有的公共条目都引入到作用域。</li>\n<li>应用场景：\n<ul>\n<li>测试。（将所有被测试代码引入到 tests 模块）</li>\n<li>用于预导入（prelude）模块</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"将模块拆分到其它文件\"><a class=\"anchor\" href=\"#将模块拆分到其它文件\">#</a> 将模块拆分到其它文件</h2>\n<ul>\n<li>\n<p>模块定义时，如果模块名后面是  <code>;</code>  结尾，而不是代码块时：</p>\n<ul>\n<li>rust 会从与模块同名的文件中加载内容</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 文件：src/lib.rs</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">//rust 会找此文件目录下的 front_of_house.rs 文件</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">front_of_house</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 文件：src/front_of_house.rs</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">hosting</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></li>\n<li>\n<p>多层模块嵌套时：</p>\n</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 文件：src/lib.rs</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">//rust 会找此文件目录下的 front_of_house.rs 文件</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">front_of_house</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 文件：src/front_of_house.rs</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">//rust 会找此文件目录下的 front_of_house/hosting.rs 文件</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">mod</span> <span class=\"token module-declaration namespace\">hosting</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// src/front_of_house/hosting.rs</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">add_to_waitlist</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure>",
            "tags": [
                "Rust基础",
                "rust"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/04/16/rust/5.%20%E6%9E%9A%E4%B8%BE%E4%B8%8E%E6%A8%A1%E5%BC%8F%E5%8C%B9%E9%85%8D/",
            "url": "https://blog.ceciljxsu.icu/2023/04/16/rust/5.%20%E6%9E%9A%E4%B8%BE%E4%B8%8E%E6%A8%A1%E5%BC%8F%E5%8C%B9%E9%85%8D/",
            "title": "5. 枚举与模式匹配",
            "date_published": "2023-04-16T10:20:20.000Z",
            "content_html": "<h1 id=\"定义枚举\"><a class=\"anchor\" href=\"#定义枚举\">#</a> 定义枚举</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">IpAddrKind</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token constant\">V4</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token constant\">V6</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>最后一个 逗号 可加，可不加</p>\n<h1 id=\"枚举值\"><a class=\"anchor\" href=\"#枚举值\">#</a> 枚举值</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">let</span> four <span class=\"token operator\">=</span> <span class=\"token class-name\">IpAddrKind</span><span class=\"token punctuation\">::</span><span class=\"token constant\">V4</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">let</span> six <span class=\"token operator\">=</span> <span class=\"token class-name\">IpAddrKind</span><span class=\"token punctuation\">::</span><span class=\"token constant\">V6</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">route</span><span class=\"token punctuation\">(</span>ip_type<span class=\"token punctuation\">:</span> <span class=\"token class-name\">IpAddrKind</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">IpAddr</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    kind<span class=\"token punctuation\">:</span> <span class=\"token class-name\">IpAddrKind</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    address<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"枚举成员嵌套任意类型\"><a class=\"anchor\" href=\"#枚举成员嵌套任意类型\">#</a> 枚举成员嵌套任意类型</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">IpAddrKind</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token constant\">V4</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">u8</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">u8</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">u8</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">u8</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token constant\">V6</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">let</span> home <span class=\"token operator\">=</span> <span class=\"token class-name\">IpAddrKind</span><span class=\"token punctuation\">::</span><span class=\"token constant\">V4</span><span class=\"token punctuation\">(</span><span class=\"token number\">127</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">let</span> loopback <span class=\"token operator\">=</span> <span class=\"token class-name\">IpAddrKind</span><span class=\"token punctuation\">::</span><span class=\"token constant\">V6</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"::1\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h1 id=\"标准库如何定义-ip-地址\"><a class=\"anchor\" href=\"#标准库如何定义-ip-地址\">#</a> 标准库如何定义 ip 地址？</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Ipv4Addr</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 省略字段</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Ipv6Addr</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 省略字段</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">IpAddr</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token constant\">V4</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Ipv4Addr</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token constant\">V6</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Ipv6Addr</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"枚举还可以定义-impl\"><a class=\"anchor\" href=\"#枚举还可以定义-impl\">#</a> 枚举还可以定义 impl</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">Message</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token class-name\">Quit</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token class-name\">Move</span> <span class=\"token punctuation\">&#123;</span>x<span class=\"token punctuation\">:</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">:</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token class-name\">Write</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token class-name\">ChangeColor</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 与 struct 类似</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">QuitMessage</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">MoveMessage</span> <span class=\"token punctuation\">&#123;</span>x<span class=\"token punctuation\">:</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">:</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">WriteMessage</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">ChangeColorMessage</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\">// 还可以使用 impl</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">impl</span> <span class=\"token class-name\">Message</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">call</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">self</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token comment\">// todo</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token comment\">// m.call();</span></pre></td></tr></table></figure><h1 id=\"option\"><a class=\"anchor\" href=\"#option\">#</a> Option</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">Option</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">T</span><span class=\"token operator\">></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token class-name\">Some</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">T</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token class-name\">None</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>因为常用，所以 Some 和 None 可单独使用。</p>\n<p>例如：</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">let</span> some_number <span class=\"token operator\">=</span> <span class=\"token class-name\">Some</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// None 无法推断类型，因此需要指定类型；</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">let</span> absent_number<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Option</span><span class=\"token operator\">&lt;</span><span class=\"token keyword\">i32</span><span class=\"token operator\">></span> <span class=\"token operator\">=</span> <span class=\"token class-name\">None</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h1 id=\"match-控制流\"><a class=\"anchor\" href=\"#match-控制流\">#</a> match 控制流</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> coin <span class=\"token operator\">=</span> <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Penny</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> value <span class=\"token operator\">=</span> <span class=\"token keyword\">match</span> coin <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Penny</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>            <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Penny\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>            <span class=\"token number\">1</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Nickel</span> <span class=\"token operator\">=></span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Dime</span> <span class=\"token operator\">=></span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Quarter</span> <span class=\"token operator\">=></span> <span class=\"token number\">25</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">Coin</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token class-name\">Penny</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token class-name\">Nickel</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token class-name\">Dime</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token class-name\">Quarter</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"绑定值的形式\"><a class=\"anchor\" href=\"#绑定值的形式\">#</a> 绑定值的形式</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> coin <span class=\"token operator\">=</span> <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Quarter</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">UsState</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Alaska</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> value <span class=\"token operator\">=</span> <span class=\"token function\">value_in_cents</span><span class=\"token punctuation\">(</span>coin<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">value_in_cents</span><span class=\"token punctuation\">(</span>coin<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token keyword\">u8</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">match</span> coin <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Penny</span> <span class=\"token operator\">=></span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Nickel</span> <span class=\"token operator\">=></span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Dime</span> <span class=\"token operator\">=></span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token class-name\">Coin</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Quarter</span><span class=\"token punctuation\">(</span>state<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"state: &#123;:?&#125;\"</span><span class=\"token punctuation\">,</span> state<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            <span class=\"token number\">25</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token attribute attr-name\">#[derive(Debug)]</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">UsState</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token class-name\">Alabama</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token class-name\">Alaska</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token comment\">// -- snip --</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">Coin</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token class-name\">Penny</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token class-name\">Nickel</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token class-name\">Dime</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token class-name\">Quarter</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">UsState</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>注意事项：</p>\n<ol>\n<li>使用时，不要忘记前缀： <code>Coin::</code></li>\n<li>使用时，不要忘记符号：  <code>=&gt;</code></li>\n<li>打印时，不要忘记注解和符号： <code>#derive(Debug)</code>  和  <code>&#123;:?&#125;</code></li>\n</ol>\n<h1 id=\"匹配-optiont\"><a class=\"anchor\" href=\"#匹配-optiont\">#</a> 匹配 Option&lt;T&gt;</h1>\n<p>如何获取 Option 里面的值呢？</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">plus_one</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Option</span><span class=\"token operator\">&lt;</span><span class=\"token keyword\">i32</span><span class=\"token operator\">></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Option</span><span class=\"token operator\">&lt;</span><span class=\"token keyword\">i32</span><span class=\"token operator\">></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">match</span> x <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token class-name\">None</span> <span class=\"token operator\">=></span> <span class=\"token class-name\">None</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token class-name\">Some</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token class-name\">Some</span><span class=\"token punctuation\">(</span>i <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"匹配是穷尽的\"><a class=\"anchor\" href=\"#匹配是穷尽的\">#</a> 匹配是穷尽的</h1>\n<p>match 需要穷尽，如果某个分支没匹配到，就会编译不通过。</p>\n<h1 id=\"_-通配符\"><a class=\"anchor\" href=\"#_-通配符\">#</a> _ 通配符</h1>\n<p>如果有些不想匹配，则可以用通配符，相当于 default 分支。</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">let</span> some_u8_value <span class=\"token operator\">=</span> <span class=\"token number\">0u8</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">match</span> some_u8_value <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token number\">1</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"one\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token number\">3</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"three\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token number\">5</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"five\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token number\">7</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"seven\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    _ <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>如果只考虑其中 1 个分支，就啰嗦了，因此有 if let</p>\n<h1 id=\"if-let-简化匹配\"><a class=\"anchor\" href=\"#if-let-简化匹配\">#</a> if let 简化匹配</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">let</span> some_u8_value <span class=\"token operator\">=</span> <span class=\"token class-name\">Some</span><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// if let</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token keyword\">let</span> <span class=\"token class-name\">Some</span><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> some_u8_value <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"three\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>这样就不用每个分支都要穷尽。</p>\n",
            "tags": [
                "Rust基础",
                "rust"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/04/15/rust/4.%20%E7%BB%93%E6%9E%84%E4%BD%93/",
            "url": "https://blog.ceciljxsu.icu/2023/04/15/rust/4.%20%E7%BB%93%E6%9E%84%E4%BD%93/",
            "title": "4. 结构体",
            "date_published": "2023-04-15T10:20:20.000Z",
            "content_html": "<h1 id=\"定义\"><a class=\"anchor\" href=\"#定义\">#</a> 定义</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">User</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    name<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    age<span class=\"token punctuation\">:</span> <span class=\"token keyword\">usize</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    gender<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u8</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"使用\"><a class=\"anchor\" href=\"#使用\">#</a> 使用</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> user <span class=\"token operator\">=</span> <span class=\"token class-name\">User</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    name<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Cecil\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    age<span class=\"token punctuation\">:</span> <span class=\"token number\">26</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    gender<span class=\"token punctuation\">:</span> <span class=\"token char\">b'M'</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h1 id=\"简化\"><a class=\"anchor\" href=\"#简化\">#</a> 简化</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">build_user</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span> user<span class=\"token punctuation\">:</span> <span class=\"token class-name\">User</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">User</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token class-name\">User</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        name<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token punctuation\">..</span>user</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>name 要和字段同名才可以，否则还是得 name: name1</p>\n<h1 id=\"元组结构体\"><a class=\"anchor\" href=\"#元组结构体\">#</a> 元组结构体</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Color</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Point</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">let</span> black <span class=\"token operator\">=</span> <span class=\"token class-name\">Color</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">let</span> origin <span class=\"token operator\">=</span> <span class=\"token class-name\">Point</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h1 id=\"类单元结构体\"><a class=\"anchor\" href=\"#类单元结构体\">#</a> 类单元结构体</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Unit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">let</span> unit <span class=\"token operator\">=</span> <span class=\"token class-name\">Unit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h1 id=\"结构体的所有权\"><a class=\"anchor\" href=\"#结构体的所有权\">#</a> 结构体的所有权</h1>\n<p>结构体内，定义需要自身所有权；例如 String，不能是 &amp;str 的 slice 类型</p>\n<p>否则拥有其它对象的引用会编译错误，除非加上生命周期。后面章节讲。</p>\n<p>结构体是为了组织代码。面向对象的思想。</p>\n<p>但是直接打印，会报错</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> rectangle <span class=\"token operator\">=</span> <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        width<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        height<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> rectangle<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    width<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    height<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>改进，需要实现 Display 和 Debug trait</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> rectangle <span class=\"token operator\">=</span> <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        width<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        height<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;:#?&#125;\"</span><span class=\"token punctuation\">,</span> rectangle<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token attribute attr-name\">#[derive(Debug)]</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    width<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    height<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"方法与结构体紧密联系\"><a class=\"anchor\" href=\"#方法与结构体紧密联系\">#</a> 方法与结构体紧密联系</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">impl</span> <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">area</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">self</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token keyword\">u32</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>width <span class=\"token operator\">*</span> <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>height</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 创建 rectangle</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// rectangle.area();</span></pre></td></tr></table></figure><p>&amp;self 和 &amp;Retangle 类似，仅仅获取引用，不获取所有权。</p>\n<p>如果想修改则使用 &amp;mut self</p>\n<h1 id=\"-运算符去哪了\"><a class=\"anchor\" href=\"#-运算符去哪了\">#</a> -&gt; 运算符去哪了？</h1>\n<p>其它语言，如果是指针，需要这样用：obj-&gt;something ()，或者 (*obj).something ();</p>\n<p>Rust 会自动引用和解引用</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>p1<span class=\"token punctuation\">.</span><span class=\"token function\">something</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>p2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// 等效</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>p1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">something</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>p2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h1 id=\"方法不带-self\"><a class=\"anchor\" href=\"#方法不带-self\">#</a> 方法不带 &amp;self ?</h1>\n<p>不带的话，还是称为函数，使用时，使用：：符号，例如：String::from (&quot;&quot;);</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 类似 Java 的静态方法</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> rectangle <span class=\"token operator\">=</span> <span class=\"token class-name\">Rectangle</span><span class=\"token punctuation\">::</span><span class=\"token function\">rectangle</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> rectangle<span class=\"token punctuation\">.</span><span class=\"token function\">area</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token attribute attr-name\">#[derive(Debug)]</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token type-definition class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    width<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    height<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token keyword\">impl</span> <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">area</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">self</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token keyword\">u32</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>width <span class=\"token operator\">*</span> <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>height</pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token comment\">// 不带 &amp;self</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">rectangle</span><span class=\"token punctuation\">(</span>size<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            width<span class=\"token punctuation\">:</span> size<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            height<span class=\"token punctuation\">:</span> size</pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"多个-impl-块\"><a class=\"anchor\" href=\"#多个-impl-块\">#</a> 多个 impl 块</h1>\n<p>支持多个 impl 块定义</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">impl</span> <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">area</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">self</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token keyword\">u32</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>width <span class=\"token operator\">*</span> <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>height</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">impl</span> <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">rectangle</span><span class=\"token punctuation\">(</span>size<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token class-name\">Rectangle</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>            width<span class=\"token punctuation\">:</span> size<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            height<span class=\"token punctuation\">:</span> size</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>不过还是建议放在一起，除非和 trait 配合使用</p>\n",
            "tags": [
                "Rust基础",
                "rust"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/04/14/rust/3.%20%E6%89%80%E6%9C%89%E6%9D%83/",
            "url": "https://blog.ceciljxsu.icu/2023/04/14/rust/3.%20%E6%89%80%E6%9C%89%E6%9D%83/",
            "title": "3. 所有权",
            "date_published": "2023-04-14T10:20:20.000Z",
            "content_html": "<h1 id=\"stack-vs-heap\"><a class=\"anchor\" href=\"#stack-vs-heap\">#</a> stack vs. heap</h1>\n<p>stack 速度比 heap 快</p>\n<p>所有权解决的问题：</p>\n<ol>\n<li>跟踪代码哪些部分正在使用 heap 的哪些数据</li>\n<li>最小化 heap 上的重复数据量</li>\n<li>清理 heap 上未使用的数据，以避免空间不足</li>\n</ol>\n<p>管理 heap 数据是所有权的主要原因</p>\n<h1 id=\"所有权规则\"><a class=\"anchor\" href=\"#所有权规则\">#</a> 所有权规则</h1>\n<ol>\n<li>每个值都有一个变量，这个变量是该值的所有者</li>\n<li>每个值同时只能有一个所有者</li>\n<li>当所有者超出作用域（scope）时，该值将被删除。</li>\n</ol>\n<h1 id=\"变量作用域\"><a class=\"anchor\" href=\"#变量作用域\">#</a> 变量作用域</h1>\n<ul>\n<li>scope 就是程序中一个项目的有效范围</li>\n</ul>\n<h1 id=\"所有权举例string-类型\"><a class=\"anchor\" href=\"#所有权举例string-类型\">#</a> 所有权举例：String 类型</h1>\n<ol>\n<li>String 比那些基础标量数据类型更复杂</li>\n<li>字符串字面值：程序里手写的那些字符串值。不可变。</li>\n<li>String 在 heap 创建</li>\n</ol>\n<h2 id=\"创建-string-类型的值\"><a class=\"anchor\" href=\"#创建-string-类型的值\">#</a> 创建 String 类型的值</h2>\n<p>使用 from 函数从字符串字面值创建出 String 类型</p>\n<p>let mut s = String::from(&quot;Hello&quot;);</p>\n<p>这类字符串是可以被修改的</p>\n<p>内存：</p>\n<ol>\n<li>内存不释放就浪费内存</li>\n<li>提前释放，变量就非法</li>\n<li>释放多次就导致 bug，因此必须一次分配对应一次释放</li>\n</ol>\n<h1 id=\"内存和分配\"><a class=\"anchor\" href=\"#内存和分配\">#</a> 内存和分配</h1>\n<ol>\n<li>rust 对于某个值来说，当拥有它的变量走出作用范围时，内存就会立即自动交还给操作系统</li>\n<li>drop 函数</li>\n</ol>\n<h1 id=\"变量和数据交互的方式移动move\"><a class=\"anchor\" href=\"#变量和数据交互的方式移动move\">#</a> 变量和数据交互的方式：移动（move）</h1>\n<ol>\n<li>多个变量可以与同一个数据使用一种独特的方式来交互</li>\n</ol>\n<p>let x = 5;</p>\n<p>let y = x;</p>\n<p>这 2 个变量的值压入到 stack 中</p>\n<h1 id=\"变量和数据交互的方式移动string-版本\"><a class=\"anchor\" href=\"#变量和数据交互的方式移动string-版本\">#</a> 变量和数据交互的方式：移动，String 版本</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> s1 <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> s2 <span class=\"token operator\">=</span> s1<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// 这里会报错；</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 因为 s1 的值所有权已经移动到 s2 了；</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">//s1 失效，不能再使用了</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> s1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// error.</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"浅拷贝-深拷贝和移动\"><a class=\"anchor\" href=\"#浅拷贝-深拷贝和移动\">#</a> 浅拷贝、深拷贝和移动</h2>\n<p>浅拷贝（shallow copy）和深拷贝（deep copy）是其他语言的概念。</p>\n<p>浅拷贝导致内存得不到释放或者多次释放。</p>\n<p>rust 不使用浅拷贝这种概念，rust 使用移动（move）概念；<br />\n例如上面的 s1 和 s2；s2 = s1 会把 s1 的值移动到 s2；数据的所有权移动到了 s2，且 s1 失效。</p>\n<p>rust 也不会创建深拷贝，移动操作都是很廉价、快速的。</p>\n<h2 id=\"变量和数据交互的方式克隆clone\"><a class=\"anchor\" href=\"#变量和数据交互的方式克隆clone\">#</a> 变量和数据交互的方式：克隆（Clone）</h2>\n<p>如果真的需要深拷贝，可以使用 clone 方法，这里不使用深拷贝概念。</p>\n<p>浅拷贝对应 rust 的移动概念，rust 多了一步失效前一个变量的操作。</p>\n<p>深拷贝对应 rust 的克隆概念。</p>\n<p>以上移动和克隆都是对 heap 上的数据讨论的。stack 上的数据直接复制就 ok。</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> s1 <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> s2 <span class=\"token operator\">=</span> s1<span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125; &#123;&#125;\"</span><span class=\"token punctuation\">,</span> s1<span class=\"token punctuation\">,</span> s2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"stack-上的数据复制\"><a class=\"anchor\" href=\"#stack-上的数据复制\">#</a> stack 上的数据：复制</h2>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> y <span class=\"token operator\">=</span> x<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// 不报错，这里不发生移动</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">//stack 执行的是复制操作</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">//stack 数据都是确定的，所以可以自动计算</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125; &#123;&#125;\"</span><span class=\"token punctuation\">,</span> x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><ol>\n<li>Copy trait: 可以像整数一样，完全放在 stack 上面的类型。</li>\n<li>如果一个类型实现了 Copy 这个接口 (trait，特性)，那么旧的变量在赋值后仍然可以使用。因为发生的是复制 (Copy)，而不是移动。</li>\n<li>因此，如果一个类型或者该类型的一部分实现了 Drop trait，那么 rust 不允许再实现 Copy trait。因为复制和移动这 2 个概念是冲突的，因此不能同时实现。</li>\n</ol>\n<h3 id=\"一些拥有-copy-trait-的类型\"><a class=\"anchor\" href=\"#一些拥有-copy-trait-的类型\">#</a> 一些拥有 Copy trait 的类型</h3>\n<ol>\n<li>任何简单的标量的组合类型都可以 Copy 的</li>\n<li>任何需要分配内存或者某种资源的都不是 Copy 的</li>\n<li>一些拥有 Copy trait 的类型：\n<ul>\n<li>所有整数类型，例如 u32</li>\n<li>bool</li>\n<li>char</li>\n<li>所有的浮点类型，例如：f64</li>\n<li>Tuple（元组），如果其所有的字段都是 Copy 的：(i32, i32) 是，而 (i32, String) 不是</li>\n</ul>\n</li>\n</ol>\n<h1 id=\"所有权与函数\"><a class=\"anchor\" href=\"#所有权与函数\">#</a> 所有权与函数</h1>\n<p>将值传递给函数和把值赋值给变量是类似的：</p>\n<ul>\n<li>将值传递给函数会发生移动或复制</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">//s 的值在堆中，值的所有权移动到函数内部了</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 函数结束后，因为持有所有权，因此就会释放</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 函数后面就不能再使用 s1 变量了。</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token function\">take_ownership</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 因为 x 是标量，值在 stack 中；</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token comment\">//i32 实现了 Copy trait</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token comment\">// 传入函数内部发生复制，因此函数后面 x 还能使用</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token function\">makes_copy</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">take_ownership</span><span class=\"token punctuation\">(</span>some_string<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token comment\">//some_string 获得所有权</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> some_string<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 函数结束，释放 some_string 堆上的内存</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">makes_copy</span><span class=\"token punctuation\">(</span>some_number<span class=\"token punctuation\">:</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token comment\">//some_number 通过复制获得新的拷贝值</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> some_number<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 函数结束，some_number 在 stack 内存上自动释放</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>  <span class=\"token comment\">// 因为是复制的，不会影响外部的变量</span></pre></td></tr></table></figure><h1 id=\"返回值与作用域\"><a class=\"anchor\" href=\"#返回值与作用域\">#</a> 返回值与作用域</h1>\n<p>函数的返回值的过程中同样也会发生所有权的转移</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 从函数返回值中获得所有权</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> s1 <span class=\"token operator\">=</span> <span class=\"token function\">gives_ownership</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">let</span> s2 <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token comment\">// 传入 s2 变量，所有权移动到函数内部</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token comment\">// 函数直接返回，再次将所有权移动到函数外面的 s3</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">let</span> s3 <span class=\"token operator\">=</span> <span class=\"token function\">takes_and_gives_back</span><span class=\"token punctuation\">(</span>s2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 后面不能使用 s2 变量，因为所有权移动到 s3 上了</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token comment\">//s2 -> a_string（函数入参） -> s3</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">gives_ownership</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">String</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">let</span> some_string <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    some_string</pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 返回值移动所有权到函数调用者</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">takes_and_gives_back</span><span class=\"token punctuation\">(</span>a_string<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">String</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    a_string</pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 传入参数获得所有权，直接返回，返回值移动所有权到函数调用者</span></pre></td></tr></table></figure><h1 id=\"如何让函数使用某个值但不获取其所有权引用\"><a class=\"anchor\" href=\"#如何让函数使用某个值但不获取其所有权引用\">#</a> 如何让函数使用某个值，但不获取其所有权？引用</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> s1 <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// 为了获取字符串的长度，需要传入变量</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 但这样传入发生所有权的移动，而且发生 2 次移动</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 有点啰嗦和影响性能</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token punctuation\">(</span>s2<span class=\"token punctuation\">,</span> len<span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token function\">calculate_length</span><span class=\"token punctuation\">(</span>s1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"The length of '&#123;&#125;' is &#123;&#125;.\"</span><span class=\"token punctuation\">,</span> s2<span class=\"token punctuation\">,</span> len<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">calculate_length</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">usize</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">let</span> length <span class=\"token operator\">=</span> s<span class=\"token punctuation\">.</span><span class=\"token function\">len</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">,</span> length<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>函数传入参数，又返回此参数；</p>\n<p>所有权移动了 2 次，但我们可能只想使用，但不需要获取其所有权，因此引入了引用（Reference）和借用（Borrow）的概念。</p>\n<p>需要区分所有权、引用 / 借用的概念，这 2 个概念容易混淆，但不是同一个东西。</p>\n<p>引用 / 借用不会改变所有权，函数结束后，也不会释放变量（没所有权）。</p>\n<h1 id=\"引用与借用\"><a class=\"anchor\" href=\"#引用与借用\">#</a> 引用与借用</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// &amp;s 这里是引用</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">let</span> length <span class=\"token operator\">=</span> <span class=\"token function\">calculate_length</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"The length of '&#123;&#125;' is &#123;&#125;.\"</span><span class=\"token punctuation\">,</span> s<span class=\"token punctuation\">,</span> length<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\">// 这里 s 是借用；只有借用关系，不会发生所有权的移动</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">calculate_length</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token keyword\">usize</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    s<span class=\"token punctuation\">.</span><span class=\"token function\">len</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>引用和借用是同一个东西，只不过发生的位置不同，传入参数就是引用的概念；函数参数定义就是借用的概念。</p>\n<h2 id=\"借用\"><a class=\"anchor\" href=\"#借用\">#</a> 借用</h2>\n<p>和变量一样，引用默认也是不可变的。</p>\n<p>如果借用一个值，需要修改，则需要定义为可变引用，变量也要定义为可变。</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 变量需要定义为可变</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 引用需要 &amp;mut 可变引用</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">let</span> length <span class=\"token operator\">=</span> <span class=\"token function\">calculate_length</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"The length of '&#123;&#125;' is &#123;&#125;.\"</span><span class=\"token punctuation\">,</span> s<span class=\"token punctuation\">,</span> length<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\">// 函数参数需要定义为可变借用</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">calculate_length</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token keyword\">usize</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    s<span class=\"token punctuation\">.</span><span class=\"token function\">push_str</span><span class=\"token punctuation\">(</span><span class=\"token string\">\" World\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    s<span class=\"token punctuation\">.</span><span class=\"token function\">len</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"可变引用\"><a class=\"anchor\" href=\"#可变引用\">#</a> 可变引用</h1>\n<ol>\n<li>可变引用有一个重要的限制：在特定作用域内，对某一块数据，只能有一个可变的引用。</li>\n<li>这样做的好处是可在编译时防止数据竞争。</li>\n</ol>\n<p>以下三种行为下（同时存在）会发生数据竞争：</p>\n<ul>\n<li>两个或多个指针同时访问同一个数据</li>\n<li>至少有一个指针用于写入数据</li>\n<li>没有使用任何机制来同步对数据的访问</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> s1 <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> s<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">let</span> s2 <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> s<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">//s1 和 s2 会发生数据竞争，因此编译不通过</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125; &#123;&#125;\"</span><span class=\"token punctuation\">,</span> s1<span class=\"token punctuation\">,</span> s2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>可以通过创建新的作用域，来允许非同时的创建多个可变引用</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">let</span> s1 <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> s<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">let</span> s2 <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> s<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"另外一个限制\"><a class=\"anchor\" href=\"#另外一个限制\">#</a> 另外一个限制</h2>\n<ol>\n<li>不可以同时拥有一个可变引用和一个不可变引用</li>\n<li>多个不变引用是可以的</li>\n</ol>\n<p>可变引用会修改数据，如果没有同步操作，不可变引用的值可能被改变导致数据不一致；因此 rust 限制这种情况。</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> r1 <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">let</span> r2 <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 不能同时有可变和不可变的引用</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">let</span> s1 <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> s<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125; &#123;&#125; &#123;&#125;\"</span><span class=\"token punctuation\">,</span> r1<span class=\"token punctuation\">,</span> r2<span class=\"token punctuation\">,</span> s1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"悬空引用-dangling-references\"><a class=\"anchor\" href=\"#悬空引用-dangling-references\">#</a> 悬空引用 Dangling References</h2>\n<ol>\n<li>\n<p>悬空指针（Dangling Pointer）: 一个指针引用了内存中的某一个地址，而这块内存可能已经释放并分配给其它人使用了。</p>\n</li>\n<li>\n<p>Rust 中，编译器可以保证引用永远都不是悬空引用。</p>\n</li>\n<li>\n<p>在 rust 中，只有这种情况可能发生悬空引用：</p>\n<ul>\n<li>函数内部创建一个对象，然后仅仅返回其引用；然而函数结束后；由于函数内持有所有权，结束会释放内存，但返回引用给调用者；这样就发生悬空引用。</li>\n<li>rust 不会允许这种情况发生，需要指定生命周期，扩大对象的作用域范围。</li>\n</ul>\n</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> r <span class=\"token operator\">=</span> <span class=\"token function\">dangle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">dangle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">String</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">let</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span>hello<span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token operator\">&amp;</span>s</pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"引用的规则\"><a class=\"anchor\" href=\"#引用的规则\">#</a> 引用的规则</h1>\n<ul>\n<li>在任何给定的时刻，只能满足下列条件之一：\n<ol>\n<li>只有一个可变的引用</li>\n<li>或者只能任意数量的不可变的引用</li>\n</ol>\n</li>\n<li>引用必须一直有效</li>\n</ul>\n<h1 id=\"切片\"><a class=\"anchor\" href=\"#切片\">#</a> 切片</h1>\n<p>rust 的另外一种不持有所有权的数据类型：切片 (slice)</p>\n<p>以下程序可能有什么问题？</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> word_index <span class=\"token operator\">=</span> <span class=\"token function\">first_word</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// 如果 s 的内存被清空了，但还有 index 在；</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 后面使用 index 从 s 中获取内容，</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 就导致 bug，例如下面这句；</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    s<span class=\"token punctuation\">.</span><span class=\"token function\">clear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> word_index<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">first_word</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token keyword\">usize</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">let</span> bytes <span class=\"token operator\">=</span> s<span class=\"token punctuation\">.</span><span class=\"token function\">as_bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>item<span class=\"token punctuation\">)</span> <span class=\"token keyword\">in</span> bytes<span class=\"token punctuation\">.</span><span class=\"token function\">iter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">enumerate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token keyword\">if</span> item <span class=\"token operator\">==</span> <span class=\"token char\">b' '</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            <span class=\"token keyword\">return</span> i<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    s<span class=\"token punctuation\">.</span><span class=\"token function\">len</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"字符串切片\"><a class=\"anchor\" href=\"#字符串切片\">#</a> 字符串切片</h2>\n<p>字符串切片是指向字符串中一部分的内容引用</p>\n<p>注意需要 &amp; 符号，因为是一个引用，类型是 &amp;str。</p>\n<p>形式：&amp; 变量 [开始索引.. 结束索引]，不包含结束索引</p>\n<p>注意：字符串切片范围索引要是有效的 utf-8 字符边界内，否则程序会报错退出。</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello world\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> hello <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">..</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 语法糖：&amp;s [..5];</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">let</span> world <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">[</span><span class=\"token number\">6</span><span class=\"token punctuation\">..</span><span class=\"token number\">11</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 语法糖：&amp;s [6..]; 或 &amp;s [6..s.len ()];</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">let</span> helloworld <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">[</span><span class=\"token punctuation\">..</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 语法糖</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"使用字符串切片重写例子\"><a class=\"anchor\" href=\"#使用字符串切片重写例子\">#</a> 使用字符串切片重写例子</h2>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> word_index <span class=\"token operator\">=</span> <span class=\"token function\">first_word</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// 这里由于所有权会报错，因此 rust 机制保证安全，</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 防止内存释放后，还使用相关内容</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    s<span class=\"token punctuation\">.</span><span class=\"token function\">clear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> word_index<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">first_word</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">let</span> bytes <span class=\"token operator\">=</span> s<span class=\"token punctuation\">.</span><span class=\"token function\">as_bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>item<span class=\"token punctuation\">)</span> <span class=\"token keyword\">in</span> bytes<span class=\"token punctuation\">.</span><span class=\"token function\">iter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">enumerate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">if</span> item <span class=\"token operator\">==</span> <span class=\"token char\">b' '</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token keyword\">return</span> <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">[</span><span class=\"token punctuation\">..</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">[</span><span class=\"token punctuation\">..</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"字符串字面值是切片\"><a class=\"anchor\" href=\"#字符串字面值是切片\">#</a> 字符串字面值是切片</h2>\n<ul>\n<li>字符串字面值直接被存储在二进制程序中。</li>\n<li>变量 s 的类型是 &amp;str，它是一个指向二进制程序特点位置的切片。</li>\n<li>字面值不可变。</li>\n</ul>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> s <span class=\"token operator\">=</span> <span class=\"token string\">\"Hello World\"</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 相当于 &amp;str 类型</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"将字符串切片作为参数传递\"><a class=\"anchor\" href=\"#将字符串切片作为参数传递\">#</a> 将字符串切片作为参数传递</h2>\n<p>建议函数入参不使用 &amp;String，更通用的做法是使用切片作为入参。</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> s <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> word_index <span class=\"token operator\">=</span> <span class=\"token function\">first_word</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">[</span><span class=\"token punctuation\">..</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> word_index<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token comment\">// 通用</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">let</span> word_index <span class=\"token operator\">=</span> <span class=\"token function\">first_word</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> word_index<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">first_word</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">let</span> bytes <span class=\"token operator\">=</span> s<span class=\"token punctuation\">.</span><span class=\"token function\">as_bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>item<span class=\"token punctuation\">)</span> <span class=\"token keyword\">in</span> bytes<span class=\"token punctuation\">.</span><span class=\"token function\">iter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">enumerate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token keyword\">if</span> item <span class=\"token operator\">==</span> <span class=\"token char\">b' '</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            <span class=\"token keyword\">return</span> <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">[</span><span class=\"token punctuation\">..</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    s</pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"其它类型的切片\"><a class=\"anchor\" href=\"#其它类型的切片\">#</a> 其它类型的切片</h2>\n<p>例如数组 i32 的切片，类型是 &amp;[i32]</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 类型 &amp;[i32]</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">let</span> slice <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">..</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125; &#123;&#125;\"</span><span class=\"token punctuation\">,</span> slice<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> slice<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure>",
            "tags": [
                "Rust基础",
                "rust"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/04/07/rust/2.%20%E9%80%9A%E7%94%A8%E7%9A%84%E7%BC%96%E7%A8%8B%E6%A6%82%E5%BF%B5/",
            "url": "https://blog.ceciljxsu.icu/2023/04/07/rust/2.%20%E9%80%9A%E7%94%A8%E7%9A%84%E7%BC%96%E7%A8%8B%E6%A6%82%E5%BF%B5/",
            "title": "2. 通用的编程概念",
            "date_published": "2023-04-07T10:20:20.000Z",
            "content_html": "<h1 id=\"变量\"><a class=\"anchor\" href=\"#变量\">#</a> 变量</h1>\n<h2 id=\"变量的可变性\"><a class=\"anchor\" href=\"#变量的可变性\">#</a> 变量的可变性</h2>\n<ol>\n<li>声明变量使用 let 关键字</li>\n<li>默认情况下，变量是不可变的（immutable）</li>\n<li>使用 let mut 声明变量，就可以声明可变的（mutable）变量</li>\n</ol>\n<h2 id=\"常量与不可变变量\"><a class=\"anchor\" href=\"#常量与不可变变量\">#</a> 常量与不可变变量</h2>\n<ol>\n<li>不可以使用 mut，常量永远不可变的</li>\n<li>声明常量使用 const，必须手工指定类型</li>\n<li>常量可以在任何作用域内声明，包括全局作用域</li>\n<li>常量只可以绑定到常量表达式，无法绑定到函数的调用结果或只能在运行时才能计算出来的值</li>\n<li>在程序运行期间，常量在其声明的作用域内一直有效</li>\n<li>命名规范，全大写字母，每个单词下划线分开</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 可在任意作用域定义</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// 10_000 插入 _，为了方便阅读</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token constant\">MAX_SIZE</span> <span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span> <span class=\"token operator\">=</span> <span class=\"token number\">10_000</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">const</span> <span class=\"token constant\">MAX_SIZE</span> <span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span> <span class=\"token operator\">=</span> <span class=\"token number\">10_000</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"shadowing-隐藏\"><a class=\"anchor\" href=\"#shadowing-隐藏\">#</a> shadowing （隐藏）</h2>\n<ol>\n<li>可以使用相同的名字定义新的变量，新的变量会隐藏之前声明的同名变量</li>\n<li>在后续的代码中，这个变量名就表示新的变量</li>\n<li>新的变量类型可以不同</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// &amp;str</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> spaces <span class=\"token operator\">=</span> <span class=\"token string\">\"    \"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// usize</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">let</span> spaces <span class=\"token operator\">=</span> spaces<span class=\"token punctuation\">.</span><span class=\"token function\">len</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"数据类型\"><a class=\"anchor\" href=\"#数据类型\">#</a> 数据类型</h1>\n<p>rust 能自动推断类型，如果推出多个类型，则需要手工指定类型</p>\n<h2 id=\"标量类型\"><a class=\"anchor\" href=\"#标量类型\">#</a> 标量类型</h2>\n<ol>\n<li>整数</li>\n<li>浮点</li>\n<li>布尔</li>\n<li>字符</li>\n</ol>\n<h3 id=\"整数类型\"><a class=\"anchor\" href=\"#整数类型\">#</a> 整数类型</h3>\n<ol>\n<li>无符号以 u 开头；有符号以 i 开头</li>\n<li>有符号范围：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>−</mo><msup><mn>2</mn><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msup></mrow><annotation encoding=\"application/x-tex\">-2^{n-1}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.897438em;vertical-align:-0.08333em;\"></span><span class=\"mord\">−</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">n</span><span class=\"mbin mtight\">−</span><span class=\"mord mtight\">1</span></span></span></span></span></span></span></span></span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mn>2</mn><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msup><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">2^{n-1} - 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.897438em;vertical-align:-0.08333em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">n</span><span class=\"mbin mtight\">−</span><span class=\"mord mtight\">1</span></span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span></li>\n<li>无符号范围：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">0</span></span></span></span> 到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mn>2</mn><mi>n</mi></msup><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">2^n - 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.747722em;vertical-align:-0.08333em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.664392em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span></li>\n<li>isize 和 usize 由系统架构所决定</li>\n</ol>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:center\">Length</th>\n<th style=\"text-align:center\">Signed</th>\n<th style=\"text-align:center\">Unsigned</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\">8-bit</td>\n<td style=\"text-align:center\">i8</td>\n<td style=\"text-align:center\">u8</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">16-bit</td>\n<td style=\"text-align:center\">i16</td>\n<td style=\"text-align:center\">u16</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">32-bit</td>\n<td style=\"text-align:center\">i32</td>\n<td style=\"text-align:center\">u32</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">64-bit</td>\n<td style=\"text-align:center\">i64</td>\n<td style=\"text-align:center\">u64</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">128-bit</td>\n<td style=\"text-align:center\">i128</td>\n<td style=\"text-align:center\">u128</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">arch</td>\n<td style=\"text-align:center\">isize</td>\n<td style=\"text-align:center\">usize</td>\n</tr>\n</tbody>\n</table>\n<h3 id=\"整数字面值\"><a class=\"anchor\" href=\"#整数字面值\">#</a> 整数字面值</h3>\n<ol>\n<li>除了 byte 类型外，所有的数值字面值都允许使用类型后缀<br />\n例如：57u8</li>\n<li>整数默认类型是：i32</li>\n<li>i32 整体速度很快，即使在 64 位系统</li>\n</ol>\n<table>\n<thead>\n<tr>\n<th>Number Literals</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Decimal</td>\n<td>98_222</td>\n</tr>\n<tr>\n<td>Hex</td>\n<td>0xff</td>\n</tr>\n<tr>\n<td>Octal</td>\n<td>0o77</td>\n</tr>\n<tr>\n<td>Binary</td>\n<td>0b1111_0000</td>\n</tr>\n<tr>\n<td>Byte (u8 only)</td>\n<td>b'A'</td>\n</tr>\n</tbody>\n</table>\n<h3 id=\"整数溢出\"><a class=\"anchor\" href=\"#整数溢出\">#</a> 整数溢出</h3>\n<ol>\n<li>调试模式下编译，rust 会检查，运行时就会 panic</li>\n<li>发布模式编译，rust 不会检查导致的 panic 整数溢出\n<ol>\n<li>如果溢出发生，rust 会执行 “环绕” 操作</li>\n</ol>\n</li>\n</ol>\n<h3 id=\"浮点类型\"><a class=\"anchor\" href=\"#浮点类型\">#</a> 浮点类型</h3>\n<ol>\n<li>f32，32 位 单精度</li>\n<li>f64，64 位 双精度</li>\n<li>使用 IEEE-754 标准表达</li>\n<li>默认 f64 类型</li>\n</ol>\n<h3 id=\"布尔类型\"><a class=\"anchor\" href=\"#布尔类型\">#</a> 布尔类型</h3>\n<ol>\n<li>一个字节大小</li>\n<li>符号是 bool</li>\n</ol>\n<h3 id=\"字符类型\"><a class=\"anchor\" href=\"#字符类型\">#</a> 字符类型</h3>\n<ol>\n<li>char 类型</li>\n<li>占用 4 个字节大小</li>\n<li>使用 Unicode 标量值：多国文字、emoji 表情</li>\n<li>范围：U+0000 到 U+D7FF；U+E000 到 U+10FFFF</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token char\">'z'</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> y<span class=\"token punctuation\">:</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">=</span> <span class=\"token char\">'Ƶ'</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">let</span> z <span class=\"token operator\">=</span> '😂'<span class=\"token punctuation\">;</span>    </pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"复合类型\"><a class=\"anchor\" href=\"#复合类型\">#</a> 复合类型</h2>\n<ol>\n<li>元组（tuple），多个类型的集合，长度固定</li>\n<li>数值，同种类型的集合，长度固定</li>\n</ol>\n<h3 id=\"tuple\"><a class=\"anchor\" href=\"#tuple\">#</a> tuple</h3>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> tup<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">i32</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">f64</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">u8</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token number\">500</span><span class=\"token punctuation\">,</span> <span class=\"token number\">6.4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token comment\">// 下标获取元素值</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;, &#123;&#125;, &#123;&#125;\"</span><span class=\"token punctuation\">,</span> tup<span class=\"token number\">.0</span><span class=\"token punctuation\">,</span> tup<span class=\"token number\">.1</span><span class=\"token punctuation\">,</span> tup<span class=\"token number\">.2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 模式匹配解构 (destructure) 获取元素值</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">,</span> z<span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> tup<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;, &#123;&#125;, &#123;&#125;\"</span><span class=\"token punctuation\">,</span> x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">,</span> z<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"数组\"><a class=\"anchor\" href=\"#数组\">#</a> 数组</h3>\n<p>数组没有 vector 灵活</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"数组的类型\"><a class=\"anchor\" href=\"#数组的类型\">#</a> 数组的类型</h3>\n<p>数组的类型以这种形式表示：[类型；长度]</p>\n<p>例如： let a: [i32; 5] = [1, 2, 3, 4, 5];</p>\n<p>如果数组每个元素值都相同，可以：let a = [3; 5];<br />\n 它就相当于：let a = [3, 3, 3, 3, 3]</p>\n<h3 id=\"访问数组元素\"><a class=\"anchor\" href=\"#访问数组元素\">#</a> 访问数组元素</h3>\n<p>rust 不允许访问数组外的地址内存</p>\n<h1 id=\"函数\"><a class=\"anchor\" href=\"#函数\">#</a> 函数</h1>\n<ol>\n<li>使用 fn 关键字</li>\n<li>使用 snake_case 命名方式</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token function\">another_function</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// argument</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">another_function</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">:</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// parameter</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"the value of x is: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"函数体中语句和表达式\"><a class=\"anchor\" href=\"#函数体中语句和表达式\">#</a> 函数体中语句和表达式</h2>\n<ol>\n<li>函数体由一系列语句组成，可选的由一个表达式结束</li>\n<li>rust 是一个基于表达式的语言</li>\n<li>语句是执行一些动作的指令</li>\n<li>表达式会计算产生一个值</li>\n<li>函数的定义也是语句</li>\n<li>语句不返回值，所以不可以使用 let 将一个语句赋值给一个变量</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> y <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token comment\">// 表达式，产生一个值；这里不能分号结束</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token comment\">// 分号结束就是一条语句，语句其实也返回一个空 tuple：()</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        x <span class=\"token operator\">+</span> <span class=\"token number\">3</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token comment\">// 空 tuple () 没有实现 Display</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 所以 x + 3 加分号，这里就不能打印；</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"The value of y is: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"函数的返回值和注释\"><a class=\"anchor\" href=\"#函数的返回值和注释\">#</a> 函数的返回值和注释</h2>\n<ol>\n<li>在 -&gt; 符号后面声明函数返回值类型，但是不可以为返回值命名</li>\n<li>在 rust 里面，返回值就是函数体里面最后一个表达式的值</li>\n<li>如果要提前返回，需要使用 return 关键字，并指定一个值</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// This is a function</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">plus_five</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">:</span> <span class=\"token keyword\">i32</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token keyword\">i32</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    x <span class=\"token operator\">+</span> <span class=\"token number\">5</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\">/* multiple line comments</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>lalalala */</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// plus_five</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token function\">plus_five</span><span class=\"token punctuation\">(</span><span class=\"token number\">6</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 5 + 6;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"The value of x is: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"控制流\"><a class=\"anchor\" href=\"#控制流\">#</a> 控制流</h1>\n<h2 id=\"if-表达式\"><a class=\"anchor\" href=\"#if-表达式\">#</a> if 表达式</h2>\n<ol>\n<li>与条件相关联的代码块叫做分支（arm）</li>\n<li>表达式必须是一个 bool 类型的，没有隐式转换</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> number <span class=\"token operator\">=</span> <span class=\"token number\">3</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">if</span> number <span class=\"token operator\">&lt;</span> <span class=\"token number\">5</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"condition was less than 5.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> number <span class=\"token operator\">></span> <span class=\"token number\">10</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"condition was greater than 10.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"condition was [5, 10].\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"如果多个-else-if-条件建议用-match-重构\"><a class=\"anchor\" href=\"#如果多个-else-if-条件建议用-match-重构\">#</a> 如果多个 else if 条件，建议用 match 重构</h2>\n<h2 id=\"在-let-语句中使用-if\"><a class=\"anchor\" href=\"#在-let-语句中使用-if\">#</a> 在 let 语句中使用 if</h2>\n<p>if 是一个表达式，因此可以放在 let 语句中等号右边。</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> condition <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">let</span> number <span class=\"token operator\">=</span> <span class=\"token keyword\">if</span> condition <span class=\"token punctuation\">&#123;</span> <span class=\"token number\">5</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token number\">6</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"The value of number is: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> number<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"循环\"><a class=\"anchor\" href=\"#循环\">#</a> 循环</h1>\n<p>rust 提供 3 种循环：loop，while 和 for</p>\n<h2 id=\"loop\"><a class=\"anchor\" href=\"#loop\">#</a> loop</h2>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> counter <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">let</span> result <span class=\"token operator\">=</span> <span class=\"token keyword\">loop</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        counter <span class=\"token operator\">+=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">if</span> counter <span class=\"token operator\">==</span> <span class=\"token number\">10</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            <span class=\"token keyword\">break</span> counter <span class=\"token operator\">*</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"The result is: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"while\"><a class=\"anchor\" href=\"#while\">#</a> while</h2>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> counter <span class=\"token operator\">=</span> <span class=\"token number\">3</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">while</span> counter <span class=\"token operator\">!=</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> counter<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        counter <span class=\"token operator\">=</span> counter <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"LIFTOFF\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"for\"><a class=\"anchor\" href=\"#for\">#</a> for</h2>\n<p>这是最简洁，最安全的数组遍历，因此这种写法最常用</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">,</span> <span class=\"token number\">20</span><span class=\"token punctuation\">,</span> <span class=\"token number\">30</span><span class=\"token punctuation\">,</span> <span class=\"token number\">40</span><span class=\"token punctuation\">,</span> <span class=\"token number\">50</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token comment\">//element 是 &amp;i32 类型，是引用类型</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">for</span> element <span class=\"token keyword\">in</span> a<span class=\"token punctuation\">.</span><span class=\"token function\">iter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"The value is: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> element<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"range\"><a class=\"anchor\" href=\"#range\">#</a> Range</h2>\n<p>Range 生成左闭右开的范围，rev () 可以倒过来。</p>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">for</span> number <span class=\"token keyword\">in</span> <span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">..</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">rev</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#125;\"</span><span class=\"token punctuation\">,</span> number<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"LIFTOFF\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure>",
            "tags": [
                "Rust基础",
                "rust"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/04/07/rust/1.%20%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%93%E9%AA%8C/",
            "url": "https://blog.ceciljxsu.icu/2023/04/07/rust/1.%20%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%93%E9%AA%8C/",
            "title": "1. 安装和体验",
            "date_published": "2023-04-07T07:20:20.000Z",
            "content_html": "<h1 id=\"安装-rust\"><a class=\"anchor\" href=\"#安装-rust\">#</a> 安装 rust</h1>\n<p>官网安装</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># mac 系统安装</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">curl</span> <span class=\"token parameter variable\">--proto</span> <span class=\"token string\">'=https'</span> <span class=\"token parameter variable\">--tlsv1.2</span> <span class=\"token parameter variable\">-sSf</span> https://sh.rustup.rs <span class=\"token operator\">|</span> <span class=\"token function\">sh</span></pre></td></tr></table></figure><h2 id=\"常用命令\"><a class=\"anchor\" href=\"#常用命令\">#</a> 常用命令</h2>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 更新</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>rustup update</pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 卸载</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>rustup self uninstall</pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 安装验证，rustc x.y.z (commit_hash yyyy-mm-dd)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>rustc <span class=\"token parameter variable\">--version</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 本地文档</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>rustup doc</pre></td></tr></table></figure><h2 id=\"开发工具\"><a class=\"anchor\" href=\"#开发工具\">#</a> 开发工具</h2>\n<p>vscode，插件：rust-analyzer、另外一个 rust 插件已经弃用了</p>\n<h1 id=\"hello-world\"><a class=\"anchor\" href=\"#hello-world\">#</a> hello world</h1>\n<ol>\n<li>文件后缀： .rs</li>\n<li>命名规范：hello_world.rs</li>\n</ol>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"编译和运行\"><a class=\"anchor\" href=\"#编译和运行\">#</a> 编译和运行</h2>\n<ol>\n<li>编译：rustc <span class=\"exturl\" data-url=\"aHR0cDovL3huLS01bnF4N2pwMHIucnM=\">文件名.rs</span></li>\n<li>生成 .exe 可执行文件和 .pdb 调试文件</li>\n<li>rust 是 ahead-of-time 编译语言：不需要安装 rust 就可以运行执行文件</li>\n<li>rustc 适合编译简单的程序</li>\n</ol>\n<h1 id=\"cargo\"><a class=\"anchor\" href=\"#cargo\">#</a> cargo</h1>\n<ol>\n<li>cargo 是 rust 构建系统和包管理工具</li>\n<li>查看是否安装：cargo --version</li>\n</ol>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 查看是否安装、版本号</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">cargo</span> <span class=\"token parameter variable\">--version</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 创建新项目</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">cargo</span> new 项目名称</pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\"># cargo new hello_world</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># --vcs 指定版本控制系统：默认 git; hg, pijul, or fossil, none</span></pre></td></tr></table></figure><h2 id=\"cargotoml-介绍\"><a class=\"anchor\" href=\"#cargotoml-介绍\">#</a> cargo.toml 介绍</h2>\n<p>[package]</p>\n<ul>\n<li>name: 项目名称</li>\n<li>version: 项目版本</li>\n<li>authors: 项目作者</li>\n<li>edition: rust 版本</li>\n</ul>\n<p>[dependencies]<br />\n rust 里面，代码的包称作 crate</p>\n<h2 id=\"cargo-构建和运行项目\"><a class=\"anchor\" href=\"#cargo-构建和运行项目\">#</a> cargo 构建和运行项目</h2>\n<ul>\n<li>cargo build: 编译</li>\n<li>cargo run: 编译和运行</li>\n</ul>\n<h2 id=\"cargo-check-检查代码\"><a class=\"anchor\" href=\"#cargo-check-检查代码\">#</a> cargo check 检查代码</h2>\n<ol>\n<li>检查代码，确保能通过编译，但是不产生可执行文件</li>\n<li>比 build 快的多，编写代码可以连续反复 cargo check 检查代码，提供效率</li>\n</ol>\n<h2 id=\"为发布构建\"><a class=\"anchor\" href=\"#为发布构建\">#</a> 为发布构建</h2>\n<p>cargo build --release</p>\n<ol>\n<li>编译时会进行优化：编译时间久，代码运行快</li>\n<li>会在 target/release 目录生成，而不是 target/debug</li>\n</ol>\n<h1 id=\"猜一个数一次猜测\"><a class=\"anchor\" href=\"#猜一个数一次猜测\">#</a> 猜一个数：一次猜测</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//prelude 没在预导入里面的，需要手工引入 use</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>io<span class=\"token punctuation\">;</span> <span class=\"token comment\">// prelude</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"猜数：\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"猜一个数（1-100）：\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// 1. 所有变量默认 immutable，如果要修改，则需要用 mut</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token comment\">// 2. 返回一个 String 对象实例，:: 关联函数</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> guess <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token comment\">// 1. stdin 关联函数返回一个 Stdin 的实例</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token comment\">// 2. 引入默认也是不可变的，因此也需要 mut</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token comment\">// 3. read_line 返回 io::Result 枚举类型：Ok, Err</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token namespace\">io<span class=\"token punctuation\">::</span></span><span class=\"token function\">stdin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">read_line</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> guess<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">expect</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"读取错误!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token comment\">// &#123;&#125; 占位符</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"你猜的数是: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> guess<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"猜一个数生成神秘数字\"><a class=\"anchor\" href=\"#猜一个数生成神秘数字\">#</a> 猜一个数：生成神秘数字</h1>\n<p>我们创建的项目是二进制 crate（可以独立运行）；我们要引用一个依赖，这个是依赖 crate（不能独立运行）。</p>\n<p>在 dependencies 下添加<br />\n rand = &quot;0.3.14&quot;</p>\n<h2 id=\"cargolock\"><a class=\"anchor\" href=\"#cargolock\">#</a> Cargo.lock</h2>\n<p>cargo.lock 锁定当前依赖版本，保证每次编译生成相同东西，保证一致性；<br />\n如果修改依赖版本，则可以 cargo update 更新这个文件</p>\n<p>cargo update</p>\n<h2 id=\"生成神秘数字\"><a class=\"anchor\" href=\"#生成神秘数字\">#</a> 生成神秘数字</h2>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 这是一个 trait，类似接口；rand::thread_rng () 需要</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">rand<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Rng</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// trait</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>io<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"猜数：\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">let</span> secret_number <span class=\"token operator\">=</span> <span class=\"token namespace\">rand<span class=\"token punctuation\">::</span></span><span class=\"token function\">thread_rng</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">gen_range</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">..</span><span class=\"token number\">101</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"神秘数字: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> secret_number<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"猜一个数（1-100）：\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> guess <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token namespace\">io<span class=\"token punctuation\">::</span></span><span class=\"token function\">stdin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">read_line</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> guess<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">expect</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"读取错误!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"你猜的数是: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> guess<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"猜一个数比较猜测数字和神秘数字\"><a class=\"anchor\" href=\"#猜一个数比较猜测数字和神秘数字\">#</a> 猜一个数：比较猜测数字和神秘数字</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 这是一个 trait，类似接口；rand::thread_rng () 需要</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">rand<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Rng</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// trait</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>cmp<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>io<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"猜数：\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">let</span> secret_number <span class=\"token operator\">=</span> <span class=\"token namespace\">rand<span class=\"token punctuation\">::</span></span><span class=\"token function\">thread_rng</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">gen_range</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">..</span><span class=\"token number\">101</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"神秘数字: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> secret_number<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"猜一个数（1-100）：\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> guess <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token namespace\">io<span class=\"token punctuation\">::</span></span><span class=\"token function\">stdin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">read_line</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> guess<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">expect</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"读取错误!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"你猜的数是: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> guess<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token comment\">// 1. parse 后，需要指定类型，这里指定 u32；expect 就是异常中断程序处理</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token comment\">// 2. 原本 secret_number 默认是 i32 类型；</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>    <span class=\"token comment\">//    因为后面 guess.cmp 与 secret_number 比较，</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token comment\">//    编译器自动推断 secret_number 类型也为 u32</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token keyword\">let</span> guess<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span> <span class=\"token operator\">=</span> guess<span class=\"token punctuation\">.</span><span class=\"token function\">trim</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">expect</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Please input a number!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token comment\">//match 匹配，每个分支称为 arm</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token keyword\">match</span> guess<span class=\"token punctuation\">.</span><span class=\"token function\">cmp</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>secret_number<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>        <span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Less</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Too small!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        <span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Greater</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Too Big!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>        <span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Equal</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"You win!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"猜一个数多次猜测\"><a class=\"anchor\" href=\"#猜一个数多次猜测\">#</a> 猜一个数：多次猜测</h1>\n<figure class=\"highlight rust\"><figcaption data-lang=\"rust\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">rand<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Rng</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>cmp<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>io<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"猜数：\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">let</span> secret_number <span class=\"token operator\">=</span> <span class=\"token namespace\">rand<span class=\"token punctuation\">::</span></span><span class=\"token function\">thread_rng</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">gen_range</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">..</span><span class=\"token number\">101</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"猜一个数（1-100）：\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token comment\">// 多次循环</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">loop</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> guess <span class=\"token operator\">=</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token namespace\">io<span class=\"token punctuation\">::</span></span><span class=\"token function\">stdin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">read_line</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">mut</span> guess<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">expect</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"读取错误!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"你猜的数是: &#123;&#125;\"</span><span class=\"token punctuation\">,</span> guess<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token comment\">//expect 导致程序中断，不优雅，因此用 match 处理不同枚举情况</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token keyword\">let</span> guess<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u32</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">match</span> guess<span class=\"token punctuation\">.</span><span class=\"token function\">trim</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            <span class=\"token comment\">// 直接返回结果</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>            <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> num<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>            <span class=\"token comment\">// 不关心结果，用 _ 表现</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>            <span class=\"token class-name\">Err</span><span class=\"token punctuation\">(</span>_<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>                <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"请输入一个数字.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>                <span class=\"token comment\">// 跳出此次循环，但不停止循环</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>                <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>        <span class=\"token keyword\">match</span> guess<span class=\"token punctuation\">.</span><span class=\"token function\">cmp</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>secret_number<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>            <span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Less</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Too small!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>            <span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Greater</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Too Big!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>            <span class=\"token class-name\">Ordering</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Equal</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>                <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"You win!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>                <span class=\"token comment\">// 跳出并且停止此循环</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure>",
            "tags": [
                "Rust基础",
                "rust"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2023/01/02/computer_science/IEEE%20754%20%E2%80%94%20%E6%B5%AE%E7%82%B9%E6%95%B0/",
            "url": "https://blog.ceciljxsu.icu/2023/01/02/computer_science/IEEE%20754%20%E2%80%94%20%E6%B5%AE%E7%82%B9%E6%95%B0/",
            "title": "IEEE 754 — 浮点数",
            "date_published": "2023-01-02T13:05:01.000Z",
            "content_html": "<h1 id=\"bit构成\"><a class=\"anchor\" href=\"#bit构成\">#</a> bit 构成</h1>\n<p>sign、exponent、fraction<br />\n 符号域、指数域、分数域</p>\n<ul>\n<li>32 位：1、8、23</li>\n<li>64 位：1、11、52</li>\n</ul>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>+------+----------+----------+</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>| sign | exponent | fraction |</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>+------+----------+----------+</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>|  1   |    8     |    23    |   &lt;-- 32 位</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>+------+----------+----------+</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>|  1   |    11    |    52    |   &lt;-- 64 位</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>+------+----------+----------+</pre></td></tr></table></figure><h1 id=\"表示\"><a class=\"anchor\" href=\"#表示\">#</a> 表示</h1>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>u</mi><mi>e</mi><mo>=</mo><mi>s</mi><mi>i</mi><mi>g</mi><mi>n</mi><mo>∗</mo><mi>e</mi><mi>x</mi><mi>p</mi><mi>o</mi><mi>n</mi><mi>e</mi><mi>n</mi><mi>t</mi><mo>∗</mo><mi>f</mi><mi>r</mi><mi>a</mi><mi>c</mi><mi>t</mi><mi>i</mi><mi>o</mi><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">value = sign * exponent * fraction</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">e</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.85396em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.80952em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10764em;\">f</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">c</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">n</span></span></span></span></p>\n<h2 id=\"sign\"><a class=\"anchor\" href=\"#sign\">#</a> sign</h2>\n<ul>\n<li>0: +</li>\n<li>1: -</li>\n</ul>\n<h2 id=\"exponent\"><a class=\"anchor\" href=\"#exponent\">#</a> exponent</h2>\n<p><a href=\"#%E8%A7%84%E7%BA%A6%E5%BD%A2%E5%BC%8F\">规约形式</a>、<a href=\"#%E9%9D%9E%E8%A7%84%E7%BA%A6%E5%BD%A2%E5%BC%8F\">非规约形式</a>、<a href=\"#%E7%89%B9%E6%AE%8A%E5%80%BC\">特殊值</a>，含义不一样。</p>\n<h2 id=\"fraction\"><a class=\"anchor\" href=\"#fraction\">#</a> fraction</h2>\n<p><a href=\"#%E8%A7%84%E7%BA%A6%E5%BD%A2%E5%BC%8F\">规约形式</a>、<a href=\"#%E9%9D%9E%E8%A7%84%E7%BA%A6%E5%BD%A2%E5%BC%8F\">非规约形式</a>、<a href=\"#%E7%89%B9%E6%AE%8A%E5%80%BC\">特殊值</a>，含义不一样。</p>\n<h1 id=\"规约形式\"><a class=\"anchor\" href=\"#规约形式\">#</a> 规约形式</h1>\n<p>规约形式：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1.</mn><mi>M</mi><mo>∗</mo><msup><mn>2</mn><mi>e</mi></msup></mrow><annotation encoding=\"application/x-tex\">1.M * 2^e</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord\">1</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.664392em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.664392em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">e</span></span></span></span></span></span></span></span></span></span></span></p>\n<h2 id=\"二进制的科学计数法\"><a class=\"anchor\" href=\"#二进制的科学计数法\">#</a> 二进制的科学计数法</h2>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1.</mn><mi>M</mi><mo>∗</mo><msup><mn>2</mn><mi>e</mi></msup></mrow><annotation encoding=\"application/x-tex\">1.M * 2^e</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord\">1</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.664392em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.664392em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">e</span></span></span></span></span></span></span></span></span></span></span></p>\n<ol>\n<li>1.M：把最高位 “1.” 部分隐藏，不在浮点数中表示，称为隐藏位。\n<ul>\n<li>因为 “1.” 这部分是固定值，没必要占用空间。</li>\n</ul>\n</li>\n<li>M：保存到 fraction 域中。\n<ul>\n<li>M 是科学计数法的尾数域（mantissa）。</li>\n<li>因为有隐藏位，为了与尾数域区分，M 叫做有效位（significant）。</li>\n</ul>\n</li>\n<li>e：保存到 exponent 中，需要转换为偏正值。\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>o</mi><mi>n</mi><mi>e</mi><mi>n</mi><mi>t</mi><mo>=</mo><mi>e</mi><mo>+</mo><mi>b</mi><mi>i</mi><mi>a</mi><mi>s</mi></mrow><annotation encoding=\"application/x-tex\">exponent = e + bias</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.80952em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">s</span></span></span></span></li>\n</ul>\n</li>\n</ol>\n<h2 id=\"exponent-2\"><a class=\"anchor\" href=\"#exponent-2\">#</a> exponent</h2>\n<h3 id=\"exponent-范围\"><a class=\"anchor\" href=\"#exponent-范围\">#</a> exponent 范围</h3>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>o</mi><mi>n</mi><mi>e</mi><mi>n</mi><mi>t</mi><mo>∈</mo><mo stretchy=\"false\">(</mo><mn>0</mn><mo separator=\"true\">,</mo><msup><mn>2</mn><mi>e</mi></msup><mo>−</mo><mn>2</mn><mo stretchy=\"false\">]</mo><mo>∩</mo><mi mathvariant=\"double-struck\">Z</mi></mrow><annotation encoding=\"application/x-tex\">exponent \\in (0, 2^e - 2] \\cap \\mathbb{Z}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.80952em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.664392em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">e</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">2</span><span class=\"mclose\">]</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∩</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68889em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord mathbb\">Z</span></span></span></span></span>；<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">0</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mn>2</mn><mi>e</mi></msup><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">2^e - 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.747722em;vertical-align:-0.08333em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.664392em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">e</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span> 用于特殊值。</p>\n<ul>\n<li>32 位（e=8）：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>o</mi><mi>n</mi><mi>e</mi><mi>n</mi><mi>t</mi><mo>∈</mo><mo stretchy=\"false\">[</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>254</mn><mo stretchy=\"false\">]</mo><mo>∩</mo><mi mathvariant=\"double-struck\">Z</mi></mrow><annotation encoding=\"application/x-tex\">exponent \\in [1, 254] \\cap \\mathbb{Z}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.80952em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">2</span><span class=\"mord\">5</span><span class=\"mord\">4</span><span class=\"mclose\">]</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∩</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68889em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord mathbb\">Z</span></span></span></span></span></li>\n<li>64 位（e=11）：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>o</mi><mi>n</mi><mi>e</mi><mi>n</mi><mi>t</mi><mo>∈</mo><mo stretchy=\"false\">[</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>2046</mn><mo stretchy=\"false\">]</mo><mo>∩</mo><mi mathvariant=\"double-struck\">Z</mi></mrow><annotation encoding=\"application/x-tex\">exponent \\in [1, 2046] \\cap \\mathbb{Z}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.80952em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">2</span><span class=\"mord\">0</span><span class=\"mord\">4</span><span class=\"mord\">6</span><span class=\"mclose\">]</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∩</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.68889em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord mathbb\">Z</span></span></span></span></span></li>\n</ul>\n<h3 id=\"偏正值\"><a class=\"anchor\" href=\"#偏正值\">#</a> 偏正值</h3>\n<p>exponent 使用 [偏正值] 表示</p>\n<p>exponent = 实际指数 + 指数偏移值</p>\n<ol>\n<li>偏正值：引入偏移值，使得 exponent 为正数</li>\n<li>作用：简化比较。指数也有符号，且 S 域也表示符号；如果指数用补码表示，则 (S + EXP) 就不能进行简单的比较</li>\n</ol>\n<h3 id=\"指数偏移值exponent-bias\"><a class=\"anchor\" href=\"#指数偏移值exponent-bias\">#</a> 指数偏移值 (exponent bias)</h3>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mn>2</mn><mrow><mi>e</mi><mo>−</mo><mn>1</mn></mrow></msup><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">2^{e-1} - 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.897438em;vertical-align:-0.08333em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">e</span><span class=\"mbin mtight\">−</span><span class=\"mord mtight\">1</span></span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span></p>\n<ul>\n<li>32 位（e=8）：+127</li>\n<li>64 位（e=11）：+1023</li>\n</ul>\n<h2 id=\"fraction-2\"><a class=\"anchor\" href=\"#fraction-2\">#</a> fraction</h2>\n<ol>\n<li>保存 1.M 的 M 部分，有效位部分</li>\n<li>范围：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1.</mn><mi>M</mi><mo>∈</mo><mo stretchy=\"false\">[</mo><mn>1</mn><mo separator=\"true\">,</mo><mn>2</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">1.M \\in [1, 2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.72243em;vertical-align:-0.0391em;\"></span><span class=\"mord\">1</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">2</span><span class=\"mclose\">)</span></span></span></span></li>\n</ol>\n<h1 id=\"非规约形式\"><a class=\"anchor\" href=\"#非规约形式\">#</a> 非规约形式</h1>\n<p>非规约形式：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0.</mn><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">0.M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.68333em;vertical-align:0em;\"></span><span class=\"mord\">0</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span></p>\n<ol>\n<li>使用 0.M 表示\n<ul>\n<li>表示非常接近 0：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0.</mn><mi>M</mi><mo>∈</mo><mo stretchy=\"false\">(</mo><mn>0</mn><mo separator=\"true\">,</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">0.M \\in (0, 1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.72243em;vertical-align:-0.0391em;\"></span><span class=\"mord\">0</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">∈</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></li>\n<li>exponent = 0</li>\n<li>fraction 保存 M，尾数域（mantissa）</li>\n</ul>\n</li>\n<li>exp = 0, mantissa ≠ 0</li>\n</ol>\n<h1 id=\"特殊值\"><a class=\"anchor\" href=\"#特殊值\">#</a> 特殊值</h1>\n<ol>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mo>=</mo><mn>0</mn><mo separator=\"true\">,</mo><mi>m</mi><mi>a</mi><mi>n</mi><mi>t</mi><mi>i</mi><mi>s</mi><mi>s</mi><mi>a</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">exp = 0, mantissa = 0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">p</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.85396em;vertical-align:-0.19444em;\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">0</span></span></span></span>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>±</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">\\pm0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.72777em;vertical-align:-0.08333em;\"></span><span class=\"mord\">±</span><span class=\"mord\">0</span></span></span></span> （和符号位有关）</li>\n</ul>\n</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mo>=</mo><msup><mn>2</mn><mi>e</mi></msup><mo>−</mo><mn>1</mn><mo separator=\"true\">,</mo><mi>m</mi><mi>a</mi><mi>n</mi><mi>t</mi><mi>i</mi><mi>s</mi><mi>s</mi><mi>a</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">exp = 2^e -1, mantissa = 0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">p</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.747722em;vertical-align:-0.08333em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.664392em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">e</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.85396em;vertical-align:-0.19444em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">0</span></span></span></span>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>±</mo><mi mathvariant=\"normal\">∞</mi></mrow><annotation encoding=\"application/x-tex\">\\pm\\infty</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">±</span><span class=\"mord\">∞</span></span></span></span> （和符号位有关）\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mfrac><mn>1.0</mn><mn>0.0</mn></mfrac><mo>→</mo><mo>+</mo><mi mathvariant=\"normal\">∞</mi></mrow><annotation encoding=\"application/x-tex\">\\frac{1.0}{0.0} \\rightarrow +\\infty</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.190108em;vertical-align:-0.345em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.845108em;\"><span style=\"top:-2.6550000000000002em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">0</span><span class=\"mord mtight\">.</span><span class=\"mord mtight\">0</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span><span class=\"mord mtight\">.</span><span class=\"mord mtight\">0</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">+</span><span class=\"mord\">∞</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>−</mo><mfrac><mn>1.0</mn><mn>0.0</mn></mfrac><mo>→</mo><mo>−</mo><mi mathvariant=\"normal\">∞</mi></mrow><annotation encoding=\"application/x-tex\">-\\frac{1.0}{0.0} \\rightarrow -\\infty</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.190108em;vertical-align:-0.345em;\"></span><span class=\"mord\">−</span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.845108em;\"><span style=\"top:-2.6550000000000002em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">0</span><span class=\"mord mtight\">.</span><span class=\"mord mtight\">0</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span><span class=\"mord mtight\">.</span><span class=\"mord mtight\">0</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">→</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.66666em;vertical-align:-0.08333em;\"></span><span class=\"mord\">−</span><span class=\"mord\">∞</span></span></span></span></li>\n</ul>\n</li>\n</ul>\n</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mo>=</mo><msup><mn>2</mn><mi>e</mi></msup><mo>−</mo><mn>1</mn><mo separator=\"true\">,</mo><mi>m</mi><mi>a</mi><mi>n</mi><mi>t</mi><mi>i</mi><mi>s</mi><mi>s</mi><mi>a</mi><mo mathvariant=\"normal\">≠</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">exp = 2^e -1, mantissa \\neq 0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">p</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.747722em;vertical-align:-0.08333em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.664392em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">e</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\"><span class=\"mrel\"><span class=\"mord vbox\"><span class=\"thinbox\"><span class=\"rlap\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"inner\"><span class=\"mrel\"></span></span><span class=\"fix\"></span></span></span></span></span><span class=\"mrel\">=</span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">0</span></span></span></span>\n<ul>\n<li>NaN （非数，与符号位无关）\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mfrac><mn>0.0</mn><mn>0.0</mn></mfrac></mrow><annotation encoding=\"application/x-tex\">\\frac{0.0}{0.0}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.190108em;vertical-align:-0.345em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.845108em;\"><span style=\"top:-2.6550000000000002em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">0</span><span class=\"mord mtight\">.</span><span class=\"mord mtight\">0</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">0</span><span class=\"mord mtight\">.</span><span class=\"mord mtight\">0</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∞</mi><mo>∗</mo><mn>0.0</mn><mo separator=\"true\">,</mo><mo>−</mo><mi mathvariant=\"normal\">∞</mi><mo>∗</mo><mn>0.0</mn></mrow><annotation encoding=\"application/x-tex\">\\infty * 0.0, -\\infty * 0.0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.46528em;vertical-align:0em;\"></span><span class=\"mord\">∞</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8388800000000001em;vertical-align:-0.19444em;\"></span><span class=\"mord\">0</span><span class=\"mord\">.</span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">−</span><span class=\"mord\">∞</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">0</span><span class=\"mord\">.</span><span class=\"mord\">0</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msqrt><mpadded depth=\"0px\"><mrow><mo>−</mo><mn>1</mn></mrow></mpadded></msqrt></mrow><annotation encoding=\"application/x-tex\">\\sqrt{\\smash[b]{-1}}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.04em;vertical-align:-0.13278em;\"></span><span class=\"mord sqrt\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.90722em;\"><span class=\"svg-align\" style=\"top:-3em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\" style=\"padding-left:0.833em;\"><span class=\"mord\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.64444em;\"><span style=\"top:-3em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span><span class=\"mord\"><span class=\"mord\">−</span><span class=\"mord\">1</span></span></span></span></span></span></span></span></span></span><span style=\"top:-2.86722em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"hide-tail\" style=\"min-width:0.853em;height:1.08em;\"><svg width='400em' height='1.08em' viewBox='0 0 400000 1080' preserveAspectRatio='xMinYMin slice'><path d='M95,702\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl0 -0\nc5.3,-9.3,12,-14,20,-14\nH400000v40H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM834 80h400000v40h-400000z'/></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.13278em;\"><span></span></span></span></span></span></span></span></span></li>\n<li>传递性：任何数字与 NaN 的算术运算，结果都是 NaN，除了 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi><mi>a</mi><msup><mi>N</mi><mn>0</mn></msup><mo>=</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">NaN^0 = 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8141079999999999em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mord mathnormal\">a</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">0</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span></li>\n<li>反自反性：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>v</mi><mo stretchy=\"false\">!</mo><mo>=</mo><mi>v</mi></mrow><annotation encoding=\"application/x-tex\">v != v</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span><span class=\"mclose\">!</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">v</span></span></span></span>（与自身比较不相等）</li>\n</ul>\n</li>\n</ul>\n</li>\n</ol>\n<h2 id=\"java-中的浮点数特殊值\"><a class=\"anchor\" href=\"#java-中的浮点数特殊值\">#</a> Java 中的浮点数特殊值</h2>\n<p>浮点数与整数不同，除 0 不会异常。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">float</span> infinity <span class=\"token operator\">=</span> <span class=\"token number\">1.0f</span> <span class=\"token operator\">/</span> <span class=\"token number\">0.0f</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">float</span> minusInfinity <span class=\"token operator\">=</span> <span class=\"token operator\">-</span><span class=\"token number\">1.0f</span> <span class=\"token operator\">/</span> <span class=\"token number\">0.0f</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">float</span> <span class=\"token class-name\">NaN</span> <span class=\"token operator\">=</span> <span class=\"token number\">0.0f</span> <span class=\"token operator\">/</span> <span class=\"token number\">0.0f</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>infinity<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>       <span class=\"token comment\">// Infinity</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>minusInfinity<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// - Infinity</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">NaN</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>            <span class=\"token comment\">// NaN</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>infinity <span class=\"token operator\">==</span> infinity<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>           <span class=\"token comment\">// true</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>minusInfinity <span class=\"token operator\">==</span> minusInfinity<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">NaN</span> <span class=\"token operator\">==</span> <span class=\"token class-name\">NaN</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>                     <span class=\"token comment\">// false</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>infinity <span class=\"token operator\">></span> minusInfinity<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// true</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>infinity <span class=\"token operator\">&lt;</span> minusInfinity<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// false</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">NaN</span> <span class=\"token operator\">></span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// false</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">NaN</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// false</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure>",
            "tags": [
                "cs",
                "cs",
                "ieee"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2022/10/08/algorithm/tree/B+%E6%A0%91/",
            "url": "https://blog.ceciljxsu.icu/2022/10/08/algorithm/tree/B+%E6%A0%91/",
            "title": "B<sup>+</sup>树",
            "date_published": "2022-10-08T11:13:20.000Z",
            "content_html": "<h1 id=\"简介\"><a class=\"anchor\" href=\"#简介\">#</a> 简介</h1>\n<h2 id=\"适合范围\"><a class=\"anchor\" href=\"#适合范围\">#</a> 适合范围</h2>\n<p>大量数据存储在外部存储器（磁盘等），例如：文件系统，MySQL 索引等。<br />\n因为外部存储器 I／O 速度比较慢，如果使用二叉搜索树算法，其树的深度又比较高，则增加了读取数据的次数，从而增加了执行的时间。</p>\n<h2 id=\"局部性原理\"><a class=\"anchor\" href=\"#局部性原理\">#</a> 局部性原理</h2>\n<p>访问磁盘中的数据，其附近的数据也将会被访问。<br />\n因为程序中的数据一般是集中存放的，所以通过预先读取数据，一般为按页读取，这样就减少读取磁盘的次数，从而减少执行的时间。</p>\n<h2 id=\"b树的特点\"><a class=\"anchor\" href=\"#b树的特点\">#</a> B<sup>+</sup> 树的特点</h2>\n<ol>\n<li>非叶子节点只存放 router（相当于 key，与叶子节点 key 区分），叶子节点存放 key 和数据。</li>\n<li>叶子节点 x 的 nextNode 引用下一个叶子节点，把所有叶子节点通过链表连接起来。</li>\n<li>key 的个数与度（degree）的关系: <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>n</mi><mi>k</mi></msub><mo>=</mo><mi>d</mi><mi>e</mi><mi>g</mi><mi>r</mi><mi>e</mi><mi>e</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">n_k = degree - 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.58056em;vertical-align:-0.15em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.33610799999999996em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.03148em;\">k</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">e</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span></span></span></span>。</li>\n<li>从根节点到叶节点的每条路径的树高都一样。</li>\n<li>除了根节点，其余所有节点包含 key 的数量至少满一半。</li>\n</ol>\n<h1 id=\"b树结构\"><a class=\"anchor\" href=\"#b树结构\">#</a> B<sup>+</sup> 树结构</h1>\n<p>非叶子节点 x 的字段：</p>\n<ol>\n<li>x.n 当前存放 router 的个数；</li>\n<li>x.routers 按升序存放：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>t</mi><mi>e</mi><msub><mi>r</mi><mn>1</mn></msub><mo>&lt;</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>t</mi><mi>e</mi><msub><mi>r</mi><mn>2</mn></msub><mo>&lt;</mo><mtext>  </mtext><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mtext>  </mtext><mo>&lt;</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>t</mi><mi>e</mi><msub><mi>r</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">x.router_1 &lt; x.router_2 &lt; \\; ... \\; &lt; x.router_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.76508em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.76508em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.76508em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>；</li>\n<li>x.leaf = false，表明该节点是非叶子节点；</li>\n<li>x.children，n + 1 个孩子节点的指针：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi><mi mathvariant=\"normal\">.</mi><msub><mi>c</mi><mn>1</mn></msub><mo separator=\"true\">,</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><msub><mi>c</mi><mn>2</mn></msub><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><msub><mi>c</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">x.c_1, x.c_2, ... , x.c_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord\"><span class=\"mord mathnormal\">c</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord\"><span class=\"mord mathnormal\">c</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord\"><span class=\"mord mathnormal\">c</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>。</li>\n</ol>\n<p>叶子节点 x 的字段：</p>\n<ol>\n<li>x.n 当前存放 key 的个数；</li>\n<li>x.keys 按升序存放：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>k</mi><mi>e</mi><msub><mi>y</mi><mn>1</mn></msub><mo>&lt;</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>k</mi><mi>e</mi><msub><mi>y</mi><mn>2</mn></msub><mo>&lt;</mo><mtext>  </mtext><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mtext>  </mtext><mo>&lt;</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>k</mi><mi>e</mi><msub><mi>y</mi><mi>n</mi></msub></mrow><annotation encoding=\"application/x-tex\">x.key_1 &lt; x.key_2 &lt; \\; ... \\; &lt; x.key_n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>；</li>\n<li>x.leaf = true，表明该节点是叶子节点。</li>\n</ol>\n<p>非叶子节点的 routers 和孩子节点的 key 关系：</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>k</mi><mi>e</mi><msub><mi>y</mi><mn>1</mn></msub><mo>≤</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>t</mi><mi>e</mi><msub><mi>r</mi><mn>1</mn></msub><mo>&lt;</mo><mi>k</mi><mi>e</mi><msub><mi>y</mi><mn>2</mn></msub><mo>≤</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>t</mi><mi>e</mi><msub><mi>r</mi><mn>2</mn></msub><mo>&lt;</mo><mi>k</mi><mi>e</mi><msub><mi>y</mi><mn>3</mn></msub><mtext>  </mtext><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mtext>  </mtext><mo>&lt;</mo><mi>k</mi><mi>e</mi><msub><mi>y</mi><mi>n</mi></msub><mo>≤</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>t</mi><mi>e</mi><msub><mi>r</mi><mi>n</mi></msub><mo>&lt;</mo><mi>k</mi><mi>e</mi><msub><mi>y</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding=\"application/x-tex\">key_1 \\leq x.router_1 &lt; key_2 \\leq x.router_2 &lt; key_3 \\; ... \\; &lt; key_n \\leq x.router_n &lt; key_{n + 1}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.76508em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.76508em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.30110799999999993em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">3</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.76508em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.151392em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.902771em;vertical-align:-0.208331em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.301108em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">n</span><span class=\"mbin mtight\">+</span><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.208331em;\"><span></span></span></span></span></span></span></span></span></span></span></p>\n<h1 id=\"搜索\"><a class=\"anchor\" href=\"#搜索\">#</a> 搜索</h1>\n<p>从根节点开始搜索：</p>\n<ol>\n<li>如果 x 是非叶子节点，则 key 与第一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>t</mi><mi>e</mi><msub><mi>r</mi><mi>i</mi></msub></mrow><annotation encoding=\"application/x-tex\">x.router_i</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.76508em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.31166399999999994em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">i</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 比较，如果 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>k</mi><mi>e</mi><mi>y</mi><mo>≤</mo><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>t</mi><mi>e</mi><msub><mi>r</mi><mi>i</mi></msub></mrow><annotation encoding=\"application/x-tex\">key \\leq x.router_i</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.76508em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.31166399999999994em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">i</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span>，则从 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi><mi mathvariant=\"normal\">.</mi><msub><mi>c</mi><mi>i</mi></msub></mrow><annotation encoding=\"application/x-tex\">x.c_i</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.58056em;vertical-align:-0.15em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord\"><span class=\"mord mathnormal\">c</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.31166399999999994em;\"><span style=\"top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">i</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 孩子节点中搜索；</li>\n<li>如果所有的 router 都比 key 小，则从最后一个孩子节点中搜索；</li>\n<li>如果 x 是叶子节点，就从 x.keys 里面查询是否存在该元素。</li>\n</ol>\n<p>下面是 java 部分关键代码：</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">D</span> <span class=\"token function\">search</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token function\">search</span><span class=\"token punctuation\">(</span>root<span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token class-name\">D</span> <span class=\"token function\">search</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">D</span><span class=\"token punctuation\">></span></span> node<span class=\"token punctuation\">,</span> <span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token comment\">// find position</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">int</span> pos <span class=\"token operator\">=</span> <span class=\"token function\">getLocation</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token comment\">// search in leaf node</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>isLeaf<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">[</span>pos<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            <span class=\"token keyword\">return</span> node<span class=\"token punctuation\">.</span>dataList<span class=\"token punctuation\">[</span>pos<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token comment\">// not found</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token comment\">// search in non-leaf node</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token function\">search</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>pos<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">int</span> <span class=\"token function\">getLocation</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">D</span><span class=\"token punctuation\">></span></span> node<span class=\"token punctuation\">,</span> <span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token keyword\">int</span> pos <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>pos <span class=\"token operator\">&lt;</span> node<span class=\"token punctuation\">.</span>keyLength <span class=\"token operator\">&amp;&amp;</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">[</span>pos<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        pos<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>    <span class=\"token keyword\">return</span> pos<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"时间复杂度\"><a class=\"anchor\" href=\"#时间复杂度\">#</a> 时间复杂度</h2>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>t</mi><mo>⋅</mo><mi>l</mi><mi>o</mi><msub><mi>g</mi><mi>t</mi></msub><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(t \\cdot log_tn)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">⋅</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal\">o</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2805559999999999em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">t</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<h1 id=\"插入\"><a class=\"anchor\" href=\"#插入\">#</a> 插入</h1>\n<p>从根节点开始搜索，直到找到适合的叶子节点 y，先搜索 key 在叶子节点的位置，在叶子节点中插入：<br />\n如果叶子节点 y 还有剩余位置，则在对应位置直接插入 key 和对应的数据，操作完成。<br />\n否则，如果叶子节点 y 已经满了，则需要分裂该节点：</p>\n<ol>\n<li>分配新的节点 z；</li>\n<li>将节点 y 的前面一半保留在节点 y；</li>\n<li>将节点 y 的后面一半移到新节点 z；</li>\n<li>key 的插入，看 key 的大小，再决定插在 y 还是 z；</li>\n<li>y 节点的 nextNode 指针指向 z 节点；选取 y 节点的最后一个 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>y</mi><mi mathvariant=\"normal\">.</mi><mi>k</mi><mi>e</mi><msub><mi>y</mi><mrow><mi>l</mi><mi>a</mi><mi>s</mi><mi>t</mi></mrow></msub></mrow><annotation encoding=\"application/x-tex\">y.key_{last}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"mord\">.</span><span class=\"mord mathnormal\" style=\"margin-right:0.03148em;\">k</span><span class=\"mord mathnormal\">e</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">y</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.33610799999999996em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal mtight\">a</span><span class=\"mord mathnormal mtight\">s</span><span class=\"mord mathnormal mtight\">t</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span></span></span></span> 和新节点 z，插入父节点 x，x 节点是 y 和 z 的父节点；设置 z 节点的父节点；</li>\n<li>如果父节点也不够空间，则继续分裂，最坏的情况就是，叶子节点到根节点的路径上所有节点都需要分裂。</li>\n</ol>\n<p><img data-src=\"BplusTreeInsertLeafNodeSplitExample.svg\" alt=\"BplusTreeInsertLeafNodeSplitExample\" style=\"background-color: white\" /></p>\n<p>在非叶子节点的分裂，因为 router 的个数比孩子节点少 1 个，所以节点分裂时，就多出一个 router，因此，把这个多余的 router 和新节点插入到父节点上：</p>\n<p><img data-src=\"BplusTreeInsertNonLeafNodeSplitExample1.svg\" alt=\"BplusTreeInsertNonLeafNodeSplitExample1\" style=\"background-color: white\" /></p>\n<p>将多余的 router 直接移除，添加到父节点上；非叶子节点分离时，children 也会被分离，需要更新移到右边的 children 的 parent；children 比 router 移动多 1 个。</p>\n<p>⚠️ 非叶子节点分裂时，children 的 parent 发生变化，children 的 parent 需要更新。</p>\n<h2 id=\"时间复杂度-2\"><a class=\"anchor\" href=\"#时间复杂度-2\">#</a> 时间复杂度</h2>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>t</mi><mo>⋅</mo><mi>l</mi><mi>o</mi><msub><mi>g</mi><mi>t</mi></msub><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(t \\cdot log_tn)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">⋅</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal\">o</span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2805559999999999em;\"><span style=\"top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">t</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em;\"><span></span></span></span></span></span></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<h1 id=\"删除\"><a class=\"anchor\" href=\"#删除\">#</a> 删除</h1>\n<p>先搜索到叶节点，在叶节点中删除命中的元素。</p>\n<ol>\n<li>在叶子节点中删除 key，如果删除后，key 的数量没有少于一半，则删除步骤结束。</li>\n<li>如果删除 key 后，key 的数量少于一半，则需要将树重新平衡。</li>\n</ol>\n<h1 id=\"参考\"><a class=\"anchor\" href=\"#参考\">#</a> 参考</h1>\n<ol>\n<li><a href=\"https://www.cs.helsinki.fi/u/mluukkai/tirak2010/B-tree.pdf\">B<sup>+</sup> - trees, Kerttu Pollari-Malmi</a></li>\n</ol>\n",
            "tags": [
                "algorithm",
                "tree",
                "algorithm",
                "tree",
                "b+"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2022/10/05/algorithm/tree/2-3-4%E6%A0%91/",
            "url": "https://blog.ceciljxsu.icu/2022/10/05/algorithm/tree/2-3-4%E6%A0%91/",
            "title": "2-3-4树",
            "date_published": "2022-10-05T09:13:20.000Z",
            "content_html": "<h1 id=\"定义\"><a class=\"anchor\" href=\"#定义\">#</a> 定义</h1>\n<ol>\n<li>2-3-4 树是多路搜索树；4 阶的 B 树；所有结点有序</li>\n<li>是一棵自平衡树；每个叶子结点的深度一样、完美平衡。</li>\n<li>叶子结点除外，内部结点只能是：2 结点、3 结点、4 结点</li>\n</ol>\n<h2 id=\"结点类型\"><a class=\"anchor\" href=\"#结点类型\">#</a> 结点类型</h2>\n<p>2 结点：1 个元素，2 个子结点<br />\n<img data-src=\"2%E7%BB%93%E7%82%B9.png\" alt=\"2结点\" title=\"2结点：1个元素，2个子结点\" width=\"40%\" /></p>\n<p>3 结点：2 个元素，3 个子结点<br />\n<img data-src=\"3%E7%BB%93%E7%82%B9.png\" alt=\"3结点\" title=\"3结点：2个元素，3个子结点\" width=\"40%\" /></p>\n<p>4 结点：3 个元素，4 个子结点<br />\n<img data-src=\"4%E7%BB%93%E7%82%B9.png\" alt=\"4结点\" title=\"4结点：3个元素，4个子结点\" width=\"40%\" /></p>\n<h1 id=\"插入\"><a class=\"anchor\" href=\"#插入\">#</a> 插入</h1>\n<p>插入操作都是在叶子结点进行合并或分裂。</p>\n<h2 id=\"插入情形\"><a class=\"anchor\" href=\"#插入情形\">#</a> 插入情形</h2>\n<ol>\n<li>2 - 结点、3 - 结点：直接合并（nodeMerge）<br />\n<img data-src=\"2-%E7%BB%93%E7%82%B9,%203-%E7%BB%93%E7%82%B9%E6%8F%92%E5%85%A5.png\" alt=\"2-结点, 3-结点插入\" title=\"2、3结点插入：直接合并\" width=\"60%\" /><br />\n<img data-src=\"2-%E7%BB%93%E7%82%B9%E5%90%88%E5%B9%B6.png\" alt=\"2-结点合并\" title=\"2-结点合并\" width=\"60%\" /><br />\n<img data-src=\"3-%E7%BB%93%E7%82%B9%E5%90%88%E5%B9%B6.png\" alt=\"3-结点合并\" title=\"3-结点合并\" width=\"60%\" /></li>\n<li>4 - 结点：分裂（nodeSplit）<br />\na. 4 - 结点先分裂，插入结点再和左、右子结点合并<br />\n b. 分裂后的结点继续向上合并或再分裂<br />\n<img data-src=\"4-%E7%BB%93%E7%82%B9%E6%8F%92%E5%85%A5.png\" alt=\"4-结点插入\" title=\"4-结点插入\" width=\"60%\" /><br />\n<img data-src=\"%E5%88%86%E8%A3%82%E5%90%91%E4%B8%8A%E5%90%88%E5%B9%B6-%E5%86%8D%E5%88%86%E8%A3%82.png\" alt=\"分裂向上合并-再分裂\" title=\"分裂结点向上合并或再分裂\" width=\"60%\" /></li>\n</ol>\n<h2 id=\"代码实现\"><a class=\"anchor\" href=\"#代码实现\">#</a> 代码实现</h2>\n<h3 id=\"类结构\"><a class=\"anchor\" href=\"#类结构\">#</a> 类结构</h3>\n<p>TwoFourTree 对象结构：</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token annotation punctuation\">@SuppressWarnings</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span> <span class=\"token string\">\"unchecked\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"rawtypes\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"hiding\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">TwoFourTree</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Comparable</span><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span><span class=\"token punctuation\">></span></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token comment\">// 2-3-4 树是阶为 4 的 B 树</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">final</span> <span class=\"token keyword\">int</span> <span class=\"token constant\">ORDER</span> <span class=\"token operator\">=</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 结点最多元素个数</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">final</span> <span class=\"token keyword\">int</span> <span class=\"token constant\">MAX_SIZE</span> <span class=\"token operator\">=</span> <span class=\"token number\">3</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token class-name\">Node</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span><span class=\"token punctuation\">></span></span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">int</span> size <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token comment\">// 创建 key 数组的类型，泛型数组创建需要通过反射机制</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token class-name\">Class</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token operator\">?</span><span class=\"token punctuation\">></span></span> keyclass<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token comment\">// 创建 value 数组的类型，泛型数组创建需要通过反射机制</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token class-name\">Class</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token operator\">?</span><span class=\"token punctuation\">></span></span> valueclass<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token class-name\">TwoFourTree</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Class</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token operator\">?</span><span class=\"token punctuation\">></span></span> keyClass<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Class</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token operator\">?</span><span class=\"token punctuation\">></span></span> valueClass<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>keyclass <span class=\"token operator\">=</span> keyClass<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>valueclass <span class=\"token operator\">=</span> valueClass<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token comment\">// ......</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>Node 对象结构：</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Node</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Comparable</span><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span><span class=\"token punctuation\">></span></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 父结点</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token class-name\">Node</span> parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// 结点的子树</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token class-name\">Node</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> children <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">[</span><span class=\"token constant\">ORDER</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token comment\">// 结点的元素（key，value），以及元素个数</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token class-name\">K</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> keys <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token class-name\">Array</span><span class=\"token punctuation\">.</span><span class=\"token function\">newInstance</span><span class=\"token punctuation\">(</span>keyclass<span class=\"token punctuation\">,</span> <span class=\"token constant\">MAX_SIZE</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token class-name\">V</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> values <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">V</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token class-name\">Array</span><span class=\"token punctuation\">.</span><span class=\"token function\">newInstance</span><span class=\"token punctuation\">(</span>valueclass<span class=\"token punctuation\">,</span> <span class=\"token constant\">MAX_SIZE</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">int</span> size<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> parent<span class=\"token punctuation\">,</span> <span class=\"token class-name\">K</span> key<span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span> value<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>parent <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        size <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        keys<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> key<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        values<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token comment\">// for gc, unbind connected obj</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        parent <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        children <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        keys <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        values <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        size <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"结点合并\"><a class=\"anchor\" href=\"#结点合并\">#</a> 结点合并</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token class-name\">Node</span> <span class=\"token function\">nodeMerge</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span> insertNode<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> instIdx<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>instIdx <span class=\"token operator\">&lt;</span> node<span class=\"token punctuation\">.</span>size<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token comment\">// 数组元素往后移动 1 格，腾出插入空间</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> instIdx<span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> instIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> instIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token comment\">//instIdx 位置的子结点被替换；instIdx+1 位置需要插入新的子结点</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> instIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> instIdx <span class=\"token operator\">+</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> instIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// 插入元素</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>insertNode<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> instIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 插入 2 个新的子结点</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>insertNode<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> instIdx<span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token comment\">// 结点元素个数 + 1</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    node<span class=\"token punctuation\">.</span>size<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token comment\">// 删除插入结点</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    insertNode<span class=\"token punctuation\">.</span><span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">return</span> node<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"结点分裂\"><a class=\"anchor\" href=\"#结点分裂\">#</a> 结点分裂</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token class-name\">Node</span> <span class=\"token function\">nodeSplit</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span> insertNode<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> instIdx<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 分裂 4 - 结点：中间元素成为父结点，两边元素成为（左 / 右）子结点</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token class-name\">Node</span> split2Parent<span class=\"token punctuation\">,</span> split2Left<span class=\"token punctuation\">,</span> split2Right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// 分裂出父结点</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    split2Parent <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token comment\">// 分裂出右子结点</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    split2Right <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">(</span>split2Parent<span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> split2Right<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 分裂出左子结点</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    split2Left <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    split2Left<span class=\"token punctuation\">.</span>size <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    split2Left<span class=\"token punctuation\">.</span>parent <span class=\"token operator\">=</span> split2Parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token comment\">// 设置分裂父结点的 2 个子结点</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    split2Parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> split2Left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    split2Parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> split2Right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token comment\">// 插入结点再与左右子结点合并</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>instIdx <span class=\"token operator\">&lt;</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token comment\">// instIdx = 0, 1 [0-left or 1-right]</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token function\">nodeMerge</span><span class=\"token punctuation\">(</span>split2Left<span class=\"token punctuation\">,</span> insertNode<span class=\"token punctuation\">,</span> instIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        <span class=\"token comment\">// instIdx = 2, 3 [0-left or 1-right]</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>        <span class=\"token comment\">// instIdx - 2 = 0, 1</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>        <span class=\"token function\">nodeMerge</span><span class=\"token punctuation\">(</span>split2Right<span class=\"token punctuation\">,</span> insertNode<span class=\"token punctuation\">,</span> instIdx <span class=\"token operator\">-</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token keyword\">return</span> split2Parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"元素迁移孩子结点迁移\"><a class=\"anchor\" href=\"#元素迁移孩子结点迁移\">#</a> 元素迁移，孩子结点迁移</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> oldNode<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> oldIdx<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span> newNode<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> newIdx<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span><span class=\"token function\">arraycopy</span><span class=\"token punctuation\">(</span>oldNode<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">,</span> oldIdx<span class=\"token punctuation\">,</span> newNode<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">,</span> newIdx<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span><span class=\"token function\">arraycopy</span><span class=\"token punctuation\">(</span>oldNode<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">,</span> oldIdx<span class=\"token punctuation\">,</span> newNode<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">,</span> newIdx<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> oldNode<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> oldIdx<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span> newNode<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> newIdx<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> size<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span><span class=\"token function\">arraycopy</span><span class=\"token punctuation\">(</span>oldNode<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">,</span> oldIdx<span class=\"token punctuation\">,</span> newNode<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">,</span> newIdx<span class=\"token punctuation\">,</span> size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span><span class=\"token function\">arraycopy</span><span class=\"token punctuation\">(</span>oldNode<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">,</span> oldIdx<span class=\"token punctuation\">,</span> newNode<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">,</span> newIdx<span class=\"token punctuation\">,</span> size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> oldParent<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> oldChildIdx<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span> newParent<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> newChildIdx<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token comment\">// jvm: -ea</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">assert</span> oldChildIdx <span class=\"token operator\">&lt;</span> <span class=\"token constant\">ORDER</span> <span class=\"token operator\">&amp;&amp;</span> newChildIdx <span class=\"token operator\">&lt;</span> <span class=\"token constant\">ORDER</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token operator\">:</span> <span class=\"token string\">\"child's position out-of-bounds. \"</span> <span class=\"token operator\">+</span> oldChildIdx <span class=\"token operator\">+</span> <span class=\"token string\">\", \"</span> <span class=\"token operator\">+</span> newChildIdx<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span><span class=\"token function\">arraycopy</span><span class=\"token punctuation\">(</span>oldParent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">,</span> oldChildIdx<span class=\"token punctuation\">,</span> newParent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">,</span> newChildIdx<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token comment\">// update child's parent</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>newParent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>newChildIdx<span class=\"token punctuation\">]</span> <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        newParent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>newChildIdx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>parent <span class=\"token operator\">=</span> newParent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> oldParent<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> oldChildIdx<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span> newParent<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> newChildIdx<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> size<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token comment\">// jvm: -ea</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token keyword\">assert</span> oldChildIdx <span class=\"token operator\">&lt;</span> <span class=\"token constant\">ORDER</span> <span class=\"token operator\">&amp;&amp;</span> newChildIdx <span class=\"token operator\">&lt;</span> <span class=\"token constant\">ORDER</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>            <span class=\"token operator\">:</span> <span class=\"token string\">\"child's position out-of-bounds. \"</span> <span class=\"token operator\">+</span> oldChildIdx <span class=\"token operator\">+</span> <span class=\"token string\">\", \"</span> <span class=\"token operator\">+</span> newChildIdx<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span><span class=\"token function\">arraycopy</span><span class=\"token punctuation\">(</span>oldParent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">,</span> oldChildIdx<span class=\"token punctuation\">,</span> newParent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">,</span> newChildIdx<span class=\"token punctuation\">,</span> size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> size<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>        <span class=\"token comment\">// update child's parent</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>newParent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>newChildIdx <span class=\"token operator\">+</span> i<span class=\"token punctuation\">]</span> <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>            newParent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>newChildIdx <span class=\"token operator\">+</span> i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>parent <span class=\"token operator\">=</span> newParent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"插入-2\"><a class=\"anchor\" href=\"#插入-2\">#</a> 插入</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">V</span> <span class=\"token function\">put</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span> value<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"key can not be null.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 查找插入的结点，以及结点的插入位置</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">Node</span> node <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        node <span class=\"token operator\">=</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> p<span class=\"token punctuation\">.</span>size<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token keyword\">int</span> cmp <span class=\"token operator\">=</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>                p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">></span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> i <span class=\"token operator\">==</span> p<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>                i<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>                p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// updated</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>                <span class=\"token class-name\">V</span> oldValue <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">V</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>                p<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>                <span class=\"token keyword\">return</span> oldValue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token comment\">// 0. 根结点</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>        root <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Node</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>        size<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>    <span class=\"token class-name\">Node</span> insertNode <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>    <span class=\"token comment\">// 1. 4 - 结点分裂</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>size <span class=\"token operator\">==</span> <span class=\"token constant\">MAX_SIZE</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>        <span class=\"token comment\">// 结点分裂</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>        node <span class=\"token operator\">=</span> <span class=\"token function\">nodeSplit</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> insertNode<span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre></pre></td></tr><tr><td data-num=\"43\"></td><td><pre>        <span class=\"token comment\">// 1_1. 根结点分裂，更新 root</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>parent <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre>            root <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre>            size<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>            <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre></pre></td></tr><tr><td data-num=\"50\"></td><td><pre>        <span class=\"token comment\">// 分裂的结点递归向上合并或再分裂</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre>        insertNode <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>        node <span class=\"token operator\">=</span> insertNode<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre></pre></td></tr><tr><td data-num=\"54\"></td><td><pre>        <span class=\"token comment\">// 找出向上合并或再分裂的插入位置</span></pre></td></tr><tr><td data-num=\"55\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> node<span class=\"token punctuation\">.</span>size<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"56\"></td><td><pre>            <span class=\"token keyword\">int</span> cmp <span class=\"token operator\">=</span> insertNode<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"57\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"58\"></td><td><pre>                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"59\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">></span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> i <span class=\"token operator\">==</span> node<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"60\"></td><td><pre>                i<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"61\"></td><td><pre>                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"62\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"63\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"64\"></td><td><pre>        <span class=\"token comment\">// 结点分裂新的结点，需要更新新的结点</span></pre></td></tr><tr><td data-num=\"65\"></td><td><pre>        node<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> insertNode<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"66\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"67\"></td><td><pre></pre></td></tr><tr><td data-num=\"68\"></td><td><pre>    <span class=\"token comment\">// 2. 2 - 结点、3 - 结点直接合并</span></pre></td></tr><tr><td data-num=\"69\"></td><td><pre>    <span class=\"token function\">nodeMerge</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> insertNode<span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"70\"></td><td><pre>    size<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"71\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"72\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"删除\"><a class=\"anchor\" href=\"#删除\">#</a> 删除</h1>\n<ol>\n<li>都是在叶子结点中删除（非叶子结点转化为叶子结点情形）</li>\n<li>叶子结点元素多，则直接删除；不够则向兄弟借，兄弟不够向父辈借</li>\n<li>树的高度降低只发生在：根结点为 2 - 结点，且孩子结点均为 2 - 结点时，合并结点导致的</li>\n</ol>\n<h2 id=\"删除情形\"><a class=\"anchor\" href=\"#删除情形\">#</a> 删除情形</h2>\n<h3 id=\"内部结点非叶子结点\"><a class=\"anchor\" href=\"#内部结点非叶子结点\">#</a> 内部结点（非叶子结点）</h3>\n<p>找前驱或后继元素，转化为删除叶子结点。<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A2%E4%B8%80.png\" alt=\"删除情形一\" title=\"删除情形①\" /></p>\n<h3 id=\"叶子结点\"><a class=\"anchor\" href=\"#叶子结点\">#</a> 叶子结点</h3>\n<ol>\n<li>富有 / 只有一个根结点：直接删除元素<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A2%E4%BA%8C.png\" alt=\"删除情形二\" title=\"删除情形②: 直接删除\" /></li>\n<li>贫穷但兄弟结点富有：向兄弟借元素<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A2%E4%B8%89.png\" alt=\"删除情形三\" title=\"删除情形③: 向兄弟借\" /></li>\n<li>贫穷且兄弟结点也贫穷，但父结点富有：合并（fuse）<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A2%E5%9B%9B.png\" alt=\"删除情形四\" title=\"删除情形④: 合并\" /></li>\n<li>贫穷且兄弟结点、父结点都贫穷，均为 2 - 结点：<br />\na. 合并然后递归向上再合并（直到根结点结束）<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A2%E4%BA%941_1.png\" alt=\"删除情形五1_1\" title=\"删除情形⑤: 向上合并 1-1\" /><br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A2%E4%BA%941_2.png\" alt=\"删除情形五1_2\" title=\"删除情形⑤: 向上合并 1-2\" /><br />\nb. 合并然后向上向借元素<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A2%E4%BA%942_1.png\" alt=\"删除情形五2_1\" title=\"删除情形⑤: 向上借元素 2-1\" /><br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A2%E4%BA%942_2.png\" alt=\"删除情形五2_2\" title=\"删除情形⑤: 向上借元素 2-2\" /></li>\n</ol>\n<h2 id=\"代码实现-2\"><a class=\"anchor\" href=\"#代码实现-2\">#</a> 代码实现</h2>\n<h3 id=\"borrow\"><a class=\"anchor\" href=\"#borrow\">#</a> borrow</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">borrow</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> childIdx<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token class-name\">Node</span> parent <span class=\"token operator\">=</span> node<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>childIdx <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token class-name\">Node</span> rightSiblings <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>childIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>rightSiblings<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        node<span class=\"token punctuation\">.</span>size <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>rightSiblings<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>rightSiblings<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> rightSiblings<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> rightSiblings<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>rightSiblings<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> rightSiblings<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> rightSiblings<span class=\"token punctuation\">.</span>size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        rightSiblings<span class=\"token punctuation\">.</span>size<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token class-name\">Node</span> leftSiblings <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>childIdx <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> childIdx <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>leftSiblings<span class=\"token punctuation\">,</span> leftSiblings<span class=\"token punctuation\">.</span>size<span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        node<span class=\"token punctuation\">.</span>size <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>leftSiblings<span class=\"token punctuation\">,</span> leftSiblings<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">,</span> childIdx <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        leftSiblings<span class=\"token punctuation\">.</span>size<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"fuse\"><a class=\"anchor\" href=\"#fuse\">#</a> fuse</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">fuse</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> childIdx<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token class-name\">Node</span> parent <span class=\"token operator\">=</span> node<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>childIdx <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token class-name\">Node</span> rightSiblings <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>childIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>rightSiblings<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>rightSiblings<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> rightSiblings<span class=\"token punctuation\">.</span>size <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        node<span class=\"token punctuation\">.</span>size <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>childIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">.</span>size <span class=\"token operator\">></span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        parent<span class=\"token punctuation\">.</span>size<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        rightSiblings<span class=\"token punctuation\">.</span><span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token class-name\">Node</span> leftSiblings <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>childIdx <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> childIdx <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> leftSiblings<span class=\"token punctuation\">,</span> leftSiblings<span class=\"token punctuation\">.</span>size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> leftSiblings<span class=\"token punctuation\">,</span> leftSiblings<span class=\"token punctuation\">.</span>size <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        leftSiblings<span class=\"token punctuation\">.</span>size <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>childIdx<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>childIdx <span class=\"token operator\">&lt;</span> parent<span class=\"token punctuation\">.</span>size<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>            <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> childIdx<span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">,</span> childIdx <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> childIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>            <span class=\"token function\">moveChild</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">,</span> childIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">,</span> childIdx<span class=\"token punctuation\">,</span> parent<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> childIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>        node<span class=\"token punctuation\">.</span><span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        parent<span class=\"token punctuation\">.</span>size<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"isleaf\"><a class=\"anchor\" href=\"#isleaf\">#</a> isLeaf</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">boolean</span> <span class=\"token function\">isLeaf</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">||</span> node<span class=\"token punctuation\">.</span>size <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">return</span> node<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"getindexinparent\"><a class=\"anchor\" href=\"#getindexinparent\">#</a> getIndexInParent</h3>\n<p>Node 对象的方法：获取结点 node 在父结点 children 数组的下标。例如：node.getIndexInParent ()。用于删除结点操作中，需要根据 node 的位置进行调整。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">int</span> <span class=\"token function\">getIndexInParent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> index <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> index <span class=\"token operator\">&lt;</span> parent<span class=\"token punctuation\">.</span>size <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> index<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>            <span class=\"token keyword\">return</span> index<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token comment\">// should not reach here.</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"underflow\"><a class=\"anchor\" href=\"#underflow\">#</a> underflow</h3>\n<p>结点元素不富有，需要借元素时，称为下溢出（underflow）。</p>\n<p>下溢出的处理包括：删除情形③、④、⑤，即：向兄弟借、与父结点合并、向上合并 / 向上借元素。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">underflow</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token class-name\">Node</span> parent <span class=\"token operator\">=</span> node<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">int</span> childIdx <span class=\"token operator\">=</span> node<span class=\"token punctuation\">.</span><span class=\"token function\">getIndexInParent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token comment\">// 兄弟有的借</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>childIdx <span class=\"token operator\">==</span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>childIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>size <span class=\"token operator\">></span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            <span class=\"token function\">borrow</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> childIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>childIdx <span class=\"token operator\">></span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> parent<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>childIdx <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>size <span class=\"token operator\">></span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            <span class=\"token function\">borrow</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> childIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token comment\">// 兄弟没得借但父亲有的借：合并</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">.</span>size <span class=\"token operator\">></span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            <span class=\"token function\">fuse</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> childIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token comment\">// 兄弟父亲都没得借：合并，然后向上递归</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token comment\">// parent.size == 1</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token function\">fuse</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">,</span> childIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token comment\">// cascade up the tree</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        node <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        <span class=\"token comment\">// 根结点降低树高</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <span class=\"token operator\">==</span> root<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>            root <span class=\"token operator\">=</span> node<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>            root<span class=\"token punctuation\">.</span>parent <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>            node<span class=\"token punctuation\">.</span><span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>            <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"remove\"><a class=\"anchor\" href=\"#remove\">#</a> remove</h3>\n<p>getNode 方法参见：<a href=\"#%E6%9F%A5%E6%89%BE\">查找</a></p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">V</span> <span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// key invalid</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"key can not be null.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token class-name\">Pair</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Integer</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> pair <span class=\"token operator\">=</span> <span class=\"token function\">getNode</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>pair <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// key not found</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token class-name\">Node</span> delElemInNode <span class=\"token operator\">=</span> pair<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">int</span> delElemIdx <span class=\"token operator\">=</span> pair<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token class-name\">V</span> returnValue <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">V</span><span class=\"token punctuation\">)</span> delElemInNode<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">[</span>delElemIdx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token comment\">// 1. 非叶子结点情形</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">isLeaf</span><span class=\"token punctuation\">(</span>delElemInNode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token comment\">// 获取后驱结点：右兄弟结点的最左子树</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token class-name\">Node</span> successor <span class=\"token operator\">=</span> delElemInNode<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>delElemIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token comment\">// 沿着最左子树遍历</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">isLeaf</span><span class=\"token punctuation\">(</span>successor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// successor.children[0] != null</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            successor <span class=\"token operator\">=</span> successor<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        <span class=\"token comment\">// swap</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>successor<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> delElemInNode<span class=\"token punctuation\">,</span> delElemIdx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>        <span class=\"token comment\">// 转化为删除叶子结点情形</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        delElemInNode <span class=\"token operator\">=</span> successor<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        delElemIdx <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token comment\">//------------ 叶子结点情形 ------------</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>    <span class=\"token comment\">// 2. 结点富有 [2 - 结点、3 - 结点] 或仅有根结点一个结点：直接移除元素</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>delElemInNode<span class=\"token punctuation\">.</span>size <span class=\"token operator\">></span> <span class=\"token number\">1</span> <span class=\"token operator\">||</span> delElemInNode <span class=\"token operator\">==</span> root<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>        <span class=\"token comment\">// 删除元素</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>        <span class=\"token function\">moveElement</span><span class=\"token punctuation\">(</span>delElemInNode<span class=\"token punctuation\">,</span> delElemIdx <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> delElemInNode<span class=\"token punctuation\">,</span> delElemIdx<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>                delElemInNode<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> delElemIdx <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>        delElemInNode<span class=\"token punctuation\">.</span>size<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>        <span class=\"token comment\">// tree empty</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>delElemInNode<span class=\"token punctuation\">.</span>size <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>            root <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre>            delElemInNode<span class=\"token punctuation\">.</span><span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre>        size<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre>        <span class=\"token keyword\">return</span> returnValue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre></pre></td></tr><tr><td data-num=\"49\"></td><td><pre>    <span class=\"token comment\">// 3. 结点贫穷：借元素或合并结点</span></pre></td></tr><tr><td data-num=\"50\"></td><td><pre>    <span class=\"token function\">underflow</span><span class=\"token punctuation\">(</span>delElemInNode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>    size<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre>    <span class=\"token keyword\">return</span> returnValue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"查找\"><a class=\"anchor\" href=\"#查找\">#</a> 查找</h1>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 用于 return 返回 2 个值时的包装，</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// 例如：因为结点包含多个元素、子结点，需要获取元素值、以及下标位置</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Pair</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span><span class=\"token punctuation\">></span></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token class-name\">K</span> key<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token class-name\">V</span> value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token class-name\">Pair</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span> value<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>key <span class=\"token operator\">=</span> key<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>value <span class=\"token operator\">=</span> value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\">// 根据 key 获取值</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">V</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"key can not be null.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token comment\">// 元素下标，结点</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token class-name\">Pair</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Integer</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> pair <span class=\"token operator\">=</span> <span class=\"token function\">getNode</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">return</span> pair <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">?</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">V</span><span class=\"token punctuation\">)</span> pair<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">.</span>values<span class=\"token punctuation\">[</span>pair<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token comment\">// 返回结点，以及元素在结点内的下标</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token keyword\">private</span> <span class=\"token class-name\">Pair</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Integer</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> <span class=\"token function\">getNode</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token comment\">// 查找</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> p<span class=\"token punctuation\">.</span>size<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>            <span class=\"token keyword\">int</span> cmp <span class=\"token operator\">=</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>                p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">></span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> i <span class=\"token operator\">==</span> p<span class=\"token punctuation\">.</span>size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>                p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">[</span>i <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>                <span class=\"token comment\">// 返回结点，以及元素在结点内的下标</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>                <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Pair</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">,</span> p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre>    <span class=\"token comment\">// not found</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"空间复杂度\"><a class=\"anchor\" href=\"#空间复杂度\">#</a> 空间复杂度</h1>\n<p>平均、最差：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<h1 id=\"时间复杂度\"><a class=\"anchor\" href=\"#时间复杂度\">#</a> 时间复杂度</h1>\n<p>搜索、插入、删除，平均和最差都是：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(\\log n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<h1 id=\"缺点\"><a class=\"anchor\" href=\"#缺点\">#</a> 缺点</h1>\n<ol>\n<li>代码实现复杂，需要考虑：结点的数据结构、操作结点时需要考虑数组的下标位置、元素和结点在数组中移动等。</li>\n<li>需要使用多种数据结构：结点之间的关系 [链表 + 数组]、结点内的元素 [数组]。</li>\n</ol>\n",
            "tags": [
                "algorithm",
                "tree",
                "algorithm",
                "tree",
                "2-3-4",
                "b tree"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2022/10/02/algorithm/tree/%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91/",
            "url": "https://blog.ceciljxsu.icu/2022/10/02/algorithm/tree/%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91/",
            "title": "二叉搜索树（Binary Search Tree）",
            "date_published": "2022-10-02T12:19:20.000Z",
            "content_html": "<h1 id=\"定义\"><a class=\"anchor\" href=\"#定义\">#</a> 定义</h1>\n<ol>\n<li>是一棵二叉树；每个结点都有一个可比较的键，以及关联的值。</li>\n<li>任何结点中的键大于该结点左子树中所有结点中的键，且小于该结点右子树中所有结点的键（有序性）<br />\n<img data-src=\"%E6%9C%89%E5%BA%8F%E6%80%A7.svg\" alt=\"有序性\" title=\"中序遍历有序性\" width=\"60%\" /></li>\n</ol>\n<h1 id=\"遍历\"><a class=\"anchor\" href=\"#遍历\">#</a> 遍历</h1>\n<p>主要讨论的是深度遍历，根据根结点的访问优先级，又可以分为：前（先）、中、后序遍历。</p>\n<p>获取结点的前驱后继时，需要用到这部分知识点，而且平衡树的调整操作中也涉及到。</p>\n<h2 id=\"前序遍历\"><a class=\"anchor\" href=\"#前序遍历\">#</a> 前序遍历</h2>\n<p>前（先）序遍历（Pre-Order Traversal）：先根结点，再左右子树。</p>\n<p><img data-src=\"%E5%85%88%E5%BA%8F%E9%81%8D%E5%8E%86.jpg\" alt=\"前序遍历\" title=\"F, B, A, D, C, E, G, I, H.\" width=\"40%\" /></p>\n<h2 id=\"中序遍历\"><a class=\"anchor\" href=\"#中序遍历\">#</a> 中序遍历</h2>\n<p>中序遍历（In-Order Traversal）：先左子树，再根结点，最后右子树。</p>\n<p><img data-src=\"%E4%B8%AD%E5%BA%8F%E9%81%8D%E5%8E%86.jpg\" alt=\"中序遍历\" title=\"A, B, C, D, E, F, G, H, I.\" width=\"40%\" /></p>\n<h2 id=\"后序遍历\"><a class=\"anchor\" href=\"#后序遍历\">#</a> 后序遍历</h2>\n<p>后序遍历（Post-Order Traversal）：先左右子树，再根结点。</p>\n<p><img data-src=\"%E4%B8%AD%E5%BA%8F%E9%81%8D%E5%8E%86.jpg\" alt=\"后序遍历\" title=\"A, C, E, D, B, H, I, G, F.\" width=\"40%\" /></p>\n<h2 id=\"代码实现递归\"><a class=\"anchor\" href=\"#代码实现递归\">#</a> 代码实现：递归</h2>\n<h3 id=\"前序遍历-2\"><a class=\"anchor\" href=\"#前序遍历-2\">#</a> 前序遍历</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">preOrderTraversalRecursion</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span></span> result<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 先根结点</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    result<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> node<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token comment\">// 再左右子树</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token function\">preOrderTraversalRecursion</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">,</span> result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token function\">preOrderTraversalRecursion</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">,</span> result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"中序遍历-2\"><a class=\"anchor\" href=\"#中序遍历-2\">#</a> 中序遍历</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">inOrderTraversalRecursion</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span></span> result<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 先左子树</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token function\">inOrderTraversalRecursion</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">,</span> result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// 再根结点</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    result<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> node<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 后右子树</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token function\">inOrderTraversalRecursion</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">,</span> result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"后序遍历-2\"><a class=\"anchor\" href=\"#后序遍历-2\">#</a> 后序遍历</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">postOrderTraversalRecursion</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> node<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span></span> result<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 先左子树</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token function\">postOrderTraversalRecursion</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">,</span> result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// 再右子树</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token function\">postOrderTraversalRecursion</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">,</span> result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token comment\">// 后根结点</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    result<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> node<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"代码实现非递归\"><a class=\"anchor\" href=\"#代码实现非递归\">#</a> 代码实现：非递归</h2>\n<h3 id=\"前序遍历-3\"><a class=\"anchor\" href=\"#前序遍历-3\">#</a> 前序遍历</h3>\n<p>实现关键：</p>\n<ol>\n<li>使用栈结构，根结点入栈；循环条件：栈非空。</li>\n<li>出栈访问结点，右、左子树入栈</li>\n</ol>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">preOrderTraversalCirculation</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> root<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span></span> result<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>root <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token class-name\">Deque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> stack <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayDeque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token comment\">// 1. 根结点入栈</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>root<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token comment\">// 2. 循环条件：栈非空</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>stack<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token comment\">// 3. 出栈访问根结点</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> stack<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token comment\">// 先访问根结点</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        result<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token comment\">// 4. 再把右结点入栈：先进后出</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token comment\">// 5. 最后把左结点入栈：后进先出</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"中序遍历-3\"><a class=\"anchor\" href=\"#中序遍历-3\">#</a> 中序遍历</h3>\n<p>实现关键：</p>\n<ol>\n<li>使用栈结构，p 指向根结点</li>\n<li>循环条件栈或 p 非空；遍历 p 左子树，遍历期间 p 入栈；出栈访问结点，p 指向右子树</li>\n</ol>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">inOrderTraversalCirculation</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> root<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span></span> result<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>root <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token class-name\">Deque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> stack <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayDeque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// 1. p 用于循环遍历左子树</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token comment\">// 2. stack 用于回溯，记录 p 指针经过的结点</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>stack<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token comment\">// 访问最左边的左结点，栈记录经过的结点，用于回溯</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token comment\">// 出栈的结点，左子树都是已访问的</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        p <span class=\"token operator\">=</span> stack<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token comment\">// 访问中间结点</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        result<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token comment\">// 循环访问右结点</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"后序遍历-3\"><a class=\"anchor\" href=\"#后序遍历-3\">#</a> 后序遍历</h3>\n<h4 id=\"双栈实现\"><a class=\"anchor\" href=\"#双栈实现\">#</a> 双栈实现</h4>\n<p>实现关键：</p>\n<ol>\n<li>双栈结构，根结点入栈 1</li>\n<li>循环条件栈 1 非空，栈 1 出栈入栈 2，左、右子树入栈 1</li>\n<li>栈 2 依次出栈访问结点</li>\n</ol>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">postOrderTraversalCirculation1</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> root<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span></span> result<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>root <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token class-name\">Deque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> stack1 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayDeque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">Deque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> stack2 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayDeque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    stack1<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>root<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>stack1<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token class-name\">Node</span> node <span class=\"token operator\">=</span> stack1<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        stack2<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            stack1<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            stack1<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>stack2<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        result<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> stack2<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h4 id=\"单栈实现\"><a class=\"anchor\" href=\"#单栈实现\">#</a> 单栈实现</h4>\n<p>实现关键：</p>\n<ol>\n<li>栈结构，p 指向 root，p 入栈</li>\n<li>循环条件栈非空；查看栈顶结点</li>\n</ol>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">postOrderTraversalCirculation2</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Node</span> root<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">></span></span> result<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>root <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token class-name\">Deque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> stack <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayDeque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>stack<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token class-name\">Node</span> node <span class=\"token operator\">=</span> stack<span class=\"token punctuation\">.</span><span class=\"token function\">peek</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token comment\">// 因为先访问底层，再访问上一层，所以直接判断左右子树是否等于 p</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">boolean</span> finishedSubtrees <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right <span class=\"token operator\">==</span> p <span class=\"token operator\">||</span> node<span class=\"token punctuation\">.</span>left <span class=\"token operator\">==</span> p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token keyword\">boolean</span> isLeaf <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">&amp;&amp;</span> node<span class=\"token punctuation\">.</span>right <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token comment\">// 如果左右子树已经访问，或是叶子结点，直接访问</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>finishedSubtrees <span class=\"token operator\">||</span> isLeaf<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            stack<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            result<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> node<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            p <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 否则把右左子树入栈</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>                stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>                stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"前驱后继\"><a class=\"anchor\" href=\"#前驱后继\">#</a> 前驱后继</h1>\n<h2 id=\"定义-2\"><a class=\"anchor\" href=\"#定义-2\">#</a> 定义</h2>\n<h3 id=\"前驱\"><a class=\"anchor\" href=\"#前驱\">#</a> 前驱</h3>\n<p>比该结点的键小且最大的结点。</p>\n<ol>\n<li>该结点有左子树：沿着左结点的右子树；循环到结点没有右子树，则该结点是前驱结点（左结点最右子树）。<br />\n<img data-src=\"%E5%89%8D%E9%A9%B1-%E7%B1%BB1.png\" alt=\"前驱：情形一\" title=\"前驱：情形一\" width=\"40%\" /></li>\n<li>该结点没有左子树：沿着祖先结点往上查；循环到祖先结点的右结点等于上一轮循环的结点（查祖辈且出现拐角）。<br />\n<img data-src=\"%E5%89%8D%E9%A9%B1-%E7%B1%BB2.png\" alt=\"前驱：情形二\" title=\"前驱：情形二\" width=\"40%\" /></li>\n</ol>\n<h3 id=\"后继\"><a class=\"anchor\" href=\"#后继\">#</a> 后继</h3>\n<p>比该结点的键大且最小的结点。</p>\n<ol>\n<li>该结点有右子树：沿着右结点的左子树；循环到结点没有左子树，则该结点是前驱结点（右结点最左子树）。<br />\n<img data-src=\"%E5%90%8E%E7%BB%A7-%E7%B1%BB1.png\" alt=\"后继：情形一\" title=\"后继：情形一\" width=\"40%\" /></li>\n<li>该结点没有右子树：沿着父结点往上查；循环到祖先结点的左结点等于上一轮循环的结点（查祖辈且出现拐角）。<br />\n<img data-src=\"%E5%90%8E%E7%BB%A7-%E7%B1%BB2.png\" alt=\"后继：情形二\" title=\"后继：情形二\" width=\"40%\" /></li>\n</ol>\n<h2 id=\"代码实现\"><a class=\"anchor\" href=\"#代码实现\">#</a> 代码实现</h2>\n<h3 id=\"前驱-2\"><a class=\"anchor\" href=\"#前驱-2\">#</a> 前驱</h3>\n<p>Node 对象没有定义 parent 指针，无法向上遍历，因此需要借助栈记录祖先结点，然后通过栈回溯祖先结点。</p>\n<p>如果 Node 定义 parent 属性，则很容易向上遍历，不需要借助栈回溯。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">Node</span> <span class=\"token function\">predecessor</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"key can not be null.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 栈用于辅助回溯祖先结点；查找结点位置时，记录经过的祖先结点</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token comment\">// 如果 Node 对象有 parent 指针时，则不需要额外的栈来向上查询祖先结点</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token class-name\">Deque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> stack <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayDeque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token comment\">// 找到结点位置</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">int</span> cmp <span class=\"token operator\">=</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token comment\">// 记录父结点</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            <span class=\"token comment\">// 记录父结点</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token comment\">// 找到结点</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token comment\">// 0. 没找到结点</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token comment\">// 1. 有左子树：前驱结点在左结点的最右子树下</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>        p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>        <span class=\"token keyword\">return</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>    <span class=\"token comment\">// 2. 没有左子树：借助栈回溯祖先结点；因为 Node 没有 parent 指针，无法向上遍历父结点</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>stack<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>        <span class=\"token comment\">// 回溯祖先结点</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>        <span class=\"token class-name\">Node</span> q <span class=\"token operator\">=</span> stack<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>        <span class=\"token comment\">/* q ->  6</pre></td></tr><tr><td data-num=\"43\"></td><td><pre>         *        \\</pre></td></tr><tr><td data-num=\"44\"></td><td><pre>         *         9   &lt;- p</pre></td></tr><tr><td data-num=\"45\"></td><td><pre>         *        /</pre></td></tr><tr><td data-num=\"46\"></td><td><pre>         *       8    key</pre></td></tr><tr><td data-num=\"47\"></td><td><pre>         */</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>q<span class=\"token punctuation\">.</span>right <span class=\"token operator\">==</span> p<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre>            <span class=\"token keyword\">return</span> q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"50\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre>            p <span class=\"token operator\">=</span> q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre>    <span class=\"token comment\">// 3. 没有前驱结点</span></pre></td></tr><tr><td data-num=\"55\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"56\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"后继-2\"><a class=\"anchor\" href=\"#后继-2\">#</a> 后继</h3>\n<p>借助栈记录祖先结点，然后通过栈回溯祖先结点。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">Node</span> <span class=\"token function\">successor</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"key can not be null.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 栈用于辅助回溯祖先结点；查找结点位置时，记录经过的祖先结点</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 如果 Node 对象有 parent 指针时，则不需要额外的栈来向上查询祖先结点</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">Deque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Node</span><span class=\"token punctuation\">></span></span> stack <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayDeque</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// 找到结点位置</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">int</span> cmp <span class=\"token operator\">=</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            <span class=\"token comment\">// 记录父结点</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            <span class=\"token comment\">// 记录父结点</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            stack<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>            <span class=\"token comment\">// 找到结点</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token comment\">// 0. 没找到结点</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token comment\">// 1. 有右子树：后继结点在右结点的最左子树下</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>        <span class=\"token keyword\">return</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>    <span class=\"token comment\">// 2. 没有右子树：借助栈回溯祖先结点；因为 Node 没有 parent 指针，无法向上遍历父结点</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>stack<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>        <span class=\"token comment\">// 回溯祖先结点</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>        <span class=\"token class-name\">Node</span> q <span class=\"token operator\">=</span> stack<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>        <span class=\"token comment\">/* q ->  8</pre></td></tr><tr><td data-num=\"42\"></td><td><pre>         *      /</pre></td></tr><tr><td data-num=\"43\"></td><td><pre>         *     5   &lt;- p</pre></td></tr><tr><td data-num=\"44\"></td><td><pre>         *      \\</pre></td></tr><tr><td data-num=\"45\"></td><td><pre>         *       6    key</pre></td></tr><tr><td data-num=\"46\"></td><td><pre>         */</span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>q<span class=\"token punctuation\">.</span>left <span class=\"token operator\">==</span> p<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre>            <span class=\"token keyword\">return</span> q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"50\"></td><td><pre>            p <span class=\"token operator\">=</span> q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre>    <span class=\"token comment\">// 3. 没有后继结点</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"55\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"插入\"><a class=\"anchor\" href=\"#插入\">#</a> 插入</h1>\n<h2 id=\"插入情形\"><a class=\"anchor\" href=\"#插入情形\">#</a> 插入情形</h2>\n<ol>\n<li>根结点为 null，未初始化：创建新结点，直接赋值给 root。</li>\n<li>在左 / 右结点为 null 的位置插入。</li>\n</ol>\n<p><img data-src=\"%E6%8F%92%E5%85%A5.svg\" alt=\"插入\" title=\"4类插入位置\" width=\"\" 40%=\"\" /></p>\n<h2 id=\"代码实现-2\"><a class=\"anchor\" href=\"#代码实现-2\">#</a> 代码实现</h2>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">V</span> <span class=\"token function\">put</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">,</span> <span class=\"token class-name\">V</span> value<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"key can not be null.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">//p 指针用于遍历，寻找插入位置</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token comment\">//parent 指针用于记录插入位置的父结点</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token class-name\">Node</span> parent <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">int</span> cmp <span class=\"token operator\">=</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            parent <span class=\"token operator\">=</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            parent <span class=\"token operator\">=</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 更新</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            <span class=\"token class-name\">V</span> oldValue <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">V</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            p<span class=\"token punctuation\">.</span>value <span class=\"token operator\">=</span> value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>            <span class=\"token comment\">// 返回旧值</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token keyword\">return</span> oldValue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token comment\">// 1. 根结点初始化（第一次插入）：parent 为空</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        root <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>    <span class=\"token comment\">// 2. 在左 / 右结点插入：</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> parent<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>        parent<span class=\"token punctuation\">.</span>left <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>        parent<span class=\"token punctuation\">.</span>right <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Node</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"删除\"><a class=\"anchor\" href=\"#删除\">#</a> 删除</h1>\n<h2 id=\"删除情形\"><a class=\"anchor\" href=\"#删除情形\">#</a> 删除情形</h2>\n<ol>\n<li>删除结点有左 + 右子树：转化为后 2 种情形。<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A21-1.png\" alt=\"删除情形1-1\" title=\"删除情形①：1\" witdh=\"60%\" /><br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A21-2.png\" alt=\"删除情形1-2\" title=\"删除情形①：2\" witdh=\"60%\" /></li>\n<li>删除叶子结点：直接删除。<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A22-1.png\" alt=\"删除情形2-1\" title=\"删除情形②：1\" witdh=\"60%\" /><br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A22-2.png\" alt=\"删除情形2-2\" title=\"删除情形②：2\" witdh=\"60%\" /></li>\n<li>删除只有一个子树的结点：删除结点的子树挂到父结点下。<br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A23-1.png\" alt=\"删除情形3-1\" title=\"删除情形③：1\" witdh=\"60%\" /><br />\n<img data-src=\"%E5%88%A0%E9%99%A4%E6%83%85%E5%BD%A23-2.png\" alt=\"删除情形3-2\" title=\"删除情形③：2\" witdh=\"60%\" /></li>\n</ol>\n<h2 id=\"代码实现-3\"><a class=\"anchor\" href=\"#代码实现-3\">#</a> 代码实现</h2>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">V</span> <span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"key can not be null.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">//parent 指针记录删除结点的父结点</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token class-name\">Node</span> parent <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token comment\">//p 指针查询删除结点位置</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">int</span> cmp <span class=\"token operator\">=</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            parent <span class=\"token operator\">=</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            parent <span class=\"token operator\">=</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token comment\">// 0. 没找到结点</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token comment\">// 删除结点后返回旧值</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token class-name\">V</span> oldValue <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">V</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>    <span class=\"token comment\">// 1. 有 2 个子树的结点：找到后继结点替换，然后删除后继结点</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token comment\">// 转化为：a. 删除叶子结点；b. 只有一个子树的结点</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">&amp;&amp;</span> p<span class=\"token punctuation\">.</span>right <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>        <span class=\"token class-name\">Node</span> q <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 在右子树下查找后继结点</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>        parent <span class=\"token operator\">=</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>q<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>            parent <span class=\"token operator\">=</span> q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>            q <span class=\"token operator\">=</span> q<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>        <span class=\"token comment\">// 用后继结点替换删除结点</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>        p<span class=\"token punctuation\">.</span>key <span class=\"token operator\">=</span> q<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre>        p<span class=\"token punctuation\">.</span>value <span class=\"token operator\">=</span> q<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre></pre></td></tr><tr><td data-num=\"45\"></td><td><pre>        <span class=\"token comment\">// 转化为删除后继结点；后继结点：1. 只有一个子树；2. 没有子树（叶子结点）</span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre>        p <span class=\"token operator\">=</span> q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre></pre></td></tr><tr><td data-num=\"49\"></td><td><pre>    <span class=\"token comment\">// 2. 叶子结点：直接删除</span></pre></td></tr><tr><td data-num=\"50\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">&amp;&amp;</span> p<span class=\"token punctuation\">.</span>right <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre>        <span class=\"token comment\">// 2_1. 删除根结点，且只有一个结点</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre>            root <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre>            <span class=\"token keyword\">return</span> oldValue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"55\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"56\"></td><td><pre>        <span class=\"token comment\">// 2_2. 叶子结点直接从父结点中移除，得判断是在左还是右结点</span></pre></td></tr><tr><td data-num=\"57\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">.</span>left <span class=\"token operator\">==</span> p<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">//p 是删除结点</span></pre></td></tr><tr><td data-num=\"58\"></td><td><pre>            parent<span class=\"token punctuation\">.</span>left <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"59\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">.</span>right <span class=\"token operator\">==</span> p<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"60\"></td><td><pre>            parent<span class=\"token punctuation\">.</span>right <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"61\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"62\"></td><td><pre>        <span class=\"token keyword\">return</span> oldValue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"63\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"64\"></td><td><pre></pre></td></tr><tr><td data-num=\"65\"></td><td><pre>    <span class=\"token comment\">// 3. 只有 1 个子树的结点：删除结点的子树挂到父结点下</span></pre></td></tr><tr><td data-num=\"66\"></td><td><pre>    <span class=\"token comment\">// 3_1. 删除的是根结点，但有一个子结点：子结点直接作为根结点</span></pre></td></tr><tr><td data-num=\"67\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"68\"></td><td><pre>        root <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">?</span> p<span class=\"token punctuation\">.</span>right <span class=\"token operator\">:</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"69\"></td><td><pre>        <span class=\"token comment\">// for gc</span></pre></td></tr><tr><td data-num=\"70\"></td><td><pre>        p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"71\"></td><td><pre>        <span class=\"token keyword\">return</span> oldValue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"72\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"73\"></td><td><pre>    <span class=\"token comment\">// 3_2. 删除的是非根结点：子树直接移到父结点的左 / 右孩子下</span></pre></td></tr><tr><td data-num=\"74\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">.</span>left <span class=\"token operator\">==</span> p<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">//p 是删除结点</span></pre></td></tr><tr><td data-num=\"75\"></td><td><pre>        parent<span class=\"token punctuation\">.</span>left <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">?</span> p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">:</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"76\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"77\"></td><td><pre>        parent<span class=\"token punctuation\">.</span>right <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">?</span> p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">:</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"78\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"79\"></td><td><pre>    <span class=\"token comment\">// for gc</span></pre></td></tr><tr><td data-num=\"80\"></td><td><pre>    p<span class=\"token punctuation\">.</span>left <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"81\"></td><td><pre>    <span class=\"token keyword\">return</span> oldValue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"82\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"查找\"><a class=\"anchor\" href=\"#查找\">#</a> 查找</h1>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">V</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>key <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"key can not be null.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token class-name\">Node</span> node <span class=\"token operator\">=</span> <span class=\"token function\">getNode</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">return</span> node <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">?</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">V</span><span class=\"token punctuation\">)</span> node<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token class-name\">Node</span> <span class=\"token function\">getNode</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span> key<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token class-name\">Node</span> p <span class=\"token operator\">=</span> root<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>p <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">int</span> cmp <span class=\"token operator\">=</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">compareTo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">K</span><span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">.</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>left<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cmp <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            p <span class=\"token operator\">=</span> p<span class=\"token punctuation\">.</span>right<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            <span class=\"token keyword\">return</span> p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"空间复杂度\"><a class=\"anchor\" href=\"#空间复杂度\">#</a> 空间复杂度</h1>\n<p>平均、最差：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<h1 id=\"时间复杂度\"><a class=\"anchor\" href=\"#时间复杂度\">#</a> 时间复杂度</h1>\n<ol>\n<li>搜索、插入、删除，平均：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(\\log n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li>搜索、插入、删除，最差：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n</ol>\n<h1 id=\"缺点\"><a class=\"anchor\" href=\"#缺点\">#</a> 缺点</h1>\n<p>数据倾斜，退化为链表，时间复杂度最差：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<p><img data-src=\"%E6%95%B0%E6%8D%AE%E5%80%BE%E6%96%9C.svg\" alt=\"数据倾斜\" title=\"数据倾斜\" width=\"60%\" /></p>\n",
            "tags": [
                "algorithm",
                "tree",
                "algorithm",
                "tree",
                "bst"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2021/08/01/security/SHA256%20[RFC-4634]/",
            "url": "https://blog.ceciljxsu.icu/2021/08/01/security/SHA256%20[RFC-4634]/",
            "title": "SHA256 [RFC-4634]",
            "date_published": "2021-08-01T11:50:45.000Z",
            "content_html": "<h1 id=\"基础\"><a class=\"anchor\" href=\"#基础\">#</a> 基础</h1>\n<ol>\n<li>输入最大消息长度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mn>2</mn><mn>64</mn></msup></mrow><annotation encoding=\"application/x-tex\">2^{64}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8141079999999999em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">6</span><span class=\"mord mtight\">4</span></span></span></span></span></span></span></span></span></span></span></span> bits</li>\n<li>输出：256 bits</li>\n<li>大端 (Big endian) 为主</li>\n<li>word = 32 bits;</li>\n<li>block = 512 bit, 16 words;</li>\n</ol>\n<h1 id=\"位操作符号\"><a class=\"anchor\" href=\"#位操作符号\">#</a> 位操作符号</h1>\n<p>w = length of word.</p>\n<ol>\n<li>SHR 右移</li>\n<li>ROTR 循环右移</li>\n<li>ROTL 循环左移</li>\n</ol>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>SHR^n(x) = x>>n</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>ROTR^n(x) = (x>>n) OR (x&lt;&lt;(w-n))</pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>ROTL^n(x) = (x&lt;&lt;n) OR (x>>(w-n))</pre></td></tr></table></figure><figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>ROTL^n(x) = ROTR^(w-n)(x)</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>ROTR^n(x) = ROTL^(w-n)(x)</pre></td></tr></table></figure><h1 id=\"填充\"><a class=\"anchor\" href=\"#填充\">#</a> 填充</h1>\n<ol>\n<li>原长度 L</li>\n<li>填充 1</li>\n<li>填充 K 个 0：L + 1 + K = 448 (mod 512)</li>\n<li>结尾 64 bits 作为原长度的二进制表示。因此决定输入消息的长度。</li>\n</ol>\n<h1 id=\"函数\"><a class=\"anchor\" href=\"#函数\">#</a> 函数</h1>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>CH( x, y, z) = (x AND y) XOR ( (NOT x) AND z)</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>MAJ( x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z)</pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>BSIG0(x) = ROTR^2(x) XOR ROTR^13(x) XOR ROTR^22(x)</pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>BSIG1(x) = ROTR^6(x) XOR ROTR^11(x) XOR ROTR^25(x)</pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>SSIG0(x) = ROTR^7(x) XOR ROTR^18(x) XOR SHR^3(x)</pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>SSIG1(x) = ROTR^17(x) XOR ROTR^19(x) XOR SHR^10(x)</pre></td></tr></table></figure><h1 id=\"常量\"><a class=\"anchor\" href=\"#常量\">#</a> 常量</h1>\n<p>64 个 32 位常量：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>K</mi><mn>0</mn><mo separator=\"true\">,</mo><mi>K</mi><mn>1</mn><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><mi>K</mi><mn>63</mn></mrow><annotation encoding=\"application/x-tex\">K0, K1, ..., K63</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8777699999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">K</span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">K</span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mord\">.</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.16666666666666666em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">K</span><span class=\"mord\">6</span><span class=\"mord\">3</span></span></span></span></p>\n<p>前 64 个素数的<strong>立方根</strong>的双精度浮点数小数部分的前 32 位的 16 进制</p>\n<p>例如：</p>\n<ol>\n<li>cube root(2) = 1.25992104989</li>\n<li>双精度浮点数，符号位（1）+ 指数（11）+ 小数（52）</li>\n</ol>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>0 01111111111</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>0100 0010 1000 1010 0010 1111 1001 1000</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>11010001110011010000</pre></td></tr></table></figure><ol start=\"3\">\n<li>前 32 位的 16 进制表达</li>\n</ol>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>0100 0010 1000 1010 0010 1111 1001 1000</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>4 2 8 a 2 f 9 8</pre></td></tr></table></figure><figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>428a2f98 71374491 b5c0fbcf e9b5dba5</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>3956c25b 59f111f1 923f82a4 ab1c5ed5</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>d807aa98 12835b01 243185be 550c7dc3</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>72be5d74 80deb1fe 9bdc06a7 c19bf174</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>e49b69c1 efbe4786 0fc19dc6 240ca1cc</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>2de92c6f 4a7484aa 5cb0a9dc 76f988da</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>983e5152 a831c66d b00327c8 bf597fc7</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>c6e00bf3 d5a79147 06ca6351 14292967</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>27b70a85 2e1b2138 4d2c6dfc 53380d13</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>650a7354 766a0abb 81c2c92e 92722c85</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>a2bfe8a1 a81a664b c24b8b70 c76c51a3</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>d192e819 d6990624 f40e3585 106aa070</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>19a4c116 1e376c08 2748774c 34b0bcb5</pre></td></tr><tr><td data-num=\"14\"></td><td><pre>391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3</pre></td></tr><tr><td data-num=\"15\"></td><td><pre>748f82ee 78a5636f 84c87814 8cc70208</pre></td></tr><tr><td data-num=\"16\"></td><td><pre>90befffa a4506ceb bef9a3f7 c67178f2</pre></td></tr></table></figure><h1 id=\"最终输出\"><a class=\"anchor\" href=\"#最终输出\">#</a> 最终输出</h1>\n<p><code>+</code>  为字符串拼接</p>\n<blockquote>\n<p>H(N) = H(N)0 + H(N)1 + ... + H(N)7</p>\n</blockquote>\n<h1 id=\"初始化\"><a class=\"anchor\" href=\"#初始化\">#</a> 初始化</h1>\n<p>前 8 个素数的<strong>平方根</strong>的双精度浮点数小数部分的前 32 位的 16 进制</p>\n<p>和前面类似，不过是平方根。<br />\n例如：</p>\n<ol>\n<li>square root(2) = 1.41421356237</li>\n<li>二进制</li>\n</ol>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>0 01111111111</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>0110 1010 0000 1001 1110 0110 0110 0111</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>11110000010101011010</pre></td></tr></table></figure><ol start=\"3\">\n<li>十六进制</li>\n</ol>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>0110 1010 0000 1001 1110 0110 0110 0111</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>6 a 0 9 e 6 6 7</pre></td></tr></table></figure><figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>H(0)0 = 6a09e667</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>H(0)1 = bb67ae85</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>H(0)2 = 3c6ef372</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>H(0)3 = a54ff53a</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>H(0)4 = 510e527f</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>H(0)5 = 9b05688c</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>H(0)6 = 1f83d9ab</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>H(0)7 = 5be0cd19</pre></td></tr></table></figure><h1 id=\"处理\"><a class=\"anchor\" href=\"#处理\">#</a> 处理</h1>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>For i = 1 to N</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    1. Prepare the message schedule W:</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        For t = 0 to 15</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>            Wt = M(i)t</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        For t = 16 to 63</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>            Wt = SSIG1(W(t-2)) + W(t-7) + SSIG0(t-15) + W(t-16)</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    2. Initialize the working variables:</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        a = H(i-1)0</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        b = H(i-1)1</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        c = H(i-1)2</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        d = H(i-1)3</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        e = H(i-1)4</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        f = H(i-1)5</pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        g = H(i-1)6</pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        h = H(i-1)7</pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    3. Perform the main hash computation:</pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        For t = 0 to 63</pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            T1 = h + BSIG1(e) + CH(e,f,g) + Kt + Wt</pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            T2 = BSIG0(a) + MAJ(a,b,c)</pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            h = g</pre></td></tr><tr><td data-num=\"21\"></td><td><pre>            g = f</pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            f = e</pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            e = d + T1</pre></td></tr><tr><td data-num=\"24\"></td><td><pre>            d = c</pre></td></tr><tr><td data-num=\"25\"></td><td><pre>            c = b</pre></td></tr><tr><td data-num=\"26\"></td><td><pre>            b = a</pre></td></tr><tr><td data-num=\"27\"></td><td><pre>            a = T1 + T2</pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    4. Compute the intermediate hash value H(i):</pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        H(i)0 = a + H(i-1)0</pre></td></tr><tr><td data-num=\"30\"></td><td><pre>        H(i)1 = b + H(i-1)1</pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        H(i)2 = c + H(i-1)2</pre></td></tr><tr><td data-num=\"32\"></td><td><pre>        H(i)3 = d + H(i-1)3</pre></td></tr><tr><td data-num=\"33\"></td><td><pre>        H(i)4 = e + H(i-1)4</pre></td></tr><tr><td data-num=\"34\"></td><td><pre>        H(i)5 = f + H(i-1)5</pre></td></tr><tr><td data-num=\"35\"></td><td><pre>        H(i)6 = g + H(i-1)6</pre></td></tr><tr><td data-num=\"36\"></td><td><pre>        H(i)7 = h + H(i-1)7</pre></td></tr><tr><td data-num=\"37\"></td><td><pre></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>最后输出 H(N)，i -> N 轮</pre></td></tr></table></figure>",
            "tags": [
                "security",
                "sha256",
                "rfc-4634"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2020/04/13/java/usage/Java%207%20Concurrency%20Cookbook/",
            "url": "https://blog.ceciljxsu.icu/2020/04/13/java/usage/Java%207%20Concurrency%20Cookbook/",
            "title": "Java 7 Concurrency Cookbook",
            "date_published": "2020-04-13T06:09:29.000Z",
            "content_html": "<h1 id=\"线程的管理\"><a class=\"anchor\" href=\"#线程的管理\">#</a> 线程的管理</h1>\n<h2 id=\"线程的创建和运行\"><a class=\"anchor\" href=\"#线程的创建和运行\">#</a> 线程的创建和运行</h2>\n<ol>\n<li>继承 Thread，重写 run 方法并执行 start 方法。</li>\n<li>实现 Runnable 接口的 run 方法，并传递给 Thread 实例并执行 start 方法。</li>\n</ol>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// File1: 继承 Thread</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">MyThread1</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Thread</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">new</span> <span class=\"token class-name\">MyThread1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token comment\">// File2: 继承 Thread，匿名子类</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">MyThread2</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            </pre></td></tr><tr><td data-num=\"21\"></td><td><pre>            <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>                <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>            </pre></td></tr><tr><td data-num=\"26\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"29\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token comment\">// File3: 实现 Runnable</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">MyRunnable1</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">Runnable</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"34\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>        <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"38\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>        <span class=\"token class-name\">Runnable</span> r <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">MyRunnable1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>        <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"43\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre></pre></td></tr><tr><td data-num=\"45\"></td><td><pre><span class=\"token comment\">// File4: 实现 Runnable，匿名子类</span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">MyRunnable2</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"48\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre>        <span class=\"token class-name\">Runnable</span> r <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"50\"></td><td><pre>            </pre></td></tr><tr><td data-num=\"51\"></td><td><pre>            <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>                <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre>            </pre></td></tr><tr><td data-num=\"55\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"56\"></td><td><pre>        <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"57\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"58\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"59\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"获取和设置线程信息\"><a class=\"anchor\" href=\"#获取和设置线程信息\">#</a> 获取和设置线程信息</h2>\n<ol>\n<li>ID：每个线程的独特标识；</li>\n<li>Name：线程的名称；</li>\n<li>Priority：线程对象的优先级。优先级别从低到高为 1-10 之间。设置后，不建议改变它们的优先级。</li>\n<li>Status：线程的状态。在 Java 中，只有这 6 种：new，runnable，blocked，waiting，time waiting，terminated。</li>\n</ol>\n<p>前提：Thread t = new Thread ();</p>\n<ol>\n<li>t.getId() : long;</li>\n<li>Name 的设置与获取\n<ul>\n<li>new Thread(String name);</li>\n<li>new Thread(Thread t, String name);</li>\n<li>new Thread(Runnable r, String name);</li>\n<li>t.setName(String name);</li>\n<li>t.getName() : String;</li>\n</ul>\n</li>\n<li>设置与获取 Priority\n<ul>\n<li>Thread.MAX_PRIORITY;</li>\n<li>Thread.MIN_PRIORITY;</li>\n<li>t.setPriority(int i);</li>\n<li>t.getPriority() : int;</li>\n</ul>\n</li>\n<li>State 是一个枚举类型，如：Thread.State.TIMED_WAITING\n<ul>\n<li>t.getState() : Thread.State;</li>\n</ul>\n</li>\n</ol>\n<h2 id=\"线程的中断\"><a class=\"anchor\" href=\"#线程的中断\">#</a> 线程的中断</h2>\n<p>Thread t = new Thread();</p>\n<ol>\n<li>检测是否中断：t.isInterrupted () : boolean;</li>\n<li>任务中断：t.interrupt () : void;</li>\n</ol>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Interrupt</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">Runnable</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">Thread</span><span class=\"token punctuation\">.</span><span class=\"token function\">currentThread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">isInterrupted</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>                <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"interrupted.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>                <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"It's not interrupted.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            <span class=\"token keyword\">try</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>                <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">.</span><span class=\"token function\">sleep</span><span class=\"token punctuation\">(</span><span class=\"token number\">800L</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">InterruptedException</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>                <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"interrupted while this thread is sleep.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>                <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token class-name\">Runnable</span> r <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Interrupt</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token class-name\">Thread</span> t <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        t<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>        <span class=\"token keyword\">try</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>            <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">.</span><span class=\"token function\">sleep</span><span class=\"token punctuation\">(</span><span class=\"token number\">5000L</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>            t<span class=\"token punctuation\">.</span><span class=\"token function\">interrupt</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">InterruptedException</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>            e<span class=\"token punctuation\">.</span><span class=\"token function\">printStackTrace</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre></pre></td></tr><tr><td data-num=\"34\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"操作线程的中断机制\"><a class=\"anchor\" href=\"#操作线程的中断机制\">#</a> 操作线程的中断机制</h2>\n<p>检测线程是否中断，如果中断，则可以抛出异常 InterruptedException，并捕获处理。Thread.sleep 操作就需要自己捕获异常并处理，参考上面的<a href=\"#%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%B8%AD%E6%96%AD\">线程的中断</a>代码里的 run。</p>\n<h2 id=\"线程的睡眠与唤醒\"><a class=\"anchor\" href=\"#线程的睡眠与唤醒\">#</a> 线程的睡眠与唤醒</h2>\n<p>当你需要线程在一段时间后才执行，则可以让线程进入睡眠，睡眠这段时间消耗资源比较少。</p>\n<ol>\n<li>Thread.sleep(long milliseconds);</li>\n<li>TimeUnit.SECONDS.sleep (long seconds); 还有其它的时间单位。</li>\n</ol>\n<h2 id=\"等待线程的终结\"><a class=\"anchor\" href=\"#等待线程的终结\">#</a> 等待线程的终结</h2>\n<p>Thread t = new Thread();</p>\n<p>当前线程调用另外一个线程 t.join () 时，则当前线程会暂停，直到 t 线程完成了，才会继续运行。</p>\n<p>join 还有另外几个方法：</p>\n<ol>\n<li>t.join(long milliseconds);\n<ul>\n<li>等待线程 t 结束后，调用 join 的线程继续运行；</li>\n<li>线程 t 还没结束，等待 milliseconds 后，调用 join 的线程直接继续运行。</li>\n</ul>\n</li>\n<li>t.join(long milliseconds, long nanos);\n<ul>\n<li>跟第一个一样，只不过可以精确到纳秒。</li>\n</ul>\n</li>\n</ol>\n<h2 id=\"守护线程的创建与运行\"><a class=\"anchor\" href=\"#守护线程的创建与运行\">#</a> 守护线程的创建与运行</h2>\n<ol>\n<li>线程分用户线程与守护线程，GC 就是一个守护线程；</li>\n<li>守护线程优先级非常低，所以守护线程不能处理重要的任务；</li>\n<li>用户线程都结束时，守护线程自动结束；</li>\n<li>守护线程的设置 setDaemon 只能在 start 方法前调用，否则抛 IllegalThreadStateException 异常；</li>\n<li>与其它线程一样，只不过是在 start 方法前调用 setDaemon (true)。</li>\n</ol>\n<p>Thread t = new Thread();</p>\n<ul>\n<li>t.setDaemon(boolean daemon);</li>\n<li>t.isDaemon() : boolean;</li>\n</ul>\n<h2 id=\"在线程中处理不受控制的异常\"><a class=\"anchor\" href=\"#在线程中处理不受控制的异常\">#</a> 在线程中处理不受控制的异常</h2>\n<p>Java 里有 2 种异常：</p>\n<ol>\n<li>检查异常（Checked exceptions）: 这些异常必须强制捕获它们或在一个方法里的 throws 子句中。 例如， IOException 或者 ClassNotFoundException。</li>\n<li>未检查异常（Unchecked exceptions）: 这些异常不用强制捕获它们。例如， NumberFormatException, RuntimeException。</li>\n</ol>\n<p>不用担心线程的检查异常，因为 run 不能 throws 异常，所以只能在 run 内部捕获并处理；</p>\n<p>但 run 内部出现未检查异常，则需要进行下面处理：</p>\n<ol>\n<li>实现 Thread.UncaughtExceptionHandler 的 uncaughtException 方法；</li>\n<li>设置线程的未捕获异常处理器，setUncaughtExceptionHandler。</li>\n</ol>\n<p>Thread 对未检查异常处理的顺序是：</p>\n<ol>\n<li>检查线程是否有设置 handler；</li>\n<li>如果没设置，则检查线程组有没有设置 handler；</li>\n<li>如果没设置，则检查 Thread 有没有设置 setDefaultUncaughtExceptionHandler 全局默认 handler；</li>\n<li>如果没有就将 stack trace 输出到控制台。</li>\n</ol>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// GlobalExceptionHandler.java</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">GlobalExceptionHandler</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">Thread<span class=\"token punctuation\">.</span>UncaughtExceptionHandler</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">uncaughtException</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Thread</span> thread<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Throwable</span> throwable<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\">// Test.java</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Test</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token class-name\">Thread</span> t <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>                <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token comment\">// 设置未捕获异常处理器</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        t<span class=\"token punctuation\">.</span><span class=\"token function\">setUncaughtExceptionHandler</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">GlobalExceptionHandler</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        t<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"使用本地线程变量\"><a class=\"anchor\" href=\"#使用本地线程变量\">#</a> 使用本地线程变量</h2>\n<h3 id=\"threadlocal\"><a class=\"anchor\" href=\"#threadlocal\">#</a> ThreadLocal</h3>\n<p>多线程共享同一个对象时，就会出现相互影响。可以使用本地线程变量，每个线程都会储存各自的副本。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token class-name\">ThreadLocal</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> local <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ThreadLocal</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">protected</span> <span class=\"token class-name\">String</span> <span class=\"token function\">initialValue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token string\">\"initial value\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><ol>\n<li>local.get() : &lt;T&gt;;</li>\n<li>local.set(&lt;T&gt; value);</li>\n<li>local.remove();</li>\n</ol>\n<p>如果线程 A 里面创建线程 B，则线程 B 调用 local.get () 得到的是初始值，即没有继承线程 A 的本地线程变量。</p>\n<h3 id=\"inheritablethreadlocal\"><a class=\"anchor\" href=\"#inheritablethreadlocal\">#</a> InheritableThreadLocal</h3>\n<p>使用 InheritableThreadLocal 可以继承本地线程变量，InheritableThreadLocal 是 ThreadLocal 的子类；</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token class-name\">InheritableThreadLocal</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> local <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">InheritableThreadLocal</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">protected</span> <span class=\"token class-name\">String</span> <span class=\"token function\">childValue</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> s<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">super</span><span class=\"token punctuation\">.</span><span class=\"token function\">childValue</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 得到父线程的值，以父线程的值做初始化</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">protected</span> <span class=\"token class-name\">String</span> <span class=\"token function\">initialValue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token string\">\"initial value\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>与 ThreadLocal 的唯一区别是：InheritableThreadLocal 多了 childValue 方法。</p>\n<p>线程 A 创建子线程 B 时，则会为子线程 B 初始化 childValue 方法，该方法可以设置其它的值。</p>\n<h2 id=\"使用线程组\"><a class=\"anchor\" href=\"#使用线程组\">#</a> 使用线程组</h2>\n<h3 id=\"创建分组与设置\"><a class=\"anchor\" href=\"#创建分组与设置\">#</a> 创建分组与设置</h3>\n<p>为了方便管理多个线程，可以为线程分组，统一管理。</p>\n<p>根线程组为 system，默认线程组为 main。</p>\n<ul>\n<li>system\n<ul>\n<li>main\n<ul>\n<li>group1（自定义）\n<ul>\n<li>thread1</li>\n<li>thread2</li>\n<li>subGroup1</li>\n</ul>\n</li>\n<li>group2（自定义）</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token class-name\">ThreadGroup</span> group <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ThreadGroup</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"worker\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token class-name\">ThreadGroup</span> subGroup <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ThreadGroup</span><span class=\"token punctuation\">(</span>group<span class=\"token punctuation\">,</span> <span class=\"token string\">\"subWorker\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token class-name\">Runnable</span> r <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token class-name\">Thread</span> w1 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>group<span class=\"token punctuation\">,</span> <span class=\"token string\">\"worker1\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token class-name\">Thread</span> w2 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>group<span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token class-name\">Thread</span> w3 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>group<span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">,</span> <span class=\"token string\">\"worker3\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"获取group的信息与管理\"><a class=\"anchor\" href=\"#获取group的信息与管理\">#</a> 获取 Group 的信息与管理</h3>\n<ol>\n<li>获取信息：\n<ul>\n<li>group.activeCount () : int;    返回活动线程的估计数。</li>\n<li>group.activeGroupCount () : int;   返回活动线程组的估计数。</li>\n<li>group.getName () : String; 返回该线程组名称。</li>\n<li>grou.\tgetMaxPriority () : int; 返回该线程组下最大的优先级。</li>\n<li>group.getParent () : ThreadGroup;  返回该线程组的父线程组。</li>\n<li>group.list () : void;  打印线程组信息。</li>\n<li>group.checkAccess () : void;   确定当前运行的线程是否有权修改此线程组。</li>\n</ul>\n</li>\n<li>判断信息：\n<ul>\n<li>group.isDaemon () : boolean;   返回该线程组是否是守护线程。</li>\n<li>group.isDestroyed () : boolean;    返回该线程组是否被销毁。</li>\n<li>group.parentOf (ThreadGroup parent) : boolean; 判断指定线程组是否是该线程组的父级。</li>\n</ul>\n</li>\n<li>管理线程：\n<ul>\n<li>group.destroy ();  销毁线程。</li>\n<li>group.interrupt ();    中断线程。</li>\n<li>group.setDaemon (boolean b);   设置是否是守护线程组。</li>\n<li>group.setMaxPriority (int max);    设置最大优先级。</li>\n<li>group.uncaughtException (Thread t, Throwable throwable);    设置全局未捕获异常处理器。</li>\n</ul>\n</li>\n</ol>\n<h2 id=\"处理线程组内的不受控制异常\"><a class=\"anchor\" href=\"#处理线程组内的不受控制异常\">#</a> 处理线程组内的不受控制异常</h2>\n<p>继承 ThreadGroup 并重写 uncaughtException 方法。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">MyThreadGroup</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">ThreadGroup</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token class-name\">MyThreadGroup</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> s<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">uncaughtException</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Thread</span> thread<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Throwable</span> throwable<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">super</span><span class=\"token punctuation\">.</span><span class=\"token function\">uncaughtException</span><span class=\"token punctuation\">(</span>thread<span class=\"token punctuation\">,</span> throwable<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"用线程工厂创建线程\"><a class=\"anchor\" href=\"#用线程工厂创建线程\">#</a> 用线程工厂创建线程</h2>\n<p>实现 ThreadFactory 接口的 newThread 方法。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">MyThreadFactory</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">ThreadFactory</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token class-name\">Thread</span> <span class=\"token function\">newThread</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Runnable</span> runnable<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"基本线程同步\"><a class=\"anchor\" href=\"#基本线程同步\">#</a> 基本线程同步</h1>\n<p>临界区：访问一个共享资源在同一时间不能超过一个线程执行的代码块。</p>\n<h2 id=\"同步方法\"><a class=\"anchor\" href=\"#同步方法\">#</a> 同步方法</h2>\n<p>使用 synchronized 关键字控制并发线程。</p>\n<h3 id=\"根据修饰对象分类\"><a class=\"anchor\" href=\"#根据修饰对象分类\">#</a> 根据修饰对象分类</h3>\n<ol>\n<li>修饰代码块\n<ul>\n<li>synchronized(this | object) {}</li>\n<li>synchronized (类.class) {}</li>\n</ul>\n</li>\n<li>修饰方法\n<ul>\n<li>修饰普通方法</li>\n<li>修饰静态方法</li>\n</ul>\n</li>\n</ol>\n<h3 id=\"根据获取的锁分类\"><a class=\"anchor\" href=\"#根据获取的锁分类\">#</a> 根据获取的锁分类</h3>\n<ol>\n<li>获取对象锁\n<ul>\n<li>synchronized(this | object) {}</li>\n<li>修饰普通方法</li>\n</ul>\n</li>\n<li>获取类锁\n<ul>\n<li>synchronized (类.class) {}</li>\n<li>修饰静态方法（静态方法内的 synchronized 块必须是类锁）</li>\n</ul>\n</li>\n</ol>\n<h3 id=\"补充\"><a class=\"anchor\" href=\"#补充\">#</a> 补充</h3>\n<ol>\n<li>synchronized 关键字不能继承。</li>\n<li>定义接口方法时，不能使用 synchronized 关键字。</li>\n<li>构造方法不能使用 synchronized 关键字，但里面的代码块可以。</li>\n<li>类锁和对象锁是互不干扰的。</li>\n<li>synchronized 消耗资源比较大，而且导致死锁发生，所以不是临界区的就不使用，尽量避免同步。</li>\n</ol>\n<h2 id=\"在同步的类里安排独立属性\"><a class=\"anchor\" href=\"#在同步的类里安排独立属性\">#</a> 在同步的类里安排独立属性</h2>\n<p>你也可以在同步的类里面创建对象，使用该对象作为对象锁，而不必使用 this。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">ShareClass</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token comment\">// 用于对象锁</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">Object</span> object <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">long</span> val<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token class-name\">ShareClass</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">long</span> val<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>val <span class=\"token operator\">=</span> val<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">addVal</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">long</span> val<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token comment\">//object 锁</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token keyword\">synchronized</span> <span class=\"token punctuation\">(</span>object<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>val <span class=\"token operator\">+=</span> val<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"在同步代码中使用条件\"><a class=\"anchor\" href=\"#在同步代码中使用条件\">#</a> 在同步代码中使用条件</h2>\n<p>缓冲区是一个共享的数据结构，我们必须采用同步机制，比如 synchronized 关键字来控制对它的访问。但是我们有更多的限制因素，如果<strong>缓冲区是满的</strong>，生产者不能存储数据，如果<strong>缓冲区是空的</strong>，消费者不能取出数据。</p>\n<p>对于这些类型的情况，Java 在 Object 对象中提供 wait ()，notify ()，和 notifyAll () 方法的实现，这三个方法是 Object 里的，所以所有对象都有这三个方法。</p>\n<p>在 synchronized 外部调用 wait () 会抛 IllegalMonitorStateException 异常，并且调用 wait () 方法后，JVM 会休眠，并释放 synchronized 锁。使用 notify ()，和 notifyAll () 唤醒。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">ShareClass</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">Object</span> object <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 是否已经通知过了</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">boolean</span> wasSignaled <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">long</span> val <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">addVal</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">long</span> val<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">synchronized</span> <span class=\"token punctuation\">(</span>object<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            <span class=\"token comment\">//while 防止丢失信号，假唤醒</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            <span class=\"token comment\">//wasSignaled 是否已经通知过了，如果通知过了，则不执行 wait ();</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>wasSignaled <span class=\"token operator\">&amp;&amp;</span> <span class=\"token comment\">/* other condition */</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>                <span class=\"token keyword\">try</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>                    object<span class=\"token punctuation\">.</span><span class=\"token function\">wait</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">InterruptedException</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>                    e<span class=\"token punctuation\">.</span><span class=\"token function\">printStackTrace</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">notify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>        <span class=\"token comment\">// 已经通知过了</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        wasSignaled <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        object<span class=\"token punctuation\">.</span><span class=\"token function\">notify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>使用时，要注意<span class=\"exturl\" data-url=\"aHR0cDovL2lmZXZlLmNvbS90aHJlYWQtc2lnbmFsaW5nLyNtaXNzZWRfc2lnbmFs\">丢失信号和假唤醒</span></p>\n<ol>\n<li>丢失信号：使用标记，如果通知过了，就不再执行 wait () 方法。</li>\n<li>假唤醒：使用 while 来判断条件，而不是 if。</li>\n</ol>\n<h2 id=\"使用lock来同步代码块\"><a class=\"anchor\" href=\"#使用lock来同步代码块\">#</a> 使用 Lock 来同步代码块</h2>\n<p>Java 提供另外的机制用来同步代码块。它比 synchronized 关键字更加强大，灵活和更好的性能。</p>\n<p>Lock 接口：</p>\n<ol>\n<li>void lock();</li>\n<li>void unlock();</li>\n<li>boolean tryLock();</li>\n<li>boolean tryLock(long waitTime, TimeUnit unit) throws InterruptedException;</li>\n<li>Condition newCondition();</li>\n<li>void lockInterruptibly() throws InterruptedException;</li>\n</ol>\n<p>Lock 接口的实现类：</p>\n<ol>\n<li>ReentrantLock</li>\n<li>ReentrantReadWriteLock.ReadLock</li>\n<li>ReentrantReadWriteLock.WriteLock</li>\n</ol>\n<p>Lock 接口下的锁是手动释放的，所以<strong>建议在 try 块的 finally 下释放</strong>，防止异常导致锁没被释放。</p>\n<h2 id=\"使用读写锁同步数据访问\"><a class=\"anchor\" href=\"#使用读写锁同步数据访问\">#</a> 使用读 / 写锁同步数据访问</h2>\n<ol>\n<li>如果有读操作，则有新的写操作时，写操作的线程就会阻塞；</li>\n<li>如果有写操作，则有新的读操作或写操作，新的线程就会阻塞。</li>\n</ol>\n<h2 id=\"修改lock的公平性\"><a class=\"anchor\" href=\"#修改lock的公平性\">#</a> 修改 Lock 的公平性</h2>\n<p>在 ReentrantLock 类和 ReentrantReadWriteLock 类的构造器中，允许一个名为 fair 的 boolean 类型参数，它允许你来控制这些类的行为。默认值为 false，这将启用非公平模式。</p>\n<p>公平锁：排队，每个线程都有机会分到 CPU 时间片；<br />\n非公平锁：该线程会尝试获取锁，没有获取到就重新在队尾排队。</p>\n<p>由于 tryLock () 方法并不会使线程进入睡眠，即使 Lock 接口正在被使用，这个公平属性并不会影响它的功能。</p>\n<h2 id=\"在lock中使用多个条件\"><a class=\"anchor\" href=\"#在lock中使用多个条件\">#</a> 在 Lock 中使用多个条件</h2>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token class-name\">Lock</span> lock <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Reentrant</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token class-name\">Condition</span> c <span class=\"token operator\">=</span> lock<span class=\"token punctuation\">.</span><span class=\"token function\">newCondition</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><ol>\n<li>\n<p>c.await() : void throws InterruptedException;</p>\n</li>\n<li>\n<p>c.await(long time, TimeUnit unit) :boolean throws InterruptedException;</p>\n</li>\n<li>\n<p>c.awaitUntil(Date date) : boolean throws InterruptedException;</p>\n</li>\n<li>\n<p>c.awaitNanos(long nanos) : long throws InterruptedException;</p>\n</li>\n<li>\n<p>c.awaitUninterruptibly() : void;</p>\n</li>\n<li>\n<p>c.signal() : void;</p>\n</li>\n<li>\n<p>c.signalAll() : void;</p>\n</li>\n</ol>\n<h1 id=\"线程同步工具\"><a class=\"anchor\" href=\"#线程同步工具\">#</a> 线程同步工具</h1>\n<p>高级的机制来达到多线程的同步:</p>\n<ol>\n<li>Semaphores: 控制访问多个共享资源的计数器。此机制是并发编程的最基本的工具之一，而且大部分编程语言都会提供此机制。</li>\n<li>CountDownLatch: CountDownLatch 类是 Java 语言提供的一个机制，它允许线程等待多个操作的完结。</li>\n<li>CyclicBarrier: CyclicBarrier 类是又一个 java 语言提供的机制，它允许多个线程在同一个点同步。</li>\n<li>Phaser: Phaser 类是又一个 java 语言提供的机制，它控制并发任务分成段落来执行。全部的线程在继续执行下一个段之前必须等到之前的段执行结束。这是 Java 7 API 的一个新特性。</li>\n<li>Exchanger: Exchanger 类也是 java 语言提供的又一个机制，它提供 2 个线程间的数据交换点。</li>\n</ol>\n<h2 id=\"控制并发访问资源semaphores\"><a class=\"anchor\" href=\"#控制并发访问资源semaphores\">#</a> 控制并发访问资源 (Semaphores)</h2>\n<p>创建信号量：资源的数量</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 默认非公平锁</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token class-name\">Semaphore</span> s <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Semaphore</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">// 公平锁</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token class-name\">Semaphore</span> s <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Semaphore</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"获取信号量\"><a class=\"anchor\" href=\"#获取信号量\">#</a> 获取信号量</h3>\n<p>一直阻塞直到获取 n 个信号量成功或线程终止。</p>\n<ol>\n<li>s.acquire():void throws InterruptedException;</li>\n<li>s.acquire(int permits):void throws InterruptedException;</li>\n</ol>\n<p>一直阻塞直到获取 n 个信号量成功，<strong>不会被打断</strong>。</p>\n<ol>\n<li>s.acquireUninterruptibly();</li>\n<li>s.acquireUninterruptibly(int permits);</li>\n</ol>\n<h3 id=\"释放信号量\"><a class=\"anchor\" href=\"#释放信号量\">#</a> 释放信号量</h3>\n<p>释放 n 个信号量。</p>\n<ol>\n<li>s.release();</li>\n<li>s.release(int permits);</li>\n</ol>\n<h3 id=\"尝试获取信号量\"><a class=\"anchor\" href=\"#尝试获取信号量\">#</a> 尝试获取信号量</h3>\n<p>尝试获取 n 个信号量，如果没有则返回 false，该方法不阻塞，可以用在 if 上。</p>\n<ol>\n<li>s.tryAcquire();</li>\n<li>s.tryAcquire(int permits);</li>\n<li>s.tryAcquire(long timeout, TimeUnit unit);</li>\n<li>s.tryAcquire(int permits, long timeout, TimeUnit unit);</li>\n</ol>\n<p>如果获取到，则处理完毕，需要 s.release 释放。</p>\n<h3 id=\"其它信息或控制\"><a class=\"anchor\" href=\"#其它信息或控制\">#</a> 其它信息或控制</h3>\n<ol>\n<li>s.drainPermits () : int 立即返回剩余的信号量，并置 0;</li>\n<li>s.availablePermits () : int 获取剩余的信号量个数；</li>\n<li>s.getQueueLength () : int 获取排队中等待 acquire 的线程数目；</li>\n<li>s.hasQueuedThreads () : boolean 判断是否还有在排队的线程；</li>\n<li>s.isFair () : boolean ： 判断是否是公平锁；</li>\n</ol>\n<h2 id=\"等待多个并发事件完成\"><a class=\"anchor\" href=\"#等待多个并发事件完成\">#</a> 等待多个并发事件完成</h2>\n<p>Java 并发 API 提供这样的类，它允许 1 个或者多个线程一直等待，直到一组操作执行完成。 这个类就是 CountDownLatch 类。它初始一个整数值，此值是线程将要等待的操作数。当某个线程为了想要执行这些操作而等待时， 它要使用 await () 方法。此方法让线程进入休眠直到操作完成。 当某个操作结束，它使用 countDown () 方法来减少 CountDownLatch 类的内部计数器。当计数器到达 0 时，这个类会唤醒全部使用 await () 方法休眠的线程们。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 等待操作数</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token class-name\">CountDownLatch</span> c <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CountDownLatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>当计时器为 0，全部唤醒后，就失效了，计时器不能增加，所以得新建对象才能重新使用。</p>\n<h3 id=\"一个或多个线程等待\"><a class=\"anchor\" href=\"#一个或多个线程等待\">#</a> 一个或多个线程等待</h3>\n<ol>\n<li>c.await () : void throws InterruptedException 等待直到计数器为 0，才被唤醒并运行；</li>\n<li>c.await (long timeout, Timeout unit) : void throws InterruptedException 等待直到计数器为 0 或超时，才被唤醒并运行；</li>\n</ol>\n<h3 id=\"减少计时器\"><a class=\"anchor\" href=\"#减少计时器\">#</a> 减少计时器</h3>\n<ol>\n<li>c.countDown () : 计时器 --，当计时器 == 0 时，会唤醒所有调过 await 的线程；</li>\n</ol>\n<h3 id=\"获取计时器的值\"><a class=\"anchor\" href=\"#获取计时器的值\">#</a> 获取计时器的值</h3>\n<ol>\n<li>c.getCount () : long 计时器的值；</li>\n</ol>\n<h2 id=\"在同一个点同步任务\"><a class=\"anchor\" href=\"#在同一个点同步任务\">#</a> 在同一个点同步任务</h2>\n<p>CyclicBarrier 也叫同步屏障，在 JDK1.5 被引入，可以让一组线程达到一个屏障时被阻塞，直到最后一个线程达到屏障时，所以被阻塞的线程才能继续执行。</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>#   线程    屏障</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>线程1 -----> |</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  线程2 ---> | 全部到达屏障后，才能通过---></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> 线程3 ----> |</pre></td></tr></table></figure><figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token class-name\">Runnable</span> r <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token comment\">// do something!</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre># <span class=\"token number\">5</span>个线程</pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token class-name\">CyclicBarrier</span> c <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CyclicBarrier</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre># <span class=\"token number\">5</span>个线程结束后，执行r线程</pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token class-name\">CyclicBarrier</span> c <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CyclicBarrier</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"到达同步点后等待\"><a class=\"anchor\" href=\"#到达同步点后等待\">#</a> 到达同步点后，等待</h3>\n<ol>\n<li>c.await () : int throws InterruptedException, BrokenBarrierException 等待，直到所有的线程都调用 await，才唤醒；</li>\n<li>c.await (int timeout, TimeUnit unit) : int throws InterruptedException, BrokenBarrierException 等待，直到所有的线程都调用 await 或超时，才唤醒；</li>\n</ol>\n<h3 id=\"重置\"><a class=\"anchor\" href=\"#重置\">#</a> 重置</h3>\n<p>与 CountDownLatch 不同的是，CyclicBarrier 可以重置回到原来的状态。</p>\n<ol>\n<li>c.reset() : void;</li>\n</ol>\n<p>调用 reset 后，之前调用 await 的线程会抛出 broken 异常。</p>\n<h3 id=\"其它信息\"><a class=\"anchor\" href=\"#其它信息\">#</a> 其它信息</h3>\n<ol>\n<li>c.getNumberWaiting () : int 返回已经调用 await 方法的线程数；</li>\n<li>c.getParties () : int 返回剩余还没调用 await 方法的线程数；</li>\n<li>c.isBroken () : boolean 当其中一个线程被中止了，则其它线程也会收到 broken 异常，且该 barrier 的状态就变成 broken 状态。</li>\n</ol>\n<h2 id=\"运行阶段性并发任务\"><a class=\"anchor\" href=\"#运行阶段性并发任务\">#</a> 运行阶段性并发任务</h2>\n<h3 id=\"创建\"><a class=\"anchor\" href=\"#创建\">#</a> 创建</h3>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token class-name\">Phaser</span> p <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Phaser</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token class-name\">Phaser</span> p <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Phaser</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> parties<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token class-name\">Phaser</span> p <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Phaser</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Phaser</span> parent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token class-name\">Phaser</span> p <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Phaser</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Phaser</span> parent<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> parties<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"注册\"><a class=\"anchor\" href=\"#注册\">#</a> 注册</h3>\n<ol>\n<li>p.register() : int;</li>\n<li>p.bulkRegister(int parties) : int;</li>\n</ol>\n",
            "tags": [
                "java",
                "usage",
                "java",
                "concurrency"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2020/04/10/java/jvm/%E8%87%AA%E5%8A%A8%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E6%9C%BA%E5%88%B6/",
            "url": "https://blog.ceciljxsu.icu/2020/04/10/java/jvm/%E8%87%AA%E5%8A%A8%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E6%9C%BA%E5%88%B6/",
            "title": "自动内存管理机制",
            "date_published": "2020-04-10T10:01:20.000Z",
            "content_html": "<h1 id=\"运行时数据区域\"><a class=\"anchor\" href=\"#运行时数据区域\">#</a> 运行时数据区域</h1>\n<p><img data-src=\"runtime_data_area.jpg\" alt=\"runtime_data_area\" title=\"运行时数据区域\" width=\"60%\" /></p>\n<h2 id=\"程序计数器\"><a class=\"anchor\" href=\"#程序计数器\">#</a> 程序计数器</h2>\n<p>是一块较小的内存空间，当前线程所执行的字节码的行号指示器。</p>\n<ul>\n<li>仅概念模型，各 JVM 实现不一样。</li>\n<li>字节码解释器读／写该计数器。</li>\n<li>各线程独立储存计数器，称 “线程私有” 内存。</li>\n<li>线程正执行 Java 方法，计数器记录的是正在执行的虚拟机字节码指令地址。</li>\n<li>线程正执行 Native 方法，计数器值为空（Undefined）；</li>\n<li>此内存区域是唯一一个在 Java 虚拟机规范中未规定任何 OutOfMemoryError 情况的区域。</li>\n</ul>\n<h2 id=\"java虚拟机栈\"><a class=\"anchor\" href=\"#java虚拟机栈\">#</a> Java 虚拟机栈</h2>\n<p>是 Java 方法执行的内存模型；每个方法在执行的同时都创建一个栈帧（Stack Frame）；栈帧用于储存局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程，就对应着一个栈帧在虚拟机栈中入栈到出栈的过程：</p>\n<ol>\n<li>方法：调用 -------&gt; 执行完成</li>\n<li>栈帧：虚拟机栈 (入栈 -------&gt; 出栈)</li>\n</ol>\n<ul>\n<li>线程私有。</li>\n<li>生命周期与线程相同。</li>\n<li>局部变量表存放编译期基本数据类型（8 类）、对象引用和 returnAddress 类型（字节码指令地址）</li>\n<li>64 位 long 和 double 类型数据占用 2 个局部变量空间（Slot），其余类型占 1 个。</li>\n<li>局部变量表所需内存空间大小在编译期间决定，运行期间不会改变；进入方法时，在帧中分配已确定大小的局部变量空间。</li>\n<li>该区域定义两种异常：线程请求的栈深度大于虚拟机所允许的深度，将抛出 StackOverflowError 异常；如果虚拟机可以动态扩展，并扩展时无法申请到足够的内存，就会抛出 OutOfMemoryError 异常。</li>\n</ul>\n<h2 id=\"本地方法栈\"><a class=\"anchor\" href=\"#本地方法栈\">#</a> 本地方法栈</h2>\n<p>与虚拟机栈发挥的作用非常相似，区别是虚拟机栈为虚拟机执行 Java 方法（字节码）服务，而本地方法栈为虚拟机使用 Native 方法服务。</p>\n<p>该区域没规范，所以具体虚拟机可以自由实现它，Sun HotSpot 虚拟机把本地方法栈和虚拟机栈合二为一。</p>\n<ul>\n<li>本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemeryError 异常。</li>\n</ul>\n<h2 id=\"java堆\"><a class=\"anchor\" href=\"#java堆\">#</a> Java 堆</h2>\n<p>是 Java 虚拟机管理的内存中最大的一块，是被所有线程共享的一块内存区域，在虚拟机启动时创建。</p>\n<ul>\n<li>此内存区域存放对象实例以及数组。</li>\n<li>是垃圾收集器管理的主要区域，又称 GC 堆（Garbage Collected Heap）。</li>\n<li>内存回收角度：新生代和老年代；细分 Eden 空间、From Survivor 空间、To Survivor 空间；</li>\n<li>内存分配角度：可能划分出多个线程私有的分配缓冲区（Thread Local Allocation Buffer，TLAB）。</li>\n<li>可以不需要连续的内存。</li>\n<li>-Xmx -Xms 控制是否可扩展；如果没有内存完成实例分配，并且堆也无法再扩展，则将抛出 OutOfMemoryError。</li>\n</ul>\n<h2 id=\"方法区\"><a class=\"anchor\" href=\"#方法区\">#</a> 方法区</h2>\n<p>是各个线程共享的内存区域，用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。</p>\n<ul>\n<li>别名 Non-Heap（非堆），是堆的一个逻辑部分。</li>\n<li>HotSpot 虚拟机的 GC 扩展至方法区，又称 “永久代”（Permanent Generation），受 <code>-XX:MaxPermSize</code>  上限限制，后期可能移除永久代。</li>\n<li>JDK 1.7 HotSpot 已经从永久代中移除字符串常量池。</li>\n<li>无法满足内存分配需求时，将抛出 OutOfMemoryError 异常。</li>\n</ul>\n<h2 id=\"运行时常量池\"><a class=\"anchor\" href=\"#运行时常量池\">#</a> 运行时常量池</h2>\n<p>是方法区的一部分。Class 文件中有一项信息是常量池（Constant Pool Table），用于存放编译期生成的各种字面量和符号引用。</p>\n<ul>\n<li>运行期间也可以将新的常量放入池中，比如 String.intern () 方法。</li>\n<li>内存无法申请时，将抛出 OutOfMemoryError 异常。</li>\n</ul>\n<h2 id=\"直接内存\"><a class=\"anchor\" href=\"#直接内存\">#</a> 直接内存</h2>\n<p>直接内存（Direct Memory），Native 函数库直接分配堆外内存，然后由 Java 堆中的对象引用该内存。以此避免 Java 堆与 Native 堆中来回复制数据。</p>\n<ul>\n<li>JDK 1.4 新加入 NIO，DirectByteBuffer 对象直接引用 Native 分配的堆外内存。</li>\n<li>受本机总内存（RAM+SWAP 区 / 分页文件）大小以及处理器寻址空间限制。内存超出会抛出 OutOfMemoryError 异常。</li>\n</ul>\n<h1 id=\"hotspot虚拟机对象探秘\"><a class=\"anchor\" href=\"#hotspot虚拟机对象探秘\">#</a> HotSpot 虚拟机对象探秘</h1>\n<h2 id=\"对象的创建\"><a class=\"anchor\" href=\"#对象的创建\">#</a> 对象的创建</h2>\n<h3 id=\"new-指令的处理\"><a class=\"anchor\" href=\"#new-指令的处理\">#</a> new 指令的处理</h3>\n<ol>\n<li>检查指令的参数能否在常量池中定位到类的符号引用；并检查这个符号引用代表的类是否被加载、解析和初始化过。</li>\n<li>如果没有，那必须先执行相应的类加载过程。</li>\n<li>加载检查通过后，为新生对象分配确定大小的内存。</li>\n<li>将分配到的内存空间都初始化为零值（不包括对象头），保证实例字段不初始化就可以使用对应的零值。</li>\n<li>设置对象头，记录各种信息：GC 分代年龄、对象的哈希码、元数据信息等。</li>\n<li>至此，对象已经产生。执行 new 指令之后，接着执行 <code>&lt;init&gt;</code>  方法（由 invokespecial 指令决定）。</li>\n</ol>\n<h3 id=\"内存分配方式\"><a class=\"anchor\" href=\"#内存分配方式\">#</a> 内存分配方式</h3>\n<ol>\n<li>指针碰撞（Bump the Pointer）：用过的内存放在一边，空闲的内存放在另外一边，中间放置分界点的指示器；通过移动指示器来分配内存。Serial、ParNew 等 Compact 过程收集器采用该算法。</li>\n<li>空闲列表（Free List）：虚拟机维护一个列表，记录哪些内存块是可用的，从中分配足够的内存空间给对象实例，并更新记录。CMS 收集器基于 Mark-Sweep 算法，采用该方式。</li>\n</ol>\n<p>分配内存比较频繁，仅改变一个指针移动，在并发情况下不是线性安全的，解决方法：</p>\n<ol>\n<li>虚拟机采用 CAS 同步，并配上失败重试的方式保证更新操作的原子性。</li>\n<li>每个线程在 Java 堆中预先分配一小块内存，称为本地线程分配缓冲（Thread Local Allocation Buffer，TLAB），当 TLAB 用完并分配新 TLAB 时，才需同步锁定。由 <code>-XX:+/-UseTLAB</code>  参数决定。</li>\n</ol>\n<h2 id=\"对象的内存布局\"><a class=\"anchor\" href=\"#对象的内存布局\">#</a> 对象的内存布局</h2>\n<p>对象在内存中存储的布局可以分为 3 块区域：对象头、实例数据、对齐填充。</p>\n<p>下面以 32 位 JVM 为例。</p>\n<h3 id=\"对象头\"><a class=\"anchor\" href=\"#对象头\">#</a> 对象头</h3>\n<p>普通对象：</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>+-----------------------------------------------------------------+</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>|                     Object Header: 64-bits                      |</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>+--------------------------------+--------------------------------+</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>|       Mark Word: 32-bits       |       Klass Word: 32-bits      |</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>+--------------------------------+--------------------------------+</pre></td></tr></table></figure><p>数组对象：</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"><span>t</span></figcaption><table><tr><td data-num=\"1\"></td><td><pre>+--------------------------------------------------------------------------------------+</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>|                                Object Header: 96-bits                                |</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>+----------------------------+----------------------------+----------------------------+</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>|     Mark Word: 32-bits     |    Klass Word: 32-bits     |   array length: 32-bits    |</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>+----------------------------+----------------------------+----------------------------+</pre></td></tr></table></figure><h4 id=\"mark-word\"><a class=\"anchor\" href=\"#mark-word\">#</a> Mark Word</h4>\n<p>标记字：记录哈希码，GC 分代年龄、锁状态标志、线程持有的锁、偏向时间戳等，数据长度为 32bit（32 位）或 64bit（64 位），它会根据对象状态复用该存储空间。比如：HotSpot 32 位，未锁定时，25bit 用于对象哈希码，4bit 用于分代年龄，2bit 锁标志位，1bit 固定为 0。</p>\n<p>32 位的标记字结构如下：</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>+-----------------------------------------------------------+--------------------+</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>|                    Mark Word: 32-bits                     |       State        |</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>+-----------------------+--------+----------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>| identity_hashcode: 25 | age: 4 | biased_lock: 1 | lock: 2 |       Normal       |</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>+------------+----------+--------+----------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>| thread: 23 | epoch: 2 | age: 4 | biased_lock: 1 | lock: 2 |       Biased       |</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>+------------+----------+--------+----------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>|             ptr_to_lock_record: 30              | lock: 2 | Lightweight Locked |</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>+-------------------------------------------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>|         ptr_to_heavyweight_monitor: 30          | lock: 2 | Heavyweight Locked |</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>+-------------------------------------------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>|                                                 | lock: 2 |   Marked for GC    |</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>+-------------------------------------------------+---------+--------------------+</pre></td></tr></table></figure><table style=\"margin-bottom: 1em;\">\n<thead>\n<tr>\n<th>biased lock</th>\n<th>lock</th>\n<th>状态</th>\n<th>存储内容</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>01</td>\n<td>未锁定</td>\n<td>对象哈希码、对象分代年龄</td>\n</tr>\n<tr>\n<td>1</td>\n<td>01</td>\n<td>可偏向</td>\n<td>偏向线程 ID、偏向时间戳、对象分代年龄</td>\n</tr>\n<tr>\n<td>0</td>\n<td>00</td>\n<td>轻量级锁</td>\n<td>指向锁记录的指针</td>\n</tr>\n<tr>\n<td>0</td>\n<td>10</td>\n<td>重量级锁（膨胀）</td>\n<td>指向重量级锁的指针</td>\n</tr>\n<tr>\n<td>0</td>\n<td>11</td>\n<td>GC 标记</td>\n<td>空，不需要记录信息</td>\n</tr>\n</tbody>\n</table>\n<ul>\n<li><strong>biased_lock:</strong> 对象是否启用偏向锁标记：0 - 关闭；1 - 启用</li>\n<li><strong>age:</strong> 对象年龄，最大值为 15。在 GC 中，如果对象在 Survivor 区复制一次，年龄增加 1。当对象达到设定的阈值（ <code>-XX:MaxTenuringThreshold</code> ）时，将会晋升到老年代。默认情况下，并行 GC 的阈值为 15，并发 GC 的阈值为 6。</li>\n<li><strong>identity_hashcode:</strong> 哈希码，采用延迟加载技术。调用方法 <code>System.identityHashCode()</code>  计算，并会将结果写到该对象头中。当对象被锁定时，该值会移动到管程 Monitor 中。而且计算哈希码后，则不能开启偏向锁。</li>\n<li><strong>thread:</strong> 持有偏向锁的线程 ID。</li>\n<li><strong>epoch:</strong> 偏向时间戳。</li>\n<li><strong>ptr_to_lock_record:</strong> 指向栈中锁记录的指针。</li>\n<li><strong>ptr_to_heavyweight_monitor</strong> 指向管程 Monitor 的指针。</li>\n</ul>\n<p>64 位的标记字结构如下：</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>+------------------------------------------------------------------------------------+--------------------+</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>|                                 Mark Word: 64-bits                                 |       State        |</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>+------------+------------+----------+-----------+--------+----------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>| unused: 25 | identity_hashcode: 31 | unused: 1 | age: 4 | biased_lock: 1 | lock: 2 |       Normal       |</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>+------------+------------+----------+-----------+--------+----------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>|       thread: 54        | epoch: 2 | unused: 1 | age: 4 | biased_lock: 1 | lock: 2 |       Biased       |</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>+-------------------------+----------+-----------+--------+----------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>|                          ptr_to_lock_record: 62                          | lock: 2 | Lightweight Locked |</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>+--------------------------------------------------------------------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>|                      ptr_to_heavyweight_monitor: 62                      | lock: 2 | Heavyweight Locked |</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>+--------------------------------------------------------------------------+---------+--------------------+</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>|                                                                          | lock: 2 |   Marked for GC    |</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>+--------------------------------------------------------------------------+---------+--------------------+</pre></td></tr></table></figure><h4 id=\"klass-word\"><a class=\"anchor\" href=\"#klass-word\">#</a> Klass Word</h4>\n<p>类型指针：指向它的类元数据的指针，JVM 通过这个确定该对象是哪个类的实例。</p>\n<p>并不是所有 JVM 实现都必须在对象数据上保留该类型指针，可通过其它途径获取类元数据信息，参考<a href=\"#%E5%8F%A5%E6%9F%84%E8%AE%BF%E9%97%AE\">句柄访问</a>。</p>\n<p>如果对象是一个 Java 数组，那对象头中还必需记录数组长度。</p>\n<h3 id=\"实例数据instance-data\"><a class=\"anchor\" href=\"#实例数据instance-data\">#</a> 实例数据（Instance Data）</h3>\n<p>存储父类继承下来的与子类定义的字段内容。</p>\n<p>这部分存储顺序受虚拟机分配策略参数（FieldsAllocationStyle）和字段在 Java 源码中定义顺序的影响。</p>\n<p>HotSpot 虚拟机默认分配策略：longs/doubles、ints、shorts/chars、bytes/booleans、oops (Ordinary Object Pointers)，从中看出，相同宽度的字段放在一起。</p>\n<p>父类中定义的变量出现在子类之前。如果 CompactFields 参数值为 true（默认），那么子类之中较窄的变量也可能会插入到父类变量的空隙中。</p>\n<h3 id=\"对齐填充padding\"><a class=\"anchor\" href=\"#对齐填充padding\">#</a> 对齐填充（Padding）</h3>\n<p>HotSpot VM 的自动管理系统要求对象起始地址必须是 8 字节的整数倍，因此实例数据部分未对齐，则需要通过对齐填充来补全。</p>\n<h2 id=\"对象的访问定位\"><a class=\"anchor\" href=\"#对象的访问定位\">#</a> 对象的访问定位</h2>\n<p>通过栈上的 reference 数据来操作堆上的具体对象，访问堆中的对象的具体位置，决定虚拟机的实现方式。目前流行的访问方式有使用句柄和直接指针两种。</p>\n<h3 id=\"句柄访问\"><a class=\"anchor\" href=\"#句柄访问\">#</a> 句柄访问</h3>\n<p>Java 堆中将会划分出一块内存作为句柄池，reference 存储的是对象的句柄地址（指针的指针）。</p>\n<p><img data-src=\"reference_handler.jpg\" alt=\"reference_handler\" title=\"句柄访问\" width=\"80%\" /></p>\n<p>优点：<br />\n在对象被移动时（GC 时移动对象是非常普遍的行为），只会改变句柄中的实例数据指针，而 reference 本身不需要修改。</p>\n<h3 id=\"直接指针\"><a class=\"anchor\" href=\"#直接指针\">#</a> 直接指针</h3>\n<p>reference 直接存储对象的地址，对象的头部需要存储对象类型数据的地址。</p>\n<p><img data-src=\"reference_direct.jpg\" alt=\"reference_direct\" title=\"直接指针\" width=\"80%\" /></p>\n<p>优点：速度更快，节省一次指针定位的时间开销；对象访问在 Java 中非常频繁。Sun HotSpot 采用这种方式进行对象访问。</p>\n<h1 id=\"实战oom-异常\"><a class=\"anchor\" href=\"#实战oom-异常\">#</a> 实战：OOM 异常</h1>\n<p>显示运行时详细的 gc 记录</p>\n<blockquote>\n<p>JVM Args: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8</p>\n</blockquote>\n<h2 id=\"java堆溢出\"><a class=\"anchor\" href=\"#java堆溢出\">#</a> Java 堆溢出</h2>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/**</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> * JVM Args: -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> */</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">HeapOOM</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">static</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">OOMObject</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">OOMObject</span><span class=\"token punctuation\">></span></span> list <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            list<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">OOMObject</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>异常：<br />\njava.lang.OutOfMemoryError: Java heap space</p>\n<p>排查：</p>\n<ol>\n<li>检查是否是内存泄露，通过工具查看泄露对象到 GC Roots 的引链。</li>\n<li>如果不存在泄露，检查虚拟机参数（-Xmx 与 - Xms）；</li>\n<li>从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况。</li>\n</ol>\n<h2 id=\"虚拟机栈和本地方法栈溢出\"><a class=\"anchor\" href=\"#虚拟机栈和本地方法栈溢出\">#</a> 虚拟机栈和本地方法栈溢出</h2>\n<ol>\n<li>如果线程请求的栈深度大于虚拟机所允许的最大深度，将抛出 StackOverflowError 异常。</li>\n<li>如果虚拟机在扩展时无法申请到足够的内存空间，则抛出 OutOfMemoryError 异常。</li>\n</ol>\n<p>实验：</p>\n<ul>\n<li>使用 - Xss 参数减少栈内存容量。结果抛出 StackOverflowError 异常，异常出现时输出的堆栈深度相应缩小。</li>\n</ul>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/**</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> * VM Args: -Xss228k</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> */</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">JavaVMStackSOF</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">int</span> stackLength <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">stackLeak</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        stackLength<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token function\">stackLeak</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token class-name\">JavaVMStackSOF</span> oom <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">JavaVMStackSOF</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token keyword\">try</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            oom<span class=\"token punctuation\">.</span><span class=\"token function\">stackLeak</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">Throwable</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"stack length: \"</span> <span class=\"token operator\">+</span> oom<span class=\"token punctuation\">.</span>stackLength<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            <span class=\"token keyword\">throw</span> e<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><ul>\n<li>分配的栈内存越大，可创建的线程数就越少。</li>\n</ul>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/**</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> * VM Args: -Xss2M</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> */</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">JavaVMStackOOM</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">dontStop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">stackLeakByThread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            <span class=\"token class-name\">Thread</span> thread <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>                <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>                <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>                    <span class=\"token function\">dontStop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            thread<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">Throwable</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        <span class=\"token class-name\">JavaVMStackOOM</span> oom <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">JavaVMStackOOM</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        oom<span class=\"token punctuation\">.</span><span class=\"token function\">stackLeakByThread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre></pre></td></tr><tr><td data-num=\"28\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><ol>\n<li>如果出现 StackOverflowError 异常时，可参考堆栈。虚拟机默认参数，栈深度在大多数情况下达到 1000～2000 完全没问题，正常方法调用（包括递归）完全够用。</li>\n<li>如果是建立过多线程导致的内存溢出，在不能减少线程数或者更换 64 位虚拟机的情况下，就只能通过减少最大堆和减少栈容量来换取更多的线程。</li>\n</ol>\n<h2 id=\"方法区和运行时常量池溢出\"><a class=\"anchor\" href=\"#方法区和运行时常量池溢出\">#</a> 方法区和运行时常量池溢出</h2>\n<h3 id=\"运行时常量溢出\"><a class=\"anchor\" href=\"#运行时常量溢出\">#</a> 运行时常量溢出</h3>\n<p>以下在 JDK 1.6 之前有效，1.7 到 1.8 已经将常量池从方法区移除</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/**</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> */</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">RuntimeConstantPoolOOM</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token comment\">// 使用 List 保持常量池引用，避免 Full GC 回收常量池行为</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> list <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            list<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">.</span><span class=\"token function\">valueOf</span><span class=\"token punctuation\">(</span>i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">intern</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>JDK 1.7 以上：</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">RuntimeConstantPoolOOM</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token class-name\">String</span> str1 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">StringBuilder</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"计算机\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">append</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"软件\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token comment\">//true, 首次出现</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>str1<span class=\"token punctuation\">.</span><span class=\"token function\">intern</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> str1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  </pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token comment\">// 字面量，编译后放在常量池，出现过；Java 1.7 将常量池移到堆中。</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token class-name\">String</span> str <span class=\"token operator\">=</span> <span class=\"token string\">\"java\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token class-name\">String</span> str2 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">StringBuilder</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"ja\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">append</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"va\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token comment\">//false, 非首次出现</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>str2<span class=\"token punctuation\">.</span><span class=\"token function\">intern</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> str2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  </pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"方法区溢出\"><a class=\"anchor\" href=\"#方法区溢出\">#</a> 方法区溢出</h3>\n<p>需要引入 cglib 库</p>\n<figure class=\"highlight xml\"><figcaption data-lang=\"XML\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>dependency</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>groupId</span><span class=\"token punctuation\">></span></span>cglib<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>groupId</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>artifactId</span><span class=\"token punctuation\">></span></span>cglib-nodep<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>artifactId</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>version</span><span class=\"token punctuation\">></span></span>3.2.4<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>version</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>dependency</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure><figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/**</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> */</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">JavaMethodAreaOOM</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>            <span class=\"token class-name\">Enhancer</span> enhancer <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Enhancer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            enhancer<span class=\"token punctuation\">.</span><span class=\"token function\">setSuperclass</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">OOMObject</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            enhancer<span class=\"token punctuation\">.</span><span class=\"token function\">setUseCache</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>            enhancer<span class=\"token punctuation\">.</span><span class=\"token function\">setCallback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">MethodInterceptor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>                <span class=\"token annotation punctuation\">@Override</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>                <span class=\"token keyword\">public</span> <span class=\"token class-name\">Object</span> <span class=\"token function\">intercept</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Object</span> o<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Method</span> method<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Object</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> objects<span class=\"token punctuation\">,</span> <span class=\"token class-name\">MethodProxy</span> methodProxy<span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">Throwable</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>                    <span class=\"token keyword\">return</span> methodProxy<span class=\"token punctuation\">.</span><span class=\"token function\">invokeSuper</span><span class=\"token punctuation\">(</span>o<span class=\"token punctuation\">,</span> objects<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            enhancer<span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">static</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">OOMObject</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"本机直接内存溢出\"><a class=\"anchor\" href=\"#本机直接内存溢出\">#</a> 本机直接内存溢出</h2>\n<p>DirectMemory 容量可通过 <code>-XX:MaxDirectMemorySize</code>  指定，默认与 Java 堆最大值（-Xmx）一样。</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/**</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> * VM Args: -Xmx20M -XX:MaxDirectMemorySize=10M</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> */</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">DirectMemoryOOM</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">final</span> <span class=\"token keyword\">int</span> _1MB <span class=\"token operator\">=</span> <span class=\"token number\">1024</span> <span class=\"token operator\">*</span> <span class=\"token number\">1024</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">Exception</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token class-name\">Field</span> unsafeField <span class=\"token operator\">=</span> <span class=\"token class-name\">Unsafe</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">.</span><span class=\"token function\">getDeclaredFields</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        unsafeField<span class=\"token punctuation\">.</span><span class=\"token function\">setAccessible</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token class-name\">Unsafe</span> unsafe <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">Unsafe</span><span class=\"token punctuation\">)</span> unsafeField<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            unsafe<span class=\"token punctuation\">.</span><span class=\"token function\">allocateMemory</span><span class=\"token punctuation\">(</span>_1MB<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>由于 DirectMemory 导致的内存溢出，一个明显的特征是在 Heap Dump 文件中不会看到明显的异常。</p>\n<p>如果发现 OOM 之后的 Dump 文件很小，而程序又直接或间接使用 NIO，则可能是这个原因。</p>\n",
            "tags": [
                "java",
                "jvm",
                "java",
                "jvm",
                "jmm"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2020/04/08/category/network/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%AF%95%E9%A2%98/",
            "url": "https://blog.ceciljxsu.icu/2020/04/08/category/network/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%AF%95%E9%A2%98/",
            "title": "计算机网络试题",
            "date_published": "2020-04-08T06:09:29.000Z",
            "content_html": "<h1 id=\"知识点\"><a class=\"anchor\" href=\"#知识点\">#</a> 知识点</h1>\n<ol>\n<li class=\"quiz essay\">\n<p>OSI 七层模型分别对应着五层模型的哪一部分</p>\n<blockquote>\n<ol>\n<li><strong>OSI 七层模型：</strong> 物理层、数据链路层、网络层、传输层、会话层、表示层、应用层</li>\n<li><strong>TCP/IP 四层模型：</strong> 网络接口层（链接层）、网络互联层（网际层）、传输层、应用层</li>\n<li><strong>五层模式：</strong> 将 OSI 模型和 TCP/IP 模型对比，因此其实还是 TCP/IP 的四层，只不过将网络接口层拆分为物理层和数据链路层。</li>\n</ol>\n<ul>\n<li><strong>物理层：</strong> 在局部局域网上传送数据帧，针脚、电压、线缆、集线器、中继器、网卡、接口卡等。</li>\n<li><strong>数据链路层：</strong> 网络寻址、错误侦测和改错，逻辑链路控制（LLC）子层、介质访问控制（MAC）子层</li>\n<li><strong>网络层：</strong> 数据的路径选择和转寄。互联网协议（IP）、ICMP</li>\n<li><strong>传输层：</strong> TCP、UDP</li>\n<li><strong>会话层：</strong> 保持双方的连接，对话；RPC，Sockets</li>\n<li><strong>表示层：</strong> 数据的表现形式，例如压缩等，MIME，SSL，TLS</li>\n<li><strong>应用层：</strong> WebSocket、HTTP</li>\n</ul>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>数据链路层三大法宝</p>\n<blockquote>\n<ol>\n<li><strong>封装成帧：</strong> 在数据的前后添加首部、尾部。</li>\n<li><strong>透明传输：</strong> 避免传输的数据中包含帧定界符，通过转义。</li>\n<li><strong>差错检测：</strong> 防止接收到传输过程中发生错误的数据。\n<ul>\n<li><strong>FCS 生成：</strong> 传输数据 / 除数 = 商... 余数（FCS）</li>\n<li><strong>CRC 校验：</strong> （传输数据 + 余数） / 除数 = 商...0</li>\n</ul>\n</li>\n</ol>\n<p>商丢弃，用不到，余数作为 FCS；CRC 校验，余数为 0 则正确。<br />\n除数都是约定的，不同标准有不同的约定。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>流量控制</p>\n<blockquote>\n<p>TCP 流量控制</p>\n<ol>\n<li>连续 ARQ 机制</li>\n<li>滑动窗口机制</li>\n<li>累计确认</li>\n<li>动态调整 ACK 号的等待时间</li>\n<li>ACK 和窗口的合并</li>\n</ol>\n<p><strong>连续 ARQ （Automatic Repeat reQuest）机制：</strong> 不采用<strong>停止等待协议</strong>，即一问一答的线性方式，效率低下。而是采用连续发送多个分组，然后再等待确认。持有对方的窗口大小，根据窗口大小连续发送。</p>\n<p><strong>滑动窗口：</strong> 接收方通过握手阶段，以及 ACK 应答包，通知发送方，自己缓冲区空闲的容量。发送方就可以根据这个容量，进行连续 ARQ 发送。</p>\n<p><strong>累计确认：</strong> 接收方不用立即应答 ACK，而是等待一段时间，在这段时间可以处理多个分组，然后才应答最新的 ACK 号给对方。</p>\n<p><strong>动态调整 ACK 号的等待时间：</strong> 发送方在连续 ARQ 发送后，等待对方的 ACK 包到达时间，如果网络拥堵，则 ACK 包到达的就很慢，超时时间就提高；如果网络减少拥堵了，则 ACK 包就到达的很快，相应的，超时时间就降低。超时时间就是等待时间，如果超过这个超时时间，就认为对方没收到，因此重新发送上次的一批分组。</p>\n<p><strong>ACK 和窗口的合并：</strong> 接收方发送应答包 ACK 时，也可以在 ACK 包上面携带新的窗口大小，这样每次都可以减少一个包的发送。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 滑动窗口</p>\n<blockquote>\n<ol>\n<li><strong>窗口：</strong> 指的是接收方的空闲缓存区，处理能力的一个容量大小</li>\n<li><strong>滑动：</strong> 窗口动态变化，接收方处理能力实时变化，而且是根据接收分组序号的顺序滑动的。</li>\n</ol>\n<p><strong>流量控制：</strong> 参考<a href=\"#%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6\">流量控制</a>，以及还有一点，死锁的发生。</p>\n<p>接收方 B 发送一个窗口为 0 的大小，发送方 A 就开始等待；等待接收方 B 处理完缓冲区数据后，返回 ACK 包。然而，如果发送方 A 没收到 ACK 包，双方就一直等待，进入死锁状态。</p>\n<p>这种情况下，发送方 A 接收到 B 的 0 窗口 ACK 包后，进入等待的同时，<strong>持续计时器</strong>也同时开始工作，时间一到，就主动<strong>发送 1 字节或不包含数据的试探包</strong>，<strong>序号使用旧的序号</strong>，这样不会浪费序号；如果对方返回还是零窗口，则重置计时器，重新等待。直到窗口不为 0。会使用退避算法尝试。</p>\n<p><strong>拥堵控制</strong></p>\n<p><strong>滑动窗口：</strong> 解决的是接收方处理速度跟不上发送方发送速度的解决方案。</p>\n<p><strong>拥堵控制：</strong> 解决的是阻止传输路径上拥堵的手段。</p>\n<p>发送方会根据滑动窗口和拥堵窗口来发送。</p>\n<p>控制发送量，慢慢接近网络的承载量。</p>\n<ul>\n<li><strong>RTO (Retransmission TimeOut)：</strong> 重传的超时时间，即等待 ACK 应答的时间。</li>\n<li><strong>RTT (Round Trip Time)：</strong> 单次握手的往返时间。</li>\n</ul>\n<ol>\n<li>TCP 为每条连接维护一个 “<strong>拥堵窗口</strong>”，拥堵窗口初始化为 1 个 MSS。</li>\n<li>每次接收对方的 ACK，拥堵窗口就成倍增加；</li>\n<li>直到到达一个 “<strong>慢启动阈值</strong>”，到达后，每次接收对方的 ACK，拥堵窗口就增加 1，线性增加。</li>\n<li>如果等待 ACK 发生超时，慢启动阈值就降为超时前拥堵窗口的一半大小，拥堵窗口重置为 1，重新回到慢启动阶段。</li>\n</ol>\n<p>这里调优，可以控制拥堵窗口的增加量，以及窗口最大限值。</p>\n</blockquote>\n<blockquote>\n<p>对于报文丢失的处理，有不同的算法，区别是在<strong>重复确认</strong>：</p>\n<ol>\n<li><strong>TCP Tahoe：</strong> 丢失时，进入 “<strong>快速重传</strong>”，慢启动阈值设为之前的拥堵窗口值的一半，拥堵窗口值降为初始值，重新进入慢启动阶段。</li>\n<li><strong>TCP Reno：</strong> <strong>快速恢复</strong>，慢启动阈值设置为之前拥堵窗口值的一半，但是，新的拥堵窗口值也为前拥堵窗口值的一半，跳过了慢启动阶段；如果继续遇到超时，则才进入慢启动阶段。</li>\n</ol>\n<p><strong>超时或者重复确认</strong>，认为是网络拥堵或网络质量差导致的丢包。</p>\n<p>重复确认即收到相同的 ACK 号，例如阈值是 3 次，即第 4 次收到相同确认号，那说明有包丢失了。</p>\n<p>对于 RTO 即超时，两个算法都是将拥堵窗口降为 1 个 MSS，然后进入慢启动阶段。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 为什么可靠？</p>\n<blockquote>\n<ol>\n<li><strong>确认 / 重传：</strong> 发送方发送后，需要接收方发回确认包，如果没收到接收方的确认，则会进行重传。</li>\n<li><strong>分组序号：</strong> 每个分组都有序列号，而且是排序的，能检测数据是否完整。</li>\n<li><strong>流量控制</strong></li>\n<li><strong>拥堵控制</strong></li>\n<li><strong>CRC 校验和</strong>，当然 UDP 也有，因此不是特有的。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 重传</p>\n<blockquote>\n<ol>\n<li>超时重传</li>\n<li>重复确认重传</li>\n</ol>\n<p>重传有个问题，是全部重传呢？还是部分重传呢？</p>\n<p>因此，引入 SACK 机制。</p>\n<p>还有 D-SACK</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 拆包 / 黏包机器解决办法</p>\n<blockquote>\n<p>TCP 是流协议，即没有界限的一串数据。TCP 不了解上层业务数据的具体含义，因此一个完整的包可能出现划分，或者多个小包封装成一个大的数据包。</p>\n<p>产生原因：</p>\n<ol>\n<li>write 写入的字节大于发送缓冲区的大小，因此进行拆分；</li>\n<li>进行 MSS 大小的 TCP 分段；</li>\n<li>以太网帧的 payload 大于 MTU 进行 IP 分片。</li>\n</ol>\n<p>解决策略：</p>\n<ol>\n<li><strong>消息定长</strong>，例如每个报文固定为 200 字节，不够就空位补空格。</li>\n<li><strong>在包尾部增加回车换行符</strong>，进行分割，例如 FTP 协议；</li>\n<li><strong>将消息分为消息头和消息体</strong>，消息头包含消息总长度的消息 / 或消息体的长度；一般设计是，消息头第一个字段使用 int32 来表示消息的总长度。</li>\n<li><strong>更复杂的应用层协议</strong>。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 详解：重传、流量控制、拥塞控制</p>\n<blockquote>\n<p>无.</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 拥塞算法</p>\n<blockquote>\n<p>早期的 Tahoe</p>\n<p>现代的：Reno、HSTCP、BIC、Vegas、Westwood</p>\n<ol>\n<li>基于丢包反馈的 TCP 协议（Tahoe、Reno、New Reno、SACK）</li>\n<li>基于延时反馈的 TCP 协议（Vegas、Westwood）</li>\n<li>无线传输中的 Westwood 算法</li>\n<li>基于丢包反馈的高速带宽算法（HSTCP、STCP、BIC-TCP、CUBIC）</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 为什么采用三次握手，而不是两次握手或四次握手？</p>\n<blockquote>\n<ol>\n<li>TCP 协议提供<strong>可靠的面向连接服务</strong>。</li>\n<li>因此<strong>发送时，需要对方应答</strong>，才能知道对方有没收到。（这样就需要 2 次握手）</li>\n<li>再由于 TCP 协议是<strong>全双工的</strong>，双方都可以发送和接收数据。</li>\n<li>因此，双方都需要知道对方是否接收成功，因此，双方都要应答。（假设双方都发送连接请求、以及应答请求，这样就 4 次了）。</li>\n<li>然而，一方的应答和请求可以同时发起，即合并在一起，因此至少要 3 次握手，以及握手次数越少越好，因此就是 3 次了。</li>\n</ol>\n<p>连接还有一个重点是：连接是为了初始化双方的一些设置，例如：序号、窗口值、以及选项（例如：SACK 是否支持）；这就是为什么需要双方都连接。</p>\n<p>SACK - Selective Acknowledgment</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 三次握手数据丢失会发生什么？</p>\n<blockquote>\n<p>有超时重传，重传指定次数都失败后，就断开连接。例如：第三次握手丢失，接收方会重传 SYN + ACK。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>RST 产生的情况</p>\n<blockquote>\n<ol>\n<li>目标端口未监听，不存在</li>\n<li>目的主机或者网络中防火墙拦截</li>\n<li>向已经关闭的 socket 发送数据</li>\n<li>向已关闭的连接发送 FIN</li>\n</ol>\n<p>对已经收到 RST 的连接进行 IO 操作，会产生 SIGPIPE 信号，broken pipe。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP/UDP 报最大长度</p>\n<blockquote>\n<p>UDP 的是 65535 - 头部 8 字节 = 65527</p>\n<p>TCP 由 MSS 决定的，一般是 1460，以太网是 1500 - IP 头部（20） - TCP 头部（20） = 1460，当然还有可选字段，以及 MSS 双方可以协商。</p>\n<p>MSS 协商，可以在 TCP 头部可选字段携带。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP/UDP 报文格式</p>\n<blockquote>\n<p>TCP 头部结构：</p>\n<ol>\n<li>发送方端口号（2 字节）、接收方端口号（2 字节）</li>\n<li>序号（4 字节）</li>\n<li>ACK（4 字节）</li>\n<li>数据偏移量（4 位）、保留（6 位）、控制位（6 位）、窗口（2 字节）</li>\n<li>校验和（2 字节）、紧急指针（2 字节）</li>\n<li>可选字段（可变长度，可有可无）</li>\n</ol>\n<p>UDP 头部结构：</p>\n<ol>\n<li>发送方端口（2 字节）、接收方端口（2 字节）</li>\n<li>数据长度（2 字节）、校验和（2 字节）</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP/UDP 优缺点以及区别</p>\n<blockquote>\n<p>TCP：</p>\n<ol>\n<li>优点：可靠，稳定。三次握手、确认、窗口、重传、拥堵控制，传完后断开连接。</li>\n<li>缺点：慢，效率低，占用系统资源高，易被攻击。</li>\n</ol>\n<p>UDP：</p>\n<ol>\n<li>优点：快，比 TCP 稍安全。没有握手、确认、窗口、重传、拥堵控制等机制，无状态协议，传递数据快。</li>\n<li>缺点：不可靠，不稳定</li>\n</ol>\n<p>TCP 只能点到点；UDP 支持一对一，一对多，多对一和多对多的交互通信。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>HTTP 与 TCP 的区别和联系</p>\n<blockquote>\n<ul>\n<li>区别：HTTP 是应用层的协议，TCP 是传输层的协议。</li>\n<li>联系：HTTP 基于 TCP 协议传输内容。</li>\n</ul>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>http 和 https 的区别与联系？</p>\n<blockquote>\n<ul>\n<li>区别：http 是明文传输的；https 是加密后传输的。端口不同</li>\n<li>联系：http + SSL = https；https 是在 http 的基础上，加上安全机制，通过证书，</li>\n</ul>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>为什么说 Http 是无状态的协议？</p>\n<blockquote>\n<ol>\n<li>请求完成后，就释放连接，尽快将资源释放给其它客户。无连接</li>\n<li>无状态是指协议对于事务处理没有记忆能力，服务器不知道客户端的状态。请求完成后就断开，不保存状态。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>Http 的 Http basic authentication</p>\n<blockquote>\n<ol>\n<li>客户端发起 http 请求；</li>\n<li>服务器验证此用户是否已经登陆，如果没有，就返回 401 给客户端，以及头部携带 WWW-Authenticate 字段，此字段提示客户端授权方式。例如：Basic</li>\n<li>客户端输入账号、密码后，使用 base64 将账号和密码编码，然后将编码值放在头部的 Authorization 字段。</li>\n<li>服务器从头部获取 Authorization 字段，然后解码，以及验证用户身份，验证通过后，就生成 session id，以及保存 session 相关信息，session id 通过 cookie 返回给客户端。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>HTTP 请求的 GET 与 POST 方式的区别</p>\n<blockquote>\n<ol>\n<li>参数的位置不同</li>\n<li>是否跨域</li>\n<li>GET 可以回退，而 POST 会再次提交请求</li>\n<li>GET 可以被 bookmark，而 POST 不可以</li>\n<li>GET 可以被浏览器缓存，而 POST 不会，除非手动设置</li>\n<li>GET 只能进行 url 编码，而 POST 支持多种编码方式</li>\n<li>GET 请求参数会被完整保留在历史记录中，而 POST 不行</li>\n<li>GET URL 有长度限制、只能 ASCII 字符，而 POST 没限制</li>\n<li>post 会先发送 options 试探跨域，然后再发送数据；而 GET 不会</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>Http1.0、Http1.1、Http2.0 的区别</p>\n<blockquote>\n<p>1.0 和 1.1 比较：</p>\n<ol>\n<li>1.0 需要通过 keep-alive 告知服务器要建立长连接；而 1.1 默认</li>\n<li>缓存：1.0 有 If-Modified-Since, Expires 作为判断；而 1.1 引入过多控制策略：Entity tag，If-Unmodified-Since，If-Match，If-None-Match 等</li>\n<li>状态码：1.1 新增 24 个错误状态码，如 409（Conflict），410（Gone）</li>\n<li>1.1 支持只发送 header 信息而不带任何 body 信息，例如：OPTINOS 和 POST；服务器认为有权限，就返回 100 状态码，否则就是 401。客户收到 100 后，才发送数据。这样不用因为 401 就发送数据，节约带宽。</li>\n<li>HOST：1.0 认为每台服务器只绑定一个唯一的 IP 地址，因此请求消息中 URL 并没有主机名。但虚拟主机技术的发展，一台物理服务器上可存在多个虚拟主机，并且共享一个 IP 地址。因此请求和响应消息都支持 Host 域，且请求消息如果没有 Host 域就报 400 错误。</li>\n</ol>\n<p>1.1 和 2.0 比较：</p>\n<ol>\n<li>多路复用：浏览器客户端在同一时间段针对同一域名的请求有一定数据限制，超过限制数目就会被阻塞。2.0 使用多路复用技术，同一连接并发处理多个请求，且并发数量比 1.1 大了好几个数量级。</li>\n<li>首部压缩：1.1 不支持。2.0 使用 HPACK 算法对 header 的数据进行压缩。</li>\n<li>服务器推送：2.0 支持把客户端需要的资源一起推送到客户端，免得客户端再次创建连接发送请求到服务器端获取。这种方式非常适合加载静态资源。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>Http 安全性</p>\n<blockquote>\n<ol>\n<li>内容加密：看不到内容具体意义</li>\n<li>身份认证：确认网站的真实性</li>\n<li>数据完整性：防止内容被第三方冒充或者篡改。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>从输入 URL 到页面加载发生了什么？</p>\n<blockquote>\n<ol>\n<li>DNS 解析</li>\n<li>TCP 连接</li>\n<li>发送 HTTP 请求</li>\n<li>服务器处理请求并返回 HTTP 报文</li>\n<li>浏览器解析渲染页面</li>\n<li>连接结束。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>Http 和 Socket 优劣比较？</p>\n<blockquote>\n<p>Http 优点：基于应用层的接口，使用方便</p>\n<p>Http 缺点：</p>\n<ol>\n<li>传输速度慢、数据包大。</li>\n<li>实现实时交互，服务器性能压力大。</li>\n<li>数据传输安全性差，服务器不会自动给客户端发送数据，除了 2.0 版本。</li>\n</ol>\n<p>Socket 优点：</p>\n<ol>\n<li>传输数据为字节级，传输数据可自定义，数据量少</li>\n<li>传输数据时间短，性能高</li>\n<li>适合客户端和服务器之间信息实时交互</li>\n</ol>\n<p>Socket 缺点：</p>\n<ol>\n<li>需要对传输的数据进行解析，转化为应用层的数据</li>\n<li>对开发人员的开发水平较高</li>\n<li>相对于 Http 协议传输，增加了开发量。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>如何实现可靠的 UDP </p>\n<blockquote>\n<p>可以按照 TCP 的可靠特性，在应用层处理相应的机制，例如：分片、确认、重发、拥堵控制等。这就变成 TCP 了。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>网络协议是什么？</p>\n<blockquote>\n<ol>\n<li>计算机双方通信时必须共同遵从的<strong>一组约定</strong>。如何建立连接，如何识别对方等。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>为什么要对网络协议分层？</p>\n<blockquote>\n<ol>\n<li>在制定标准之前，各个厂商对以太网的实现都不太统一，因此由国际标准组织统一标准，制定了 OSI 标准模型。</li>\n<li>分层是为了将职责划分，这样比较直观、容易描述和理解复杂的系统，以及方便管理。因此采用分层的方式制定规范。计算机很多系统都是以分层思想来设计的。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>应用层</p>\n<blockquote>\n<ol>\n<li>应用层位于 OSI 的最上层。</li>\n<li>应用层直接和应用程序接口结合，并提供常见的服务。</li>\n<li>例子：HTTP、DNS、DHCP、FTP、SMTP、Telnet、SSH、POP3 等。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>传输层</p>\n<blockquote>\n<ol>\n<li><strong>为应用提供端到端的通信服务。</strong></li>\n<li>例如：TCP、UDP 协议</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>网络层</p>\n<blockquote>\n<ol>\n<li><strong>提供路由和寻址功能。</strong></li>\n<li>使用<strong> IP 地址</strong>来唯一标识互联网上的设备。依靠 IP 地址进行相互通信。</li>\n<li>在网络内部，是不需要网络层设备的，仅仅靠数据链路层就可以进行通信。对于不同网络的互联，就需要借助路由器等第三层设备。不同网络相互通信因此形成互联网。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>数据链路层</p>\n<blockquote>\n<p>构成数据单元（数据帧），并对帧定界、同步、收发顺序的控制，以及差错校验等。</p>\n<p>导线的端到端数据传输。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>物理层</p>\n<blockquote>\n<ol>\n<li>为数据端设备提供传送数据通路。</li>\n<li>传输数据。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP/IP 协议族</p>\n<blockquote>\n<ol>\n<li>是一个网络通信模型，为网际网络的基础通信架构。</li>\n<li>TCP 和 IP 是该协议族的最初核心协议，因此称为 TCP/IP 协议族。</li>\n<li>TCP/IP 提供了应用的端到端通信的机制，将数据应该如何封装、定址、传输、路由以及在目的地如何接收，都加以标准化。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 报文的头部结构</p>\n<blockquote>\n<p>TCP 头部结构：</p>\n<ol>\n<li>发送方端口号（2 字节）、接收方端口号（2 字节）</li>\n<li>序号（4 字节）</li>\n<li>ACK（4 字节）</li>\n<li>数据偏移量（4 位）、保留（6 位）、控制位（6 位）、窗口（2 字节）</li>\n<li>校验和（2 字节）、紧急指针（2 字节）</li>\n<li>可选字段（可变长度，可有可无）</li>\n</ol>\n<p>数据偏移量的单位，4 字节；因此，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><msup><mn>2</mn><mn>4</mn></msup><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>∗</mo><mn>4</mn><mo>=</mo><mn>15</mn><mo>∗</mo><mn>4</mn><mo>=</mo><mn>60</mn></mrow><annotation encoding=\"application/x-tex\">(2^4 - 1) * 4 = 15 * 4 = 60</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.064108em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">4</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">4</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">1</span><span class=\"mord\">5</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">4</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.64444em;vertical-align:0em;\"></span><span class=\"mord\">6</span><span class=\"mord\">0</span></span></span></span> 字节。头部长度。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>三次握手</p>\n<blockquote>\n<p>连接阶段：</p>\n<ol>\n<li>发送方发送：SYN、【初始的序号 x】、【窗口大小】</li>\n<li>接收方发送：【ACK：x+1】、【窗口大小】、SYN、【初始的序号 y】</li>\n<li>发送方发送：【ACK：y+1】</li>\n</ol>\n<p>连接：为了同步<strong>序号</strong>、<strong>窗口大小</strong>。以及其它选项的配置。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>四次挥手</p>\n<blockquote>\n<ol>\n<li>发送方：FIN</li>\n<li>接收方：【ACK 号】</li>\n<li>接收方：FIN</li>\n<li>发送方：【ACK 号】</li>\n<li>双方删除套接字</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>为什么 TCP 连接的时候是 3 次？2 次不可以吗？</p>\n<blockquote>\n<ol>\n<li>TCP 协议提供可靠的面向连接服务，因此需要确认机制，这样就 2 次握手了。</li>\n<li>TCP 提供全双工工作模式，双方可同时进行收发工作，以及双方都需要连接进行初始化，因此就 4 次了。</li>\n<li>有一端在确认的同时，可以合并连接操作，因此 3 次就行。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>为什么 TCP 连接的时候是 3 次，关闭的时候却是 4 次？</p>\n<blockquote>\n<ol>\n<li>TCP 协议提供可靠的面向连接服务，因此需要确认机制，这样就 2 次握手了。</li>\n<li>双方都需要断开，然后才能安全的删除套接字，因此，需要 4 次。</li>\n<li>以及断开操作和确认不能合并，是因为，一方断开是表明不再发送数据，但可能还有数据没接收完成；以及另外一端可能数据也还没发送完成。因此，另外一方在确认的同时，为了数据的完整，不能同时断开操作。等待另外一方发送完成后，才发送断开操作，因此双方断开操作不是同时的。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>为什么客户端发出第四次挥手的确认报文后要等 2MSL 的时间才能释放 TCP 连接？</p>\n<blockquote>\n<ol>\n<li>2 倍的 MSL，即报文的等待超时时间（Maximum Segment Lifetime）。</li>\n<li>客户端发出 ACK 后，考虑到如果 ACK 由于网络拥堵等原因，丢失了，服务器会重新发送 FIN；此时客户端如果经过 1MSL 关闭后，就会导致接收不到 FIN 了。这样是为了确保网络拥堵情况下，服务器重发 FIN 可以收到 FIN，然后再次发送 ACK。</li>\n<li>延长 1 个 MSL 是，确保服务器真正收到 ACK 包，不会因为没收到而重新发送 FIN，客户端关闭了，导致服务器错误。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>如果已经建立了连接，但是客户端突然出现故障了怎么办？</p>\n<blockquote>\n<ol>\n<li>服务器无法感知客户端是否故障，只不过是这段时间没有客户端的数据而已。</li>\n<li>但有 KeepAlive 机制，这不是 TCP 规范中的，但很多操作系统都实现了此机制。</li>\n<li>tcp_keepalive_time：默认 2 小时，空闲时长</li>\n<li>tcp_keepalive_intvl：探测包，间隔 75 s，在，空闲时长超时后，进行探测</li>\n<li>tcp_keepalive_probes：探测次数，默认 9 次，如果 9 次都没应答，就认为客户端已经遇到故障了。</li>\n</ol>\n<p>Linux 系统默认是不开启的，需要配置。</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">cat</span> /proc/sys/net/ipv4/tcp_keepalive_time</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">cat</span> /proc/sys/net/ipv4/tcp_keepalive_intvl</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">cat</span> /proc/sys/net/ipv4/tcp_keepalive_probes</pre></td></tr></table></figure><p>/etc/sysctl.conf 的全局配置，修改后，执行：sysctl -p 生效。</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token assign-left variable\">net.ipv4.tcp_keepalive_time</span><span class=\"token operator\">=</span><span class=\"token number\">7200</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token assign-left variable\">net.ipv4.tcp_keepalive_intvl</span><span class=\"token operator\">=</span><span class=\"token number\">75</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token assign-left variable\">net.ipv4.tcp_keepalive_probes</span><span class=\"token operator\">=</span><span class=\"token number\">9</span></pre></td></tr></table></figure><p>应用也可以开启，Tomcat，Netty 等。</p>\n<p><strong>如果不开启 KeepAlive，请求完成就断开操作了。</strong></p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>TCP 和 Http 中 Keep-Alive 的关系</p>\n<blockquote>\n<ol>\n<li>\n<p>HTTP 协议的 Keep-Alive 意图在于<strong>连接复用</strong>，同一个连接上串行方式传递请求 - 响应数据。</p>\n</li>\n<li>\n<p>TCP 的 Keep-Alive 机制意图在于存活、心跳，检测连接错误</p>\n</li>\n<li>\n<p>http 的 Keep-Alive 是在同一个 TCP 连接下，传输多个 http 请求，主要目的是为了连接复用。</p>\n</li>\n<li>\n<p>TCP 的 Keep-Alive 更纯粹，为了检测对方是否还存活。</p>\n</li>\n<li>\n<p>以及 Http 的 Keep-Alive 还有一个超时，超时后，服务器就断开 Keep-Alive DDOS 攻击。</p>\n</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>什么是 HTTP，HTTP 与 HTTPS 的区别</p>\n<blockquote>\n<ol>\n<li>HTTP 是应用层的协议，使用 TCP 协议传输 HTTP 报文。</li>\n<li>HTTP 传输的内容是明文，因此数据不安全；因此引入了安全机制，即结合 SSL 形成 HTTPS 协议，这样有了安全机制，传输的数据加密了，这样就保证了数据的安全。以及 SSL 需要向权威机构申请证书，这样就能保证站点的信任。</li>\n<li>以及防止篡改数据，保证数据的完整性。</li>\n</ol>\n<ul>\n<li>数据安全性</li>\n<li>站点信任</li>\n<li>防止篡改数据。</li>\n</ul>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>常用 HTTP 状态码</p>\n<blockquote>\n<ol>\n<li>1xxx 开头：消息，临时响应，即服务器已经接收，需要客户端进一步处理。</li>\n<li>2xxx 开头：成功，代表服务器已经接收请求。</li>\n<li>3xxx 开头：重定向，重定向在 Location 指定。</li>\n<li>4xxx 开头：客户端错误</li>\n<li>5xxx 开头：服务器错误</li>\n</ol>\n<ul>\n<li>101 Switch Protocols，Upgrade 头通知客户端使用新协议，例如切换新版本 2.0、WebSocket</li>\n<li>204 No Content，没有内容，例如 OPTIONS</li>\n<li>301 Moved Permanently，资源永久移动位置</li>\n<li>500 Internal Server Error</li>\n<li>502 Bad Gateway</li>\n<li>503 Service Unavailable</li>\n</ul>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>什么是对称加密与非对称加密</p>\n<blockquote>\n<ul>\n<li>对称加密：加密速度快，取决于密钥长度；加密 / 解密使用的都是同一个密钥。</li>\n<li>非对称加密：加密稍慢，加密使用公开的钥匙。解密使用私有的钥匙。私钥不公开，因此比较安全。</li>\n</ul>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>什么是 HTTP2</p>\n<blockquote>\n<ol>\n<li>http 有几个版本：1.0，1.1， 2.0</li>\n<li>2.0 版本新增：</li>\n</ol>\n<ul>\n<li>多路复用：同一连接，可以并发发送多个请求</li>\n<li>首部压缩：HPACK 算法对 header 的数据进行压缩。</li>\n<li>服务端推送：支持把客户端需要的资源一起推送到客户端。</li>\n</ul>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>Session、Cookie 和 Token 的主要区别</p>\n<blockquote>\n<ol>\n<li>Session 保存在服务器</li>\n<li>Cookie 保存在客户端</li>\n<li>Token 是用户身份的标识，token 可以由：uid（用户身份）+ 时间戳 + sign（由服务器签名，因此解决信任问题）</li>\n</ol>\n<p>session，如果用户访问量很大，session 需要储存，导致服务器压力很大。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>Servlet 是线程安全的吗</p>\n<blockquote>\n<p>Servlet 不是线程安全的。</p>\n<p>tomcat 模型：<br />\n用户发起请求，tomcat 从线程池中取出线程，然后找到请求对应的 Servlet 对象，进行初始化，然后调用 service 方法。</p>\n<p>Servlet 是单例，因此，如果多个线程都调用同一个 Servlet 对象，就可能会导致线程问题。</p>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>Servlet 接口中有哪些方法及 Servlet 生命周期探秘</p>\n<blockquote>\n<p>方法：</p>\n<figure class=\"highlight java\"><figcaption data-lang=\"java\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">package</span> <span class=\"token namespace\">javax<span class=\"token punctuation\">.</span>servlet</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">import</span> <span class=\"token import\"><span class=\"token namespace\">java<span class=\"token punctuation\">.</span>io<span class=\"token punctuation\">.</span></span><span class=\"token class-name\">IOException</span></span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">public</span> <span class=\"token keyword\">interface</span> <span class=\"token class-name\">Servlet</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">void</span> <span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">ServletConfig</span> var1<span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">ServletException</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token class-name\">ServletConfig</span> <span class=\"token function\">getServletConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">void</span> <span class=\"token function\">service</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">ServletRequest</span> var1<span class=\"token punctuation\">,</span> <span class=\"token class-name\">ServletResponse</span> var2<span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">ServletException</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">IOException</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token class-name\">String</span> <span class=\"token function\">getServletInfo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">void</span> <span class=\"token function\">destroy</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>生命周期：</p>\n<ol>\n<li>容器调用 init 初始化 Servlet 对象。</li>\n<li>请求到达后，执行 service，然后根据请求方法，执行 doGet 或 doPost</li>\n<li>服务器关闭后或项目卸载后，服务器调用 destroy 销毁对象。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz essay\">\n<p>如果客户端禁止 cookie 能实现 session 还能用吗？</p>\n<blockquote>\n<ol>\n<li>\n<p>session 实现的前提是，客户端有储存 sessionId 的能力；</p>\n</li>\n<li>\n<p>客户端如何携带 sessionId。</p>\n</li>\n<li>\n<p>客户端禁用 cookie，那 localStorage 和 sessionStorage 可以储存。</p>\n</li>\n<li>\n<p>携带方式，可以是 url，头部。因此可以通过 url，或者自定义一个头部字段</p>\n</li>\n</ol>\n</blockquote>\n</li>\n</ol>\n<h1 id=\"试题\"><a class=\"anchor\" href=\"#试题\">#</a> 试题</h1>\n<ol>\n<li class=\"quiz fill\">\n<p>网络协议主要要素为<span class=\"gap\">语法</span>、<span class=\"gap\">语义</span>、<span class=\"gap\">同步</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>一座大楼内的一个计算机网络系统，属于<span class=\"gap\"> LAN（Local area network）局域网</span>。</p>\n</li>\n<li class=\"quiz multi\">\n<p>随着电信和信息技术的发展，国际上出现了所谓 “三网融合” 的趋势，下列属于三网之一的是：</p>\n<ul class=\"options\">\n<li class=\"correct\">传统电信网</li>\n<li class=\"correct\">计算机网</li>\n<li class=\"correct\">有线电视网</li>\n<li>卫星通信网</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>通信系统必须具备的三个基本要素是</p>\n<ul class=\"options\">\n<li>终端、电缆、计算机</li>\n<li>信号发生器、通信线路、信号接收设备</li>\n<li class=\"correct\">信源、通信媒体、信宿</li>\n<li>终端、通信设施、接收设备</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>计算机网络通信系统是</p>\n<ul class=\"options\">\n<li>电信号传输系统</li>\n<li>文字通信系统</li>\n<li>信号通信系统</li>\n<li class=\"correct\">数据通信系统</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>常用的传输介质中，带宽最宽、信号传输衰减最小、抗干扰能力最强的一类传输介质是</p>\n<ul class=\"options\">\n<li class=\"correct\">光纤</li>\n<li>双绞线</li>\n<li>同轴电缆</li>\n<li>无线信道</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 OSI 七层结构模型中，处于数据链路层与运输层之间的是</p>\n<ul class=\"options\">\n<li>物理层</li>\n<li class=\"correct\">网络层</li>\n<li>会话层</li>\n<li>表示层</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>数据解封装的过程是</p>\n<ul class=\"options\">\n<li>段 — 包 — 帧 — 流 — 数据</li>\n<li class=\"correct\">流 — 帧 — 包 — 段 — 数据</li>\n<li>数据 — 包 — 段 — 帧 — 流</li>\n<li>数据 — 段 — 包 — 帧 — 流</li>\n</ul>\n<blockquote>\n<p>信号流 --&gt; 数据流 --&gt; 数据帧 --&gt; IP 包 --&gt; TCP 分组 --&gt; 数据</p>\n</blockquote>\n</li>\n<li class=\"quiz\">\n<p>完成路径选择功能是在 OSI 模型的</p>\n<ul class=\"options\">\n<li>物理层</li>\n<li>数据链路层</li>\n<li class=\"correct\">网络层</li>\n<li>运输层</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 OSI 中，完成整个网络系统内连接工作，为上一层提供整个网络范围内两个终端用户之间数据传输通路工作的是</p>\n<ul class=\"options\">\n<li>物理层</li>\n<li>数据链路层</li>\n<li class=\"correct\">网络层</li>\n<li>运输层</li>\n</ul>\n<blockquote>\n<p><strong>注意</strong>：<strong>为上一层</strong>提供整个网络范围内两个终端用户之间数据传输通路，题目不是问这个，而是前半段；<strong>因此不是运输层。</strong></p>\n</blockquote>\n</li>\n<li class=\"quiz\">\n<p>在 OSI 中，为实现有效、可靠数据传输，必须对传输操作进行严格的控制和管理，完成这项工作的层次是</p>\n<ul class=\"options\">\n<li>物理层</li>\n<li class=\"correct\">数据链路层   </li>\n<li>网络层</li>\n<li>运输层</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>T1 载波的数据传输率为</p>\n<ul class=\"options\">\n<li>1Mbps</li>\n<li>10Mbps</li>\n<li>2.048Mbps</li>\n<li class=\"correct\">1.544Mbps</li>\n</ul>\n<blockquote>\n<p>人的话音信道在 4Mhz 之内，根据奈奎斯特采样定理按照 2 倍 8MHz 采样，并 128 级量化，即<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mn>2</mn><mn>7</mn></msup></mrow><annotation encoding=\"application/x-tex\">2^7</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8141079999999999em;vertical-align:0em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">7</span></span></span></span></span></span></span></span></span></span></span>，用 7 个二进制 (7bit) 来表示一个采样（一个语音帧），每秒钟的产生的二进制数据量为 56kb, 计算公式：<br />\n<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mfrac><mrow><mn>1</mn><mi>s</mi></mrow><mrow><mn>7</mn><mi>b</mi><mi>i</mi><mi>t</mi><mo>∗</mo><mn>8</mn><mi>M</mi><mi>H</mi><mi>z</mi></mrow></mfrac><mo>=</mo><mn>56</mn><mi>K</mi><mi>b</mi><mi>p</mi><mi>s</mi></mrow><annotation encoding=\"application/x-tex\">\\frac{1s}{7bit * 8MHz} = 56Kbps</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.190108em;vertical-align:-0.345em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.845108em;\"><span style=\"top:-2.6550000000000002em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">7</span><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\">i</span><span class=\"mord mathnormal mtight\">t</span><span class=\"mbin mtight\">∗</span><span class=\"mord mtight\">8</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.10903em;\">M</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.08125em;\">H</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.04398em;\">z</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span><span class=\"mord mathnormal mtight\">s</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\">5</span><span class=\"mord\">6</span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">K</span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">s</span></span></span></span></p>\n</blockquote>\n<blockquote>\n<p>在实际编码中每一个采样中还会加入一个信令位，即 8bit 组成一个通信信道。但通信介质（电话线）的带宽远大于一个信道，所以采用多路复用技术，将 24 个话音信道组成一组，即 T1 信道，最后加入一个帧同步，这样每一帧则变成了 193bit，计算公式：<br />\n<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>8</mn><mi>b</mi><mi>i</mi><mi>t</mi><mo>∗</mo><mn>24</mn><mo>+</mo><mn>1</mn><mi>b</mi><mi>i</mi><mi>t</mi><mo>=</mo><mn>193</mn><mi>b</mi><mi>i</mi><mi>t</mi></mrow><annotation encoding=\"application/x-tex\">8bit * 24 + 1bit = 193bit</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord\">8</span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.72777em;vertical-align:-0.08333em;\"></span><span class=\"mord\">2</span><span class=\"mord\">4</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord\">1</span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord\">1</span><span class=\"mord\">9</span><span class=\"mord\">3</span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">t</span></span></span></span></p>\n</blockquote>\n<blockquote>\n<p>由取样频率 8MHz 可知，取样周期为 125us，则可知 T1 信道的比特率为：<br />\n<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mfrac><mrow><mn>193</mn><mi>b</mi><mi>i</mi><mi>t</mi></mrow><mrow><mn>125</mn><mi>u</mi><mi>s</mi></mrow></mfrac><mo>=</mo><mn>1.544</mn><mi>M</mi><mi>b</mi><mi>p</mi><mi>s</mi></mrow><annotation encoding=\"application/x-tex\">\\frac{193bit}{125us} = 1.544 Mbps</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.2251079999999999em;vertical-align:-0.345em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8801079999999999em;\"><span style=\"top:-2.6550000000000002em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span><span class=\"mord mtight\">2</span><span class=\"mord mtight\">5</span><span class=\"mord mathnormal mtight\">u</span><span class=\"mord mathnormal mtight\">s</span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.394em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span><span class=\"mord mtight\">9</span><span class=\"mord mtight\">3</span><span class=\"mord mathnormal mtight\">b</span><span class=\"mord mathnormal mtight\">i</span><span class=\"mord mathnormal mtight\">t</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8888799999999999em;vertical-align:-0.19444em;\"></span><span class=\"mord\">1</span><span class=\"mord\">.</span><span class=\"mord\">5</span><span class=\"mord\">4</span><span class=\"mord\">4</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mord mathnormal\">b</span><span class=\"mord mathnormal\">p</span><span class=\"mord mathnormal\">s</span></span></span></span></p>\n</blockquote>\n<blockquote>\n<p>T1 载波是专用电话连接、时分多路数字传输设施<br />\n T1 载波的数据速率是 1.544Mbps，<br />\nE1 载波的数据速率是 2.048Mbps，<br />\nE2 载波数据速率为 8.448Mbps，<br />\nE3 载波数据速率为 34.368Mbps，<br />\nE4 载波数据速率为 139.24Mbps，<br />\nE5 载波数据速率为 565.148Mbps。</p>\n</blockquote>\n</li>\n<li class=\"quiz\">\n<p>若网络形状是由站点和连接站点的链路组成的一个闭合环，则称这种拓扑结构为</p>\n<ul class=\"options\">\n<li>星形拓扑</li>\n<li>总线拓扑</li>\n<li class=\"correct\">环形拓扑</li>\n<li>树形拓扑</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在计算机网络中，所有的计算机均连接到一条通信传输线路上，在线路两端连有防止信号反射的装置。 这种连接结构被称为</p>\n<ul class=\"options\">\n<li class=\"correct\">总线结构</li>\n<li>环型结构</li>\n<li>星型结构</li>\n<li>网状结构</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>报文交换技术说法不正确的是</p>\n<ul class=\"options\">\n<li>报文交换采用的传送方式是 “存储一转发” 方式</li>\n<li>报文交换方式中数据传输的数据块其长度不限且可变</li>\n<li>报文交换可以把一个报文发送到多个目的地</li>\n<li class=\"correct\">报文交换方式适用于语音连接或交互式终端到计算机的连接</li>\n</ul>\n<blockquote>\n<p>C - 可通过广播地址，发送多个目的地</p>\n<ol>\n<li>电路交换：适用于电话语音等交互性强的，但不适合数据通信业务</li>\n<li>报文交换：在节点采用储存转发方式</li>\n<li>分组交换：在节点采用储存转发方式</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz\">\n<p>市话网在数据传输期间，在源节点与目的节点之间有一条利用中间节点构成的物理连接线路。这种市话网采用____技术</p>\n<ul class=\"options\">\n<li>报文交换</li>\n<li class=\"correct\">电路交换</li>\n<li>分组交换</li>\n<li>数据交换</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>世界上很多国家都相继组建了自己国家的公用数据网，现有的公用数据网大多采用</p>\n<ul class=\"options\">\n<li class=\"correct\">分组交换方式</li>\n<li>报文交换方式</li>\n<li>电路交换方式</li>\n<li>空分交换方式</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在计算机网络中，一般局域网的数据传输速率要比广域网的数据传输速率</p>\n<ul class=\"options\">\n<li class=\"correct\">高</li>\n<li>低</li>\n<li>相同</li>\n<li>不确定</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>电路交换是实现数据交换的一种技术，其特点是</p>\n<ul class=\"options\">\n<li>无呼叫损失</li>\n<li>不同速率的用户之间可以进行数据交换</li>\n<li class=\"correct\">信息延时短，且固定不变</li>\n<li>可以把一个报文发送到多个目的节点中</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>因特网在通信子网内实现数据报操作方式对端系统</p>\n<ul class=\"options\">\n<li>只提供数据报服务</li>\n<li>只提供虚电路服务</li>\n<li class=\"correct\">提供数据报和虚电路服务</li>\n<li>不提供服务</li>\n</ul>\n<blockquote>\n<p>虚拟电路：即节点和节点之间的连接，形成的通信通道，就类似电路一样；因此把这个通道形象地称为虚电路。</p>\n</blockquote>\n</li>\n<li class=\"quiz\">\n<p>以下各项中，不是数据报操作特点的是</p>\n<ul class=\"options\">\n<li>每个分组自身携带有足够的信息，它的传送是被单独处理的</li>\n<li>在整个传送过程中，不需建立虚电路</li>\n<li class=\"correct\">使所有分组按顺序到达目的端系统</li>\n<li>网络节点要为每个分组做出路由选择</li>\n</ul>\n<blockquote>\n<ol>\n<li>虚电路是分组技术中的；数据报使用真正的电路信号。</li>\n<li>分组交换，分组不一定按顺序到达目的端系统。</li>\n</ol>\n</blockquote>\n</li>\n<li class=\"quiz\">\n<p>在 OSI 中，物理层存在四个特性。其中，通信接口所用接线器的形状和尺寸属于</p>\n<ul class=\"options\">\n<li class=\"correct\">机械特性</li>\n<li>电气特性</li>\n<li>功能特性</li>\n<li>过程特性</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>对于 CSMA/CD 而言，为了确保发送站点在传输时能检测到可能存在的冲突，数据帧的传输时延至少要等于信号传播时延的</p>\n<ul class=\"options\">\n<li>1 倍</li>\n<li class=\"correct\">2 倍</li>\n<li>4 倍</li>\n<li>2.5 倍</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在同一个信道上的同一时刻，能够进行双向数据传送的通信方式是</p>\n<ul class=\"options\">\n<li>单工</li>\n<li>半双工</li>\n<li class=\"correct\">全双工</li>\n<li>上述三种均不是</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>采用全双工通信方式，数据传输的方向性结构为</p>\n<ul class=\"options\">\n<li class=\"correct\">可以在两个方向上同时传输</li>\n<li>出只能在一个方向上传输</li>\n<li>可以在两个方向上传输，但不能同时进位</li>\n<li>以上均不对</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>令牌总线的媒体访问控制方法是由___定义的。</p>\n<ul class=\"options\">\n<li>IEEE 802.2</li>\n<li>IEEE 802.3</li>\n<li class=\"correct\">IEEE 802.4</li>\n<li>IEEE 802.5</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在中继系统中，中继器处于</p>\n<ul class=\"options\">\n<li class=\"correct\">物理层</li>\n<li>数据链路层</li>\n<li>网络层</li>\n<li>高层</li>\n</ul>\n<blockquote>\n<p>中继系统，如集线器，更多的是信号中继，不像交换机等，有进行拆包，检测；集线器更多的是电路技术。</p>\n</blockquote>\n</li>\n<li class=\"quiz\">\n<p>下列只能简单再生信号的设备是</p>\n<ul class=\"options\">\n<li>网卡</li>\n<li>网桥</li>\n<li class=\"correct\">中继器</li>\n<li>路由器</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>互联网主要由一系列的组件和技术构成，其网络协议核心是</p>\n<ul class=\"options\">\n<li>ISP</li>\n<li>PPP</li>\n<li class=\"correct\">TCP/IP</li>\n<li>HTTP</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在数字通信中广泛采用 CRC 循环冗余码的原因是 CRC 可以</p>\n<ul class=\"options\">\n<li>检测出一位差错</li>\n<li>检测并纠正一位差错</li>\n<li class=\"correct\">检测出多位突发性差错</li>\n<li>检测并纠正多位突发性差错</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在计算机网络通信系统中，一般要求误码率低于</p>\n<ul class=\"options\">\n<li>10-4</li>\n<li>10-5</li>\n<li class=\"correct\">10-6</li>\n<li>10-7</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 10 Base T 的以太网中，使用双绞线作为传输介质，最大的网段长度是</p>\n<ul class=\"options\">\n<li>2000m</li>\n<li>500m</li>\n<li>185m</li>\n<li class=\"correct\">100m</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>同轴电缆与双绞线相比，同轴电缆的抗干扰能力</p>\n<ul class=\"options\">\n<li>弱</li>\n<li>一样</li>\n<li class=\"correct\">强</li>\n<li>不能确定</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>IEEE802.3 标准是</p>\n<ul class=\"options\">\n<li>逻辑链路控制</li>\n<li class=\"correct\">CSMA/CD 访问方法和物理层规范</li>\n<li>令牌总线访问方法和物理层规范</li>\n<li>令牌环网访问方法和物理层规范</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>局域网具有的几种典型的拓扑结构中，一般不含</p>\n<ul class=\"options\">\n<li>星型</li>\n<li>环型</li>\n<li>总线型</li>\n<li class=\"correct\">全连接网型</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>为采用拨号方式联入 Internet 网络，____是不必要的</p>\n<ul class=\"options\">\n<li>电话线</li>\n<li>一个 MODEM</li>\n<li>一个 Internet 账号</li>\n<li class=\"correct\">一台打印机</li>\n</ul>\n</li>\n<li class=\"quiz multi\">\n<p>计算机网络中，分层和协议的集合称为计算机网络的____。目前应用最广泛的是____。</p>\n<ul class=\"options\">\n<li>组成结构</li>\n<li>参考模型</li>\n<li class=\"correct\">体系结构</li>\n<li>基本功能</li>\n<li>SNA</li>\n<li>MAP/TOP</li>\n<li class=\"correct\">TCP/IP</li>\n<li>X.25</li>\n<li>ISO／OSI</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 OSI 的七层参考模型中，工作在第三层以上的网间连接设备是</p>\n<ul class=\"options\">\n<li>集线器</li>\n<li class=\"correct\">网关</li>\n<li>网桥</li>\n<li>中继器</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>从通信协议的角度来看，路由器是在哪个层次上实现网络互联</p>\n<ul class=\"options\">\n<li>物理层</li>\n<li>链路层</li>\n<li class=\"correct\">网络层</li>\n<li>传输层</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>Internet 的网络层含有四个重要的协议，分别为</p>\n<ul class=\"options\">\n<li>IP，ICMP，ARP，UDP</li>\n<li>TCP，ICMP，UDP，ARP</li>\n<li class=\"correct\">IP，ICMP，ARP，RARP</li>\n<li>UDP，IP，ICMP，RARP</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>IP 协议是无连接的，其信息传输方式是</p>\n<ul class=\"options\">\n<li>点对点</li>\n<li class=\"correct\">数据报</li>\n<li>广播</li>\n<li>虚电路</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>TCP/IP 体系结构中的 TCP 和 IP 所提供的服务分别为</p>\n<ul class=\"options\">\n<li>链路层服务和网络层服务</li>\n<li>网络层服务和运输层服务</li>\n<li>运输层服务和应用层服务</li>\n<li class=\"correct\">运输层服务和网络层服务</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>IP 地址是一个 32 位的二进制，它通常采用点分</p>\n<ul class=\"options\">\n<li>二进制数表示</li>\n<li>八进制数表示</li>\n<li class=\"correct\">十进制数表示</li>\n<li>十六进制数表示</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 IP 地址方案中，159.226.181.1 是一个</p>\n<ul class=\"options\">\n<li>A 类地址</li>\n<li class=\"correct\">B 类地址</li>\n<li>C 类地址</li>\n<li>D 类地址</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>把网络 202.112.78.0 划分为多个子网（子网掩码是 255.255.255.192），则每个子网中可用的主机地址数是</p>\n<ul class=\"options\">\n<li>254</li>\n<li>128</li>\n<li>124</li>\n<li class=\"correct\">62</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>TCP/IP 网络中常用的距离矢量路由协议是</p>\n<ul class=\"options\">\n<li>ARP</li>\n<li>ICMP</li>\n<li>OSPF</li>\n<li class=\"correct\">RIP</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 TCP/IP 协议簇中，TCP、UDP 协议工作在</p>\n<ul class=\"options\">\n<li>应用层</li>\n<li class=\"correct\">传输层</li>\n<li>网络互联层</li>\n<li>网络接口层</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 OSI 网络结构中，HTTP\\DHCP 协议工作在</p>\n<ul class=\"options\">\n<li class=\"correct\">应用层</li>\n<li>传输层</li>\n<li>网络互联层</li>\n<li>网络接口层</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>下面协议中，用于 WWW 传输控制的是</p>\n<ul class=\"options\">\n<li>URL</li>\n<li>SMTP</li>\n<li class=\"correct\">HTTP</li>\n<li>HTML</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>域名服务器上存放有 Internet 主机的</p>\n<ul class=\"options\">\n<li>域名</li>\n<li>IP 地址</li>\n<li class=\"correct\">域名和 IP 地址</li>\n<li>E-mail 地址</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 Internet 域名体系中，域的下面可以划分子域，各级域名用圆点分开，按照</p>\n<ul class=\"options\">\n<li>从左到右越来越小的方式分 4 层排列</li>\n<li>从左到右越来越小的方式分多层排列</li>\n<li>从右到左越来越小的方式分 4 层排列</li>\n<li class=\"correct\">从右到左越来越小的方式分多层排列</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>在 Internet/Intranet 中，不需要为用户设置帐号和口令的服务是</p>\n<ul class=\"options\">\n<li>WWW</li>\n<li>FTP</li>\n<li>E-mail</li>\n<li class=\"correct\">DNS</li>\n</ul>\n</li>\n<li class=\"quiz\">\n<p>下面协议中，用于电子邮件 Email 传输控制的是</p>\n<ul class=\"options\">\n<li>SNMP</li>\n<li class=\"correct\">SMTP</li>\n<li>HTTP</li>\n<li>HTML</li>\n</ul>\n</li>\n<li class=\"quiz fill\">\n<p>世界最早投入运行的计算机网络是<span class=\"gap\"> ARPANET</span></p>\n</li>\n<li class=\"quiz fill\">\n<p>计算机网络的体系结构是一种<span class=\"gap\">分层</span>结构</p>\n</li>\n<li class=\"quiz fill\">\n<p>OSI 参考模型采用了<span class=\"gap\"> 7</span> 层的体系结构</p>\n</li>\n<li class=\"quiz fill\">\n<p>串行数据通信的方向性结构有三种，即<span class=\"gap\">单工</span>、<span class=\"gap\">半双工</span>和<span class=\"gap\">全双工</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>因特网提供服务所采用的模式是<span class=\"gap\">客户端 / 服务器</span></p>\n</li>\n<li class=\"quiz fill\">\n<p>按照实际的数据传送技术，交换网络又可分为电路交换网、<span class=\"gap\">报文交换网</span>和<span class=\"gap\">分组交换网</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>两种最常使用的多路复用技术是：<span class=\"gap\">频分多路复用</span>和<span class=\"gap\">时分多路复用</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>当数据报在物理网络中进行传输时，IP 地址被转换成<span class=\"gap\">物理</span>地址。</p>\n</li>\n<li class=\"quiz fill\">\n<p>用电路交换技术完成的数据传输要经历<span class=\"gap\">电路建立</span>、<span class=\"gap\">数据传输</span>和<span class=\"gap\">电路拆除</span>过程。</p>\n</li>\n<li class=\"quiz fill\">\n<p>局域网中所使用的双绞线分成两类，即<span class=\"gap\">屏蔽双绞线</span>和<span class=\"gap\">非屏蔽双绞线</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>计算机网络中常用的三种有线媒体是<span class=\"gap\">同轴电缆</span>、<span class=\"gap\">双绞线</span>和<span class=\"gap\">光纤</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>在 IEEE802 局域网体系结构中，数据链路层被细化成<span class=\"gap\"> LLC 逻辑链路控制子层</span>和<span class=\"gap\"> MAC 介质访问控制子层</span>两层。</p>\n</li>\n<li class=\"quiz fill\">\n<p>T1 系统的传输速率为<span class=\"gap\"> 1.544Mbps</span>，E1 系统的数据传输速率为<span class=\"gap\"> 2.048Mbps</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>曼彻斯特编码是一种同步方式为<span class=\"gap\">自同步</span>的编码方案。</p>\n</li>\n<li class=\"quiz fill\">\n<p>在计算机的通信子网中，其操作方式有两种，它们是面向连接的<span class=\"gap\">虚电路</span>和无连接的<span class=\"gap\">数据报</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>运输层的运输服务有两大类：<span class=\"gap\">面向连接</span>的服务和<span class=\"gap\">无连接</span>的服务。</p>\n</li>\n<li class=\"quiz fill\">\n<p>TCP 在 IP 的基础上，提供端到端的<span class=\"gap\">面向连接</span>的可靠传输。</p>\n</li>\n<li class=\"quiz fill\">\n<p>子网掩码的作用是<span class=\"gap\">判断两台主机是否在同一子网中</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>标准的 B 类 IP 地址使用<span class=\"gap\"> 16</span> 位二进制数表示网络号。</p>\n</li>\n<li class=\"quiz fill\">\n<p>在 TCP/IP 层次模型的网络层中包括的协议主要有<span class=\"gap\"> IP</span>、<span class=\"gap\">ICMP</span>、<span class=\"gap\">ARP</span> 及 <span class=\"gap\">RARP</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>32 位全为 1 (255.255.255.255) 的 IP 地址叫做<span class=\"gap\">有限广播地址</span>，用于本网广播。</p>\n</li>\n<li class=\"quiz fill\">\n<p>如果路由表发生错误，数据报可能进入循环路径，无休止地在网络中流动。利用 IP 报头中的<span class=\"gap\">生存周期 / TTL</span> 可以防止这一情况的发生。</p>\n</li>\n<li class=\"quiz fill\">\n<p>在 TCP/IP 层次模型中运输层相对应的主要协议有<span class=\"gap\"> TCP（传输控制协议）</span>和<span class=\"gap\"> UDP（用户数据报协议）</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>到达通信子网中某一部分的分组数量过多，使得该部分乃至整个网络性能下降的现象，称为<span class=\"gap\">拥堵</span>现象。</p>\n</li>\n<li class=\"quiz fill\">\n<p>域名系统 DNS 是一个<span class=\"gap\">分布式数据库</span>系统。</p>\n</li>\n<li class=\"quiz fill\">\n<p>WWW 上的每一个网页都有一个独立的地址，这些地址称为<span class=\"gap\">统一资源定位器</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>在 WWW 中，使用统一资源定位器 URL 来唯一地标识和定位因特网中的资源，它由三部分组成：<span class=\"gap\">协议</span>、<span class=\"gap\">主机地址（域名）</span>、<span class=\"gap\">文件路径名</span>。</p>\n</li>\n<li class=\"quiz fill\">\n<p>支持在电子邮件中传输汉字信息的协议是<span class=\"gap\"> MIME</span>。</p>\n</li>\n</ol>\n",
            "tags": [
                "network",
                "network"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2020/03/31/category/network/%E7%BD%91%E7%BB%9C%E6%98%AF%E6%80%8E%E6%A0%B7%E8%BF%9E%E6%8E%A5%E7%9A%84-%E5%85%B6%E4%BA%8C/",
            "url": "https://blog.ceciljxsu.icu/2020/03/31/category/network/%E7%BD%91%E7%BB%9C%E6%98%AF%E6%80%8E%E6%A0%B7%E8%BF%9E%E6%8E%A5%E7%9A%84-%E5%85%B6%E4%BA%8C/",
            "title": "网络是怎样连接的-其二",
            "date_published": "2020-03-31T06:09:29.000Z",
            "content_html": "<h1 id=\"电信号传输-tcpip-数据\"><a class=\"anchor\" href=\"#电信号传输-tcpip-数据\">#</a> 电信号传输 TCP/IP 数据</h1>\n<h2 id=\"协议栈\"><a class=\"anchor\" href=\"#协议栈\">#</a> 协议栈</h2>\n<ol>\n<li>TCP、UDP、ICMP</li>\n<li>IP、ARP</li>\n</ol>\n<p>一般来说，浏览器、邮件等应用程序使用 TCP 协议；DNS 查询这种收发较短的控制数据的时候则使用 UDP。</p>\n<ul>\n<li>ICMP 用于告知网络包传送过程中产生的错误和各种控制信息</li>\n<li>ARP 用于根据 IP 地址查询 MAC 地址</li>\n</ul>\n<h3 id=\"套接字的实体\"><a class=\"anchor\" href=\"#套接字的实体\">#</a> 套接字的实体</h3>\n<p>套接字是抽象概念，那它的实体代表什么呢？</p>\n<p>在协议栈内部，有一块存放控制信息的内存空间，记录了用于通信操作的控制信息。例如：对象的 IP 地址、端口号、通信操作的进行状态等。</p>\n<h3 id=\"查看套接字信息\"><a class=\"anchor\" href=\"#查看套接字信息\">#</a> 查看套接字信息</h3>\n<p>Windows 下：</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">netstat</span> <span class=\"token parameter variable\">-ano</span></pre></td></tr></table></figure><figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Proto   Local Address   Foreign Address  State       PID</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>TCP     0.0.0.0:135     0.0.0.0:0        LISTENING   984</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>TCP     10.10.1.16:1031 10.10.1.80:139   ESTABLISHED 4</pre></td></tr></table></figure><p>使用协议、本地 IP 和端口、对方的 IP 和端口、通信状态、进程编号</p>\n<p>LISTENING 表明是在等待被连接，因此 Foreign Address 还不知道。本地的 IP 也还不知道。</p>\n<p>ESTABLISHED 表明已经建立连接，可以进行通信了。</p>\n<h3 id=\"连接的意义\"><a class=\"anchor\" href=\"#连接的意义\">#</a> 连接的意义</h3>\n<p>将本身的 IP 和端口告诉对方，这样才相互知道双方的 IP，才能建立通道，进行通信。</p>\n<p>并不像网线的连接概念；网线是一直连接的，并没有断开。</p>\n<h3 id=\"负责保存控制信息的头部\"><a class=\"anchor\" href=\"#负责保存控制信息的头部\">#</a> 负责保存控制信息的头部</h3>\n<p>每次通信都需要这些控制信息，因此进行通信时，这些控制信息都放在网络包的开头。</p>\n<p>TCP 头部结构：</p>\n<ol>\n<li>发送方端口号（2 字节）、接收方端口号（2 字节）</li>\n<li>序号（4 字节）</li>\n<li>ACK（4 字节）</li>\n<li>数据偏移量（4 位）、保留（6 位）、控制位（6 位）、窗口（2 字节）</li>\n<li>校验和（2 字节）、紧急指针（2 字节）</li>\n<li>可选字段（可变长度，可有可无）</li>\n</ol>\n<p>解释：</p>\n<ol>\n<li>序号：发送数据的顺序编号</li>\n<li>ACK：接收数据的顺序编号</li>\n<li>数据偏移量：数据部分的起始位置，因为头部占用一定空间，也就是头部的长度。</li>\n<li>控制位：URG、ACK、PSH、RST、SYN、FIN</li>\n<li>窗口：接收方告知发送方窗口大小</li>\n<li>紧急指针：应急处理的数据位置</li>\n<li>可选字段，一般连接阶段使用，平时很少使用</li>\n</ol>\n<p>除了可选字段，前面已经占用 20 字节；而且头部最多可用 60 字节；因此：可选字段，最多只有 40 字节，而且是 4 的整数倍。</p>\n<h3 id=\"收发数据\"><a class=\"anchor\" href=\"#收发数据\">#</a> 收发数据</h3>\n<p>数据不会立即被发送出去的，有一个缓冲区。根据不同策略发送。</p>\n<p>立即发送可能会导致出现很多小的网络包，效率不高。</p>\n<ol>\n<li>立即发送，由应用层控制。</li>\n<li>缓冲区长度达到 MSS 或接近，才发送。</li>\n<li>计时器，达到一定时间后，发出去。</li>\n</ol>\n<p>浏览器这种会话类型的应用，需要立即发送，这样交互时间才降低。</p>\n<p>如果交互频率很低，缓冲区导致延时时间发送，因此需要计时器，到达时间，即使缓冲区没满，也需要发出了。</p>\n<h4 id=\"mtu-mss\"><a class=\"anchor\" href=\"#mtu-mss\">#</a> MTU、MSS</h4>\n<p>MTU：最大传输单元（Maximum Transmission Unit），一个网络包允许的最大长度，以太网中是 1500 字节。</p>\n<p>MSS：最大分段大小（Maximum Segment Siz），去掉头部，剩余真正的数据的长度。</p>\n<h4 id=\"拆分\"><a class=\"anchor\" href=\"#拆分\">#</a> 拆分</h4>\n<p>如果传输的数据很长，就需要按 MSS 进行拆分。每个分段，都加上 TCP 头部。</p>\n<h4 id=\"ack-确认网络包收到\"><a class=\"anchor\" href=\"#ack-确认网络包收到\">#</a> ACK 确认网络包收到</h4>\n<p>网络包组装好，就开始发送了，发送之后，还没有结束，还有一个确认的过程。</p>\n<p><strong>确认原理</strong><br />\n拆分的数据，会有一个序号。好处</p>\n<ol>\n<li>数据不会乱，有序，接收方能知道是否遗漏。</li>\n<li>能确认每个分段都收到。</li>\n</ol>\n<p>接收方收到一个网络包后，就将此序号，写入 TCP，以及 ACK 确认，然后发送给发送方。</p>\n<p>序号不是从 1 开始的，而是连接的时候，初始化阶段，是随机的一个值，从这个值开始累计。</p>\n<p>这样可以防止通信过程可预测，防止被攻击。</p>\n<h4 id=\"连接阶段\"><a class=\"anchor\" href=\"#连接阶段\">#</a> 连接阶段</h4>\n<p>因为是双向通信的，因此双方都有初始的序号，需要通知对方。</p>\n<p>连接阶段：</p>\n<ol>\n<li>发送方：发送，【初始的序号 x】、SYN</li>\n<li>接收方：发送，ACK、【ACK：x+1】、SYN、【初始的序号 y】</li>\n<li>发送方：发送，ACK、【ACK：y+1】</li>\n</ol>\n<p>这样，就能知道双方的初始的序号了。</p>\n<ul>\n<li>SYN + 初始的序号</li>\n<li>ACK + 确认序号</li>\n</ul>\n<h3 id=\"动态调整-ack-号的等待时间\"><a class=\"anchor\" href=\"#动态调整-ack-号的等待时间\">#</a> 动态调整 ACK 号的等待时间</h3>\n<p>当网络传输繁忙时就会发生拥堵，ACK 号返回就变慢。这时候就要延长等待 ACK 的时间了。否则会认为丢失了该网络包而重新传送。</p>\n<p>本来网络传输已经繁忙了，这时候出现不必要的重传，那加重网络的拥堵。</p>\n<p>ACK 号的返回，时间可能随机的，因此不能固定一个等待时间，需要动态的调整。</p>\n<p><strong>监测 ACK 号的返回时间，如果返回变慢了，则相应延长等待时间；相反地，如果返回时间变快了，则相应缩短等待时间。</strong></p>\n<h3 id=\"使用窗口有效管理-ack-号\"><a class=\"anchor\" href=\"#使用窗口有效管理-ack-号\">#</a> 使用窗口有效管理 ACK 号</h3>\n<p>每发送一个包就等待一个 ACK 号的方式是最简单的，但在等待这段时间什么也做不了，就很浪费了。</p>\n<p>因此引入滑动窗口。</p>\n<p>滑动窗口：发送一个包后，不等待 ACK 号返回，而是直接发送后续一系列包。这样就可以有效利用这段等待时间了。</p>\n<p>但不断发送一系列包，可能导致接收方处理不过来。</p>\n<ol>\n<li>首先，接收方要告诉发送方，自己最多能接收多少数据。</li>\n<li>发送方根据这个值，对数据进行发送操作。</li>\n<li>发送方发完了这个值的数量，就等待发送。</li>\n<li>接收方接收后，就确认 ACK 的时候，告知对方，自己目前新的、可用的大小。</li>\n<li>发送方接收到 ACK 后，得到对方的窗口大小，就可以继续根据窗口大小发送网络包。</li>\n</ol>\n<p><strong>TCP 调优的一个参数：窗口大小。</strong></p>\n<h3 id=\"ack-和窗口的合并\"><a class=\"anchor\" href=\"#ack-和窗口的合并\">#</a> ACK 和窗口的合并</h3>\n<p>如果每次 ACK 都发送，以及窗口需要更新，也独立发送网络包，这样就增加的网络包的数量。</p>\n<p>因此，接收方，并不马上发送 ACK 包，而是等待一段时间发送 ACK 包，可以连续处理多个包，然后发送最后一个 ACK 的包；因此可以减少网络包的数量。</p>\n<p>以及，窗口需要更新时，也可以在 ACK 包中携带，因此又可以减少因窗口更新而导致的网络包增加。</p>\n<p>这就是 ACK 和窗口更新的控制数据的合并。</p>\n<h3 id=\"断开连接\"><a class=\"anchor\" href=\"#断开连接\">#</a> 断开连接</h3>\n<p>数据发送完毕后，就可以断开连接了。</p>\n<p>协议栈允许任何一方先发起断开过程，因此断开顺序取决于应用本身。</p>\n<p>Web 服务器返回响应信息后，服务器先发起断开。</p>\n<ol>\n<li>服务器发送：FIN</li>\n<li>客户端发送：ACK</li>\n<li>客户端发送：FIN</li>\n<li>服务器发送：ACK</li>\n</ol>\n<p>这里为什么客户端发送 ACK 和 FIN 分开呢？</p>\n<p>因为服务器需要关闭，因此通知客户端；而客户端可能并不打算立即就断开本身，因此先发 ACK 确认自己收到对方的断开操作。然后根据本身再发送 FIN 通知对方，等待对方的确认。</p>\n<p>客户端可能这时候还没处理缓冲区的数据，因此不会在 ACK 的同时，立即断开，等待处理完成缓冲区的数据后，再发送 FIN 断开。</p>\n<h3 id=\"删除套接字\"><a class=\"anchor\" href=\"#删除套接字\">#</a> 删除套接字</h3>\n<p>套接字要在双方都发送 FIN 和确认 ACK 后，才删除套接字；这样可以防止误操作。</p>\n<p>如果对方提早删除套接字，则可能对方没收到 FIN 包，因此可能会重复发送 FIN 包。</p>\n<h3 id=\"总结\"><a class=\"anchor\" href=\"#总结\">#</a> 总结</h3>\n<p>连接阶段：</p>\n<ol>\n<li>发送方发送：SYN、【初始的序号 x】、【窗口大小】</li>\n<li>接收方发送：【ACK：x+1】、【窗口大小】、SYN、【初始的序号 y】</li>\n<li>发送方发送：【ACK：y+1】</li>\n</ol>\n<p>通信阶段：</p>\n<ol>\n<li>发送方：【序号】【数据】</li>\n<li>接收方：【ACK 号】【窗口】</li>\n</ol>\n<p>断开阶段：</p>\n<ol>\n<li>发送方：FIN</li>\n<li>接收方：【ACK 号】</li>\n<li>接收方：FIN</li>\n<li>发送方：【ACK 号】</li>\n<li>双方删除套接字</li>\n</ol>\n<p>TCP 模块需要底层的 IP 模块</p>\n<p>IP 模块负责添加如下两个头部：</p>\n<ul>\n<li>MAC 头部：以太网的头部，包含 MAC 地址</li>\n<li>IP 头部：IP 用的头部，包含 IP 地址。</li>\n</ul>\n<h2 id=\"ip-模块\"><a class=\"anchor\" href=\"#ip-模块\">#</a> IP 模块</h2>\n<p>无论要收发的包是控制包，还是数据包，IP 对各种类型的包的收发操作都是相同的。</p>\n<h3 id=\"ip-头部\"><a class=\"anchor\" href=\"#ip-头部\">#</a> IP 头部</h3>\n<ol>\n<li>版本号（4b）、头部长度（4b）、服务类型（1B）、总长度（2B）</li>\n<li>ID 号（2B）、标志（3b）、分片偏移量（13b）</li>\n<li>生存时间（1B）、协议号（1B）、头部校验和（2B）</li>\n<li>发送方 IP 地址（4B）</li>\n<li>接收方 IP 地址（4B）</li>\n<li>可选字段：可变长度</li>\n</ol>\n<p>解释：</p>\n<ol>\n<li>版本号：4，IPv4</li>\n<li>服务类型：包传输优先级，该字段比较模糊，DiffServ 规格重新定义</li>\n<li>总长度：IP 消息总长度</li>\n<li>ID 号：包的序列号，如果分片，则所有分片都有相同的 ID</li>\n<li>标志：仅 2 比特有效，即是否允许分片，以及当前是否为分片包</li>\n<li>分片偏移量：当前数据是第几个字节开始的</li>\n<li>生存时间：每经过一个路由器就减 1 ，直到 0 丢弃</li>\n<li>协议号：0x06 - TCP；0x11 - UDP；0x01 - ICMP</li>\n<li>校验和：现在不用了</li>\n</ol>\n<h3 id=\"网卡的选择\"><a class=\"anchor\" href=\"#网卡的选择\">#</a> 网卡的选择</h3>\n<p>接收方 IP 地址直接是对方的 IP 地址，但发送方如果有多个网卡，有多个 IP 地址，那应该选哪个呢？</p>\n<p>根据系统配置的路由表，匹配是否有相同子网下的 IP，因此使用此 IP，如果没有则使用默认的路由表</p>\n<h3 id=\"添加-mac-头部\"><a class=\"anchor\" href=\"#添加-mac-头部\">#</a> 添加 MAC 头部</h3>\n<ol>\n<li>接收方 MAC 地址（6 字节）</li>\n<li>发送方 MAC 地址（6 字节）</li>\n<li>以太类型（2 字节）</li>\n</ol>\n<p>类型：</p>\n<ol>\n<li>0000-05DC：IEEE 802.3</li>\n<li>0800：IP 协议</li>\n<li>0806：ARP 协议</li>\n<li>86DD：IPv6</li>\n</ol>\n<p>一般使用 0800 和 0806</p>\n<p>发送方，通过 IP 就可以知道是哪快网卡，因此可以直接知道 MAC 地址；</p>\n<p>而接收方，知道 IP 地址，但还未知对方的 MAC 地址；</p>\n<p>因此需要通过对方 IP 地址，查询对方的 MAC 地址。</p>\n<h3 id=\"arp-查询目标路由器的-mac-地址\"><a class=\"anchor\" href=\"#arp-查询目标路由器的-mac-地址\">#</a> ARP 查询目标路由器的 MAC 地址</h3>\n<p>ARP 利用广播，询问目标主机的 MAC 地址。</p>\n<p>查询到的目标主机的 MAC 地址，会缓存起来；下次查询时，可以直接获取。</p>\n<p>ARP 缓存删除比较简单粗暴，一般经过几分钟，所有缓存都清空。</p>\n<h3 id=\"为什么以太网的包需要-ip-模块来组装\"><a class=\"anchor\" href=\"#为什么以太网的包需要-ip-模块来组装\">#</a> 为什么以太网的包，需要 IP 模块来组装？</h3>\n<p>以太网的结构，应该由以太网来封装，但为什么由上层来封装呢？</p>\n<p><strong>因为由上层来封装，则可以实现各种类型的协议，IP 协议、ARP 协议等等；这样就不需要以太网层来考虑类型了，直接发送网络包即可。</strong></p>\n<h3 id=\"以太网基础知识\"><a class=\"anchor\" href=\"#以太网基础知识\">#</a> 以太网基础知识</h3>\n<h4 id=\"以太网结构的演变\"><a class=\"anchor\" href=\"#以太网结构的演变\">#</a> 以太网结构的演变</h4>\n<ol>\n<li><strong>10BASE5（以太网原型）</strong>\n<ul>\n<li>信号通过网线流过整个网络</li>\n</ul>\n</li>\n<li><strong>10BASE-T</strong>\n<ul>\n<li>信号通过中继式集线器扩散到整个网络。使用双绞线，以及使用中继式集线器替换骨干网线。因此，结构改变，但性质不变。</li>\n</ul>\n</li>\n<li><strong>交换式集线器</strong>\n<ul>\n<li>交换式集线器会根据接收方的 MAC 地址，将包发送到指定的目的地。因此，信号只会到达指定设备。</li>\n<li><strong>交换式集线器</strong>和<strong>中继式集线器</strong>结构一样，但信号发送方式不同。</li>\n</ul>\n</li>\n</ol>\n<p>以上三种的变迁，但以太网封装是不变的。</p>\n<h3 id=\"ip-包转换成电光信号传输\"><a class=\"anchor\" href=\"#ip-包转换成电光信号传输\">#</a> IP 包转换成电 / 光信号传输</h3>\n<h4 id=\"网卡\"><a class=\"anchor\" href=\"#网卡\">#</a> 网卡</h4>\n<p>不同厂商的网卡，需要不同的驱动，这集成于操作系统中了，因此可以直接使用。</p>\n<p><strong>网卡结构</strong><br />\n包含：MAC、缓冲区、ROM、PHY（MAU）、RJ-45 接口等</p>\n<p>ROM 储存全球唯一的 MAC 地址，代表此网卡的地址，厂商生产时，烧录进去的。</p>\n<p>网卡中的 MAC 地址由驱动读取，然后分配给 MAC 模块</p>\n<h4 id=\"网卡添加控制数据\"><a class=\"anchor\" href=\"#网卡添加控制数据\">#</a> 网卡添加控制数据</h4>\n<p>MAC 模块从网卡缓冲区中取出帧，然后头部添加报头和起始帧分界符，尾部添加帧校验序列（FCS），用于错误校验。</p>\n<p><strong>头部添加的是 1 和 0 的交替，56 bit。</strong></p>\n<p>这用于确定读取的时机：1 和 0 的交替，可以测量 1 到 0 这段时间，作为读取数据的间隔。</p>\n<p>起始帧分隔符是以 11 结尾的。</p>\n<ol>\n<li>报头（56 bit，1 和 0 交替）</li>\n<li>起始帧分隔符（8 bit，结尾是 11）：1010 1011</li>\n</ol>\n<p>起始帧分隔符（SFD）用于测量帧的起始位置</p>\n<p>电信号通过电压高低来确定 1 或 0，但如果是连续的电压，变化不大，那么从哪里划分数据呢？</p>\n<p>因此需要<strong>时钟信号</strong>。</p>\n<p>合并数据信号和时钟信号，合并的信号，容易读取数据。</p>\n<p>合并规则：</p>\n<ol>\n<li>高 + 高 = 低</li>\n<li>低 + 低 = 低</li>\n<li>高 + 低 = 高</li>\n<li>低 + 高 = 高</li>\n</ol>\n<p><strong>如果单独发送数据信号和时钟信号，网线较长时，导致传输数据信号和时钟信号产生时间差，时钟就会发生偏移。</strong></p>\n<p>因此数据信号需要叠加时钟信号，然后发送叠加的信号。</p>\n<p>因此，如果能知道发送方的时钟信号的周期，就能读取叠加信号。</p>\n<p><strong>通过统计一段时间，可以知道发送方时钟信号的周期，因此，报头的作用就是提供给接收方统计用的，统计出发送方的时钟周期，进而读取叠加信号的数据。</strong></p>\n<p>末尾的 FCS 也是用于检验因噪声导致信号紊乱导致的数据错误。</p>\n<h3 id=\"向集线器发送信号\"><a class=\"anchor\" href=\"#向集线器发送信号\">#</a> 向集线器发送信号</h3>\n<p>集线器是半双工的；交换机是全双工的。</p>\n<p>集线器可能会发生信号冲突，因此发送前，需要检测网线是否有其它设备发送。</p>\n<p><strong>MAC 模块将数据转成通用的电信号，然后由 PHY 或 MAU 模块发送出去。</strong></p>\n<p>转换成电信号的速率，即为传输速率。</p>\n<p><strong>PHY 会将电信号转成不同网线规格的信号。网线传输情况很复杂。有很多编码，这些不同编码导致发送的速率不同。</strong></p>\n<p>举例：4B/5B、曼彻斯特编码...</p>\n<p>PHY 还要检测线路是否已经有其它设备发送信号了。</p>\n<p>如果发生冲突，则通信终止，然后发送一段时间阻塞，即等待一段时间，然后再发送，如果再有冲突，则延长一倍等待时间，如果重试 10 次都冲突，就报告通信错误。</p>\n<p>全双工就不会发生信号冲突，也因此简单很多。</p>\n<h3 id=\"接收信号\"><a class=\"anchor\" href=\"#接收信号\">#</a> 接收信号</h3>\n<p>集线器半双工模式，设备发送的信号，连接同一个集线器的都接收到信号，因此所有设备都接收集线器上的信号。</p>\n<ol>\n<li>PHY 模块将解码电信号（取决于网线，以及编码），转成通用的电信号</li>\n<li>MAC 模块处理电信号，转成数字信息，然后放到缓冲区。到达 FCS 结尾，还要校验数据是否错误。错误就丢弃。</li>\n<li>FCS 校验没问题，就检查头部 MAC 接收地址，是否为本网卡的 MAC 地址，如果不匹配，则不是发给此网卡的，则抛弃。</li>\n<li>MAC 地址一致时，才返回到协议层，然后到应用层。</li>\n</ol>\n<p>网卡驱动程序也不是一直监控网卡的活动，因此网卡通过中断机制通知网卡驱动程序。</p>\n<p>网卡通过扩展总线的中断线路发送中断信号。中断线路连接 CPU，CPU 暂时挂起其它任务，然后切换到操作系统的中断程序。中断程序调用网卡驱动，然后通知到了网卡驱动，驱动程序就开始读取网卡数据。</p>\n<p>中断信号都有一个编号的。网卡安装时，就设置了一个中断编号，网卡的中断号和驱动程序中断号绑定起来。</p>\n<p>现代设备都是可以通过即插即用的方式，自动设置中断号，就不用手动设置了。</p>\n<h3 id=\"ip-模块到-tcp-模块\"><a class=\"anchor\" href=\"#ip-模块到-tcp-模块\">#</a> IP 模块到 TCP 模块</h3>\n<p>网卡驱动将数据交给协议栈处理。</p>\n<p>先由 IP 模块处理，如果接收方 IP 不匹配，则抛弃数据，客户端不做转发功能，以及，返回 ICMP 通知错误。</p>\n<p>ICMP 错误消息有很多种类。</p>\n<p>ICMP 包含在 IP 报文中</p>\n<p>以及增加 ICMP 头部信息</p>\n<ol>\n<li>类型（1 字节）、代码（1 字节）、校验和（2 字节）</li>\n<li>内容</li>\n</ol>\n<p>ping 使用 ICMP 协议类型的：8，0</p>\n<p>traceroute 使用 ICMP 协议</p>\n<h2 id=\"udp-协议的收发\"><a class=\"anchor\" href=\"#udp-协议的收发\">#</a> UDP 协议的收发</h2>\n<h3 id=\"不需要重发的-udp-更高效\"><a class=\"anchor\" href=\"#不需要重发的-udp-更高效\">#</a> 不需要重发的 UDP 更高效</h3>\n<p>TCP 复杂是由于要确保可靠，需要确保对方收到，没收到就要重发。</p>\n<p>但有些简单的包，没有分片，就只有一个包，因此，就算对方没收到，也只需重发此包即可。</p>\n<h3 id=\"udp-协议头部\"><a class=\"anchor\" href=\"#udp-协议头部\">#</a> UDP 协议头部</h3>\n<p>像 DNS 这种查询的只需要 1 个包就能解决。</p>\n<p>UDP 没有确认机制、窗口等，因此不需要建立、连接；只需要获取对方端口信息，就可以直接发送了。</p>\n<p>遇到错误的包，丢包，也不用处理。UDP 只管发送。</p>\n<ol>\n<li>发送方端口（2 字节）、接收方端口（2 字节）</li>\n<li>数据长度（2 字节）、校验和（2 字节）</li>\n</ol>\n<h3 id=\"udp-的使用场景\"><a class=\"anchor\" href=\"#udp-的使用场景\">#</a> UDP 的使用场景</h3>\n<p>音频和视频</p>\n<p>因为音频和视频要求时效性，如果掉帧了，播放就卡掉。但这时候再重传，也挽回不了画面卡掉的情况。因此就放弃了重传。</p>\n<p>产生少量的失真和卡顿，也是可以接受的；如果存在大量的这种情况，那即使重传也解决不了问题，而是要提高传输速率。</p>\n",
            "tags": [
                "network",
                "network"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2020/03/30/category/network/%E7%BD%91%E7%BB%9C%E6%98%AF%E6%80%8E%E6%A0%B7%E8%BF%9E%E6%8E%A5%E7%9A%84-%E5%85%B6%E4%B8%80/",
            "url": "https://blog.ceciljxsu.icu/2020/03/30/category/network/%E7%BD%91%E7%BB%9C%E6%98%AF%E6%80%8E%E6%A0%B7%E8%BF%9E%E6%8E%A5%E7%9A%84-%E5%85%B6%E4%B8%80/",
            "title": "网络是怎样连接的-其一",
            "date_published": "2020-03-30T06:09:29.000Z",
            "content_html": "<h1 id=\"浏览器访问资源\"><a class=\"anchor\" href=\"#浏览器访问资源\">#</a> 浏览器访问资源</h1>\n<h2 id=\"url\"><a class=\"anchor\" href=\"#url\">#</a> URL</h2>\n<p>统一资源定位符（Uniform Resource Locator）</p>\n<h3 id=\"格式\"><a class=\"anchor\" href=\"#格式\">#</a> 格式</h3>\n<h4 id=\"http-协议\"><a class=\"anchor\" href=\"#http-协议\">#</a> HTTP 协议</h4>\n<p><code>http://user:password@www.example.com:80/dir/file1.htm</code></p>\n<ol>\n<li>协议</li>\n<li>用户名、密码，<strong>可省略</strong></li>\n<li>web 服务器域名</li>\n<li>端口，<strong>可省略</strong></li>\n<li>文件路径名</li>\n</ol>\n<h4 id=\"ftp-协议\"><a class=\"anchor\" href=\"#ftp-协议\">#</a> FTP 协议</h4>\n<p><code>ftp://user:password@ftp.example.com:21/dir/file1.htm</code></p>\n<ol>\n<li>协议</li>\n<li>用户名、密码，<strong>可省略</strong></li>\n<li>FTP 服务器域名</li>\n<li>端口，<strong>可省略</strong></li>\n<li>文件路径名</li>\n</ol>\n<h4 id=\"本地文件\"><a class=\"anchor\" href=\"#本地文件\">#</a> 本地文件</h4>\n<p><code>file://localhost/c:/path/file1.zip</code></p>\n<ol>\n<li>协议</li>\n<li>计算机名，<strong>可省略</strong></li>\n<li>文件的路径名</li>\n</ol>\n<h4 id=\"电子邮件\"><a class=\"anchor\" href=\"#电子邮件\">#</a> 电子邮件</h4>\n<p><code>mailto:toUser@example.com</code></p>\n<h4 id=\"新闻\"><a class=\"anchor\" href=\"#新闻\">#</a> 新闻</h4>\n<p><code>news:comp.protocols.tcp-ip</code></p>\n<h2 id=\"生成-http-请求消息\"><a class=\"anchor\" href=\"#生成-http-请求消息\">#</a> 生成 HTTP 请求消息</h2>\n<p>请求信息</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>&lt;方法>&lt;空格>&lt;URI>&lt;空格>&lt;HTTP版本></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>&lt;字段名>:&lt;字段值></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>...</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>...</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&lt;空行></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&lt;消息体></pre></td></tr></table></figure><h2 id=\"http-响应信息\"><a class=\"anchor\" href=\"#http-响应信息\">#</a> HTTP 响应信息</h2>\n<p>响应信息</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>&lt;HTTP版本>&lt;空格>&lt;状态码>&lt;空格>&lt;响应描述></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>&lt;字段名>:&lt;字段值></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>...</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>...</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&lt;空行></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>&lt;消息体></pre></td></tr></table></figure><h1 id=\"dns-查询服务器-ip-地址\"><a class=\"anchor\" href=\"#dns-查询服务器-ip-地址\">#</a> DNS 查询服务器 IP 地址</h1>\n<h2 id=\"ip\"><a class=\"anchor\" href=\"#ip\">#</a> IP</h2>\n<h3 id=\"表示方式\"><a class=\"anchor\" href=\"#表示方式\">#</a> 表示方式</h3>\n<h4 id=\"点分十进制\"><a class=\"anchor\" href=\"#点分十进制\">#</a> 点分十进制</h4>\n<p>每 8 bit 用。分隔。</p>\n<p>10.11.12.13</p>\n<h4 id=\"子网掩码\"><a class=\"anchor\" href=\"#子网掩码\">#</a> 子网掩码</h4>\n<p>10.11.12.13/255.255.255.0</p>\n<h4 id=\"比特数的子网掩码\"><a class=\"anchor\" href=\"#比特数的子网掩码\">#</a> 比特数的子网掩码</h4>\n<p>10.11.12.13/<strong>24</strong></p>\n<p>前 24 位全为 1，剩余为 0，表示主机数。</p>\n<ol>\n<li>IP 可以得出网络号</li>\n<li>除了网络号，剩余的位数，继续用子网掩码划分</li>\n<li>子网掩码 + 网络号，得出子网号，剩余的才是这个子网的主机号。</li>\n</ol>\n<h4 id=\"代表整个子网\"><a class=\"anchor\" href=\"#代表整个子网\">#</a> 代表整个子网</h4>\n<p>10.11.12.<strong>0</strong>/24</p>\n<h4 id=\"子网内广播\"><a class=\"anchor\" href=\"#子网内广播\">#</a> 子网内广播</h4>\n<p>10.11.12.<strong>255</strong>/24</p>\n<h2 id=\"dns-解析\"><a class=\"anchor\" href=\"#dns-解析\">#</a> DNS 解析</h2>\n<p>DNS（Domain Name System）查询 IP 地址的操作，称为域名解析，负责执行此操作的为解析器。</p>\n<h3 id=\"查询条件\"><a class=\"anchor\" href=\"#查询条件\">#</a> 查询条件</h3>\n<ol>\n<li>域名</li>\n<li>Class：目前只固定 IN</li>\n<li>记录类型：A - 地址；MX - Mail eXchange</li>\n</ol>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>域名                   Class 记录类型 响应数据</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>www.lab.glasscom.com  IN     A      192.0.2.226</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>glasscom.com          IN     MX     10 mail.glasscom.com</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>mail.glasscom.com     IN     A      192.0.2.227</pre></td></tr></table></figure><p>邮箱还有一个优先级</p>\n<h3 id=\"域名分层\"><a class=\"anchor\" href=\"#域名分层\">#</a> 域名分层</h3>\n<p>使用英文句点来划分，靠右层级越高。</p>\n<p>例如： <code>www.lab.glasscom.com</code></p>\n<ul>\n<li>一级域名：com</li>\n<li>二级域名：glasscom</li>\n<li>三级、四级：lab、www</li>\n</ul>\n<h3 id=\"根域服务器\"><a class=\"anchor\" href=\"#根域服务器\">#</a> 根域服务器</h3>\n<p>它没有名字，如果要表示，就在域名最右边添加句点，例如：</p>\n<p><code>www.lab.glasscom.com.</code></p>\n<p>全球目前只有 13 台 根域服务器，这些都配置在主机中的。</p>\n<p>当然还有成千上万台镜像 DNS 服务器，会定时更新根域服务器的数据。</p>\n<h3 id=\"查找过程\"><a class=\"anchor\" href=\"#查找过程\">#</a> 查找过程</h3>\n<p><code>www.lab.glasscom.com.</code>  域名的查找过程</p>\n<ol>\n<li>从主机配置的 DNS 服务器查找；配置是系统 TCP/IP 自动配置好的，或者手动配置。</li>\n<li>查找不到了，再从最高级别查起，即根域或其镜像 DNS 服务器查找</li>\n<li>没有再从 com 的 DNS 服务器查找</li>\n<li>然后一级一级的查询，直到查询或到达最低级域名 DNS 为止。</li>\n</ol>\n<p>当然，DNS 服务器可能包含多级的域名注册信息，因此不用查询多次。以及 DNS 服务器有<strong>缓存</strong>。</p>\n<p>低级的域名都会注册到高级的域名服务器中。</p>\n<p>例如：一级域名 com、cn 等的域名都注册到根域服务器中。</p>\n<h3 id=\"dns-使用-tcp-还是-udp\"><a class=\"anchor\" href=\"#dns-使用-tcp-还是-udp\">#</a> DNS 使用 TCP 还是 UDP？</h3>\n<p>两者都使用：</p>\n<ol>\n<li>在局域网中使用 UDP</li>\n<li>在跨越较远的根服务器、一级等，用 TCP</li>\n</ol>\n<h2 id=\"委托协议栈发送信息\"><a class=\"anchor\" href=\"#委托协议栈发送信息\">#</a> 委托协议栈发送信息</h2>\n<p>得到对方的 IP 后，就可以委托系统的 Socket 库来收发数据。</p>\n<p>Socket 建立两者之间的通道，数据在通道中流动。</p>\n<p>流程：</p>\n<ol>\n<li>双方创建套接字（创建阶段）</li>\n<li>客户端连接服务器的套接字上（连接阶段）</li>\n<li>收发数据（通信阶段）</li>\n<li>断开管道并删除套接字（断开阶段）</li>\n</ol>\n<p>应用程序</p>\n<figure class=\"highlight plaintext\"><figcaption data-lang=\"plaintext\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>// DNS</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>&lt;内存地址> = gethostbyname(\"www.lab.glasscom.com\");</pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>// 创建阶段</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>&lt;描述符> = socket(&lt;IPv4>, &lt;流模式>, ...);</pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>// 连接阶段</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>connect(&lt;描述符>, &lt;服务器的 IP 地址和端口>, ...);</pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>// 通信阶段</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>write(&lt;描述符>, &lt;发送数据>, &lt;数据长度>);</pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>&lt;接收数据长度> = read(&lt;描述符>, &lt;接收缓冲区>, ...);</pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>// 断开阶段</pre></td></tr><tr><td data-num=\"16\"></td><td><pre>close(&lt;描述符>);</pre></td></tr></table></figure><h3 id=\"socket-socket-套接字区别\"><a class=\"anchor\" href=\"#socket-socket-套接字区别\">#</a> Socket、socket、套接字区别：</h3>\n<ul>\n<li>Socket 代表库，包含多种组件</li>\n<li>socket 指的是创建套接字的 socket 程序组件</li>\n<li>套接字：指的是双方创建的通道</li>\n</ul>\n<h3 id=\"创建阶段\"><a class=\"anchor\" href=\"#创建阶段\">#</a> 创建阶段</h3>\n<p>使用 socket 组件，创建套接字，协议栈会返回描述符号。</p>\n<p>描述符储存在内存中，就类似一个 ID，用于区分是哪个套接字。</p>\n<h3 id=\"连接阶段\"><a class=\"anchor\" href=\"#连接阶段\">#</a> 连接阶段</h3>\n<p>使用 connect 组件；需要指定描述符、服务器 IP 地址、端口号。</p>\n<p>IP 能识别到某台主机，但不知道对方的哪个套接字，因此需要端口号。</p>\n<p>端口号能识别到对方的某个套接字</p>\n<p>因此连接阶段，通过 IP 和端口号，能连接到对方主机的套接字，完成套接字的连接，形成通道。</p>\n<h3 id=\"为什么不使用套接字的描述符代表端口呢\"><a class=\"anchor\" href=\"#为什么不使用套接字的描述符代表端口呢\">#</a> 为什么不使用套接字的描述符代表端口呢？</h3>\n<p>因为描述符代表的是本机的套接字，是本机识别本机的套接字的；而对方的套接字无法知道。</p>\n<p>因此，使用双方约定好的端口号，作为对方的套接字的识别。</p>\n<h3 id=\"通信阶段传递消息\"><a class=\"anchor\" href=\"#通信阶段传递消息\">#</a> 通信阶段：传递消息</h3>\n<p>通过 write 和 read 来读写消息，实现传递消息。</p>\n<p>例如，HTTP，生成 HTTP 请求报文，然后调用 write 写入通道中，服务器通过 read 读取通道的数据。</p>\n<h3 id=\"断开阶段\"><a class=\"anchor\" href=\"#断开阶段\">#</a> 断开阶段</h3>\n<p>使用 close 组件，断开和删除套接字，通道关闭。</p>\n<p>HTTP 协议规定，web 服务器发送完响应消息后，先断开；然后浏览器知道断开后，也会调用 close 断开。</p>\n<p>不同协议，客户端和服务器端哪一方先执行 close 都有可能。</p>\n",
            "tags": [
                "network",
                "network"
            ]
        },
        {
            "id": "https://blog.ceciljxsu.icu/2020/03/27/spring/source/Feign%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/",
            "url": "https://blog.ceciljxsu.icu/2020/03/27/spring/source/Feign%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/",
            "title": "Feign原理简述",
            "date_published": "2020-03-27T06:09:29.000Z",
            "content_html": "<h1 id=\"feign原理简述\"><a class=\"anchor\" href=\"#feign原理简述\">#</a> Feign 原理简述</h1>\n<ol>\n<li>@EnableFeignClients 开启扫描，扫描包下的所有 @FeignClient，然后注入到 IOC 容器中。</li>\n<li>调用 feign 接口，通过 JDK 动态代理生成 RequestTemplate。</li>\n<li>RequestTemplate 是模版，包含请求所有信息，然后生成 Request，Request 交给 client 处理，client 默认是 JDK 的 HTTPUrlConnection，也可以是 OKHttp、Apache 的 HTTPClient 等。</li>\n<li>client 封装成 LoadBalanceClient，结合 ribbon 负载均衡发起调用。</li>\n<li>调用失败，还有 hystrix 熔断。</li>\n</ol>\n<p>Feign、hystrix 与 retry 的关系请参考 https://xli1224.github.io/2017/09/22/configure-feign/</p>\n<h2 id=\"enablexxxx-原理\"><a class=\"anchor\" href=\"#enablexxxx-原理\">#</a> @EnableXxxx 原理</h2>\n<ol>\n<li>@EnableXxxx 注解都包含一个 @Import 注解，指定配置类。 [嵌套多一层是为了隐藏细节（配置类，这个使用者不用关注），方便使用者使用，使用者直接一个注解即可，不用任何配置]</li>\n<li>@Import 注解的配置类，需要实现接口 ImportSelector，以及实现方法 selectImports，入参是注解元数据，出参是需要导入的类 String []</li>\n</ol>\n",
            "tags": [
                "spring",
                "source",
                "source",
                "spring"
            ]
        }
    ]
}