<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 第九章 `Map`接口 > 原文:[Chapter 9 The Map interface](http://greenteapress.com/thinkdast/html/thinkdast010.html) > 譯者:[飛龍](https://github.com/wizardforcel) > 協議:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) > 自豪地采用[谷歌翻譯](https://translate.google.cn/) 在接下來的幾個練習中,我介紹了`Map`接口的幾個實現。其中一個基于哈希表,這可以說是所發明的最神奇的數據結構。另一個是類似的`TreeMap`,不是很神奇,但它有附加功能,它可以按順序迭代元素。 你將有機會實現這些數據結構,然后我們將分析其性能。 但是在我們可以解釋哈希表之前,我們將從一個`Map`開始,它使用鍵值對的`List`來簡單實現。 ## 9.1 實現`MyLinearMap` 像往常一樣,我提供啟動代碼,你將填寫缺少的方法。這是`MyLinearMap`類定義的起始: ```java public class MyLinearMap<K, V> implements Map<K, V> { private List<Entry> entries = new ArrayList<Entry>(); ``` 該類使用兩個類型參數,`K`是鍵的類型,`V`是值的類型。`MyLinearMap`實現`Map`,這意味著它必須提供`Map`接口中的方法。 `MyLinearMap`對象具有單個實例變量,`entries`,這是一個`Entry`的`ArrayList`對象。每個`Entry`都包含一個鍵值對。這里是定義: ```java public class Entry implements Map.Entry<K, V> { private K key; private V value; public Entry(K key, V value) { this.key = key; this.value = value; } @Override public K getKey() { return key; } @Override public V getValue() { return value; } } ``` `Entry`沒有什么,只是一個鍵和一個值的容器。該定義內嵌在`MyLinearList`中,因此它使用相同類型的參數,`K`和`V`。 這就是你做這個練習所需的所有東西,所以讓我們開始吧。 ## 9.2 練習 7 在本書的倉庫中,你將找到此練習的源文件: + `MyLinearMap.java`包含練習的第一部分的起始代碼。 + `MyLinearMapTest.java`包含`MyLinearMap`的單元測試。 你還會找到 Ant 構建文件`build.xml`。 運行`ant build`來編譯源文件。然后運行`ant MyLinearMapTest`;幾個測試應該失敗,因為你有一些任務要做。 首先,填寫`findEntry`的主體。這是一個輔助方法,不是`Map`接口的一部分,但是一旦你讓它工作,你可以在幾種方法中使用它。給定一個目標鍵(Key),它應該搜索條目(Entry)并返回包含目標的條目(按照鍵,而不是值),或者如果不存在則返回`null`。請注意,我提供了`equals`,正確比較兩個鍵并處理`null`。 你可以再次運行`ant MyLinearMapTest`,但即使你的`findEntry`是正確的,測試也不會通過,因為`put`不完整。 填充`put`。你應該閱讀`Map.put`的文檔,<http://thinkdast.com/listput> ,以便你知道應該做什么。你可能希望從一個版本開始,其中`put`始終添加新條目,并且不會修改現有條目;這樣你可以先測試簡單的情況。或者如果你更加自信,你可以一次寫出整個東西。 一旦你`put`正常工作,測試`containsKey`應該通過。 閱讀`Map.get`的文檔,<http://thinkdast.com/listget> ,然后填充方法。再次運行測試。 最后,閱讀`Map.remove`的文檔,<http://thinkdast.com/maprem> 并填充方法。 到了這里,所有的測試都應該通過。恭喜! ## 9.3 分析`MyLinearMap` 這一節中,我展示了上一個練習的答案,并分析核心方法的性能。這里是`findEntry`和`equals`。 ```java private Entry findEntry(Object target) { for (Entry entry: entries) { if (equals(target, entry.getKey())) { return entry; } } return null; } private boolean equals(Object target, Object obj) { if (target == null) { return obj == null; } return target.equals(obj); } ``` `equals`的運行時間可能取決于`target`鍵和鍵的大小 ,但通常不取決于條目的數量,`n`。那么`equals`是常數時間。 在`findEntry`中,我們可能會很幸運,并在一開始就找到我們要找的鍵,但是我們不能指望它。一般來說,我們要搜索的條目數量與`n`成正比,所以`findEntry`是線性的。 大部分的`MyLinearMap`核心方法使用`findEntry`,包括`put`,`get`,和`remove`。這就是他們的樣子: ```java public V put(K key, V value) { Entry entry = findEntry(key); if (entry == null) { entries.add(new Entry(key, value)); return null; } else { V oldValue = entry.getValue(); entry.setValue(value); return oldValue; } } public V get(Object key) { Entry entry = findEntry(key); if (entry == null) { return null; } return entry.getValue(); } public V remove(Object key) { Entry entry = findEntry(key); if (entry == null) { return null; } else { V value = entry.getValue(); entries.remove(entry); return value; } } ``` `put`調用`findEntry`之后,其他一切都是常數時間。記住這個`entries`是一個`ArrayList`,所以向末尾添加元素平均是常數時間。如果鍵已經在映射中,我們不需要添加條目,但我們必須調用`entry.getValue`和`entry.setValue`,而這些都是常數時間。把它們放在一起,`put`是線性的。 同樣,`get`也是線性的。 `remove`稍微復雜一些,因為`entries.remove`可能需要從一開始或中間刪除`ArrayList`的一個元素,并且需要線性時間。但是沒關系:兩個線性運算仍然是線性的。 總而言之,核心方法都是線性的,這就是為什么我們將這個實現稱為`MyLinearMap`(嗒嗒!)。 如果我們知道輸入的數量很少,這個實現可能會很好,但是我們可以做得更好。實際上,`Map`所有的核心方法都是常數時間的實現。當你第一次聽到這個消息時,可能似乎覺得不可能。實際上我們所說的是,你可以在常數時間內大海撈針,不管海有多大。這是魔法。 我們不是將條目存儲在一個大的`List`中,而是把它們分解成許多短的列表。對于每個鍵,我們將使用哈希碼(在下一節中進行說明)來確定要使用的列表。 使用大量的簡短列表比僅僅使用一個更快,但正如我將解釋的,它不會改變增長級別;核心功能仍然是線性的。但還有一個技巧:如果我們增加列表的數量來限制每個列表的條目數,就會得到一個恒定時間的映射。你會在下一個練習中看到細節,但是首先要了解哈希! 在下一章中,我將介紹一種解決方案,分析`Map`核心方法的性能,并引入更有效的實現。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看