簡體   English   中英

如何在 java 中正確實現 Map?

[英]how to implement a Map in java correctly?

所以我試圖實現我自己的 Map 來了解它是如何工作的。 我之前通過在我的實現中創建了 2 個私有列表來做到這一點,但我被告知使用和條目 class。 所以現在對我來說主要問題是如何比較存儲在列表中的條目的鍵? 這是我的代碼

   import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

public class CorrectMapImpl implements Map {
private List<Entry> entries = new ArrayList<>();

@Override
public Object put(Object key, Object value) {
    Entry entry = new Entry(key, value);
    if (entries.contains(entry)) {
        int index = entries.indexOf(entry);
        entries.set(index, (Entry) value);
    }else if(entries.contains()){

    } else  {
        entries.add(entry);
    };
    return entry.getValue();
}

@Override
public Object get(Object key) {
   //return entries.stream().filter(e -> e.getKey().equals(key)).findFirst().orElse(null).getValue();
    /*Optional<Entry> optionalEntry = entries.stream().filter(e -> e.getKey().equals(key)).findFirst();
    optionalEntry.ifPresent(Entry::getValue);
    return optionalEntry;*/
}

@Override
public int size() {
    return entries.size();
}

@Override
public Object remove(Object key) {
    boolean hasKey = false;
    int keyIndex = 0;
    for(Entry entry: entries) {
        if(entry.getKey().equals(key)) {
            hasKey = true;
            break;
        }
        keyIndex++;
    }
    if(hasKey) {
        return entries.remove(keyIndex).getValue();
    }
    return null;
}
//---------------------------------------------------------------------------------------------
class Entry {
    private Object key;
    private Object value;

    public Entry(Object key, Object value) {
        this.key = key;
        this.value = value;
    }

    public Object getKey() {
        return key;
    }

    public void setKey(Object key) {
        this.key = key;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Entry)) return false;
        Entry entry = (Entry) o;
        return Objects.equals(key, entry.key) &&
                Objects.equals(value, entry.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(key, value);
    }
}

} “put”沒有完整地寫出來。 我添加了“else if”,因為沒有它“put”沒有測試相同鍵/不同值的條目,只有當條目的實例完全相同時,鍵和值。 當我嘗試 entry.put 一個具有相同鍵但值不同的條目的新實例時,它不會像必須那樣覆蓋具有相同鍵的條目的前一個實例,而是添加一個新實例,因此大小為列表遞增。 “get”實現也不起作用。 第一條語句拋出 NullPointerException,而另一條則提示 object 的 class (CorrectMapImpl$Entry@cd440b02),而不是設置為鍵的值。

現在你有一個Entry對象列表。 請參閱java API ,其中指出:

[contains] 如果此集合包含指定元素,則返回 true。 更正式地說,當且僅當此集合包含至少一個元素 e 滿足 (o==null?e==null: o.equals(e)) 時才返回 true。

這意味着當你寫:

if (entries.contains(entry)) {

這實際上相當於

for(Entry e : entries) if(e.equals(entry){...}

您在Entry class 中的equals()代碼,

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Entry)) return false;
    Entry entry = (Entry) o;
    return Objects.equals(key, entry.key) &&
            Objects.equals(value, entry.value);
}

意味着a.equals(b)只有在鍵相同時才會返回 true。

這就是為什么你的代碼失敗了。 我認為正確的解決方案不是改變您當前實現.equals()的方式,因為您實現它的方式確實定義了兩個 Entry 對象的相等性。

我的建議是用手動循環遍歷列表並手動比較鍵來替換.contains(entry)代碼。 像這樣的東西

for(int i = 0; i < entries.size(); i++){
  if(entries.get(i).getKey().equals(entry.getKey())) {
    index = i;
    break;
  }
}

您的Entry class 應該實現Map.Entry接口。

put 方法應該查找具有給定鍵的現有條目。 您可以使用 for - 循環來做到這一點:

    public Object put(Object key, Object value) {
        Entry foundEntry = null;
        for (Entry entry : entries) {
            if (key.equals(entry.getKey())) {
                foundEntry = entry;
            }
        }

當循環結束時,要么你找到了一個具有相同鍵的條目,要么沒有。

  • 如果你找到了一個條目,你必須更新它的值。
  • 如果您沒有找到條目,則必須創建一個新條目並將其添加到 map。

不要忘記您必須返回條目的舊值。

        if (foundEntry == null) {
            // Key not in map: create new Entry
            entries.add(new Entry(key, value));
            return null;
        } else {
            // Key already in map: update Entry
            Object oldValue = foundEntry.getValue();
            foundEntry.setValue(value);
            return oldValue;
        }
    }

get方法應該類似於 put 方法的第一部分:首先查找具有正確鍵的條目。 如果找到這樣的條目,則返回其值。 否則,返回null

其他提示 object 的 class 像 [CorrectMapImpl$Entry@cd440b02)

您需要在 Entry 中添加一個toString方法。 請參閱如何在不獲取“SomeType@2f92e0f4”的情況下打印我的 Java object?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM