如何正确地用java实现Map



所以我正在尝试实现我自己的Map,以了解它是如何工作的。我之前在实现中制作了两个私有列表,但我被告知要使用和Entry类。所以我现在的主要问题是如何比较存储在列表中的条目的密钥?这是我的代码

   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);
    }
}

}";放入";写得不完整。我把";否则如果";因为没有它";放入";没有为相同的键/不同的值测试条目,只有当条目的实例完全相同时,键和值都相同。当我尝试entry.pout一个具有相同键但不同值的条目的新实例时,它不会像必须的那样覆盖具有相同键的条目的前一个实例,而是添加一个新实例,这样列表的大小就会增加。此外;得到";实现不起作用。第一条语句处理NullPointerException,另一条语句处理对象的类,如(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类中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类应该实现Map.Entry接口。

put方法应该查找具有给定键的现有条目。你可以用for-loop:来实现这一点

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

循环结束后,要么您找到了具有相同关键字的条目,要么您没有找到。

  • 如果找到一个条目,则必须更新其值
  • 如果没有找到条目,则必须创建一个新条目并将其添加到地图中

不要忘记您必须返回条目的旧值。

        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

其他提示对象的类,如[CorrectMapImpl$Entry@cd440b02)

您需要向Entry添加一个toString方法。参见How do I print my Java object without get";SomeType@2f92e0f4"?

最新更新