如何在Java中正确实现一个Map?

huangapple go评论79阅读模式
英文:

how to implement a Map in java correctly?

问题

Here's the translated code portion:

所以我正在尝试实现自己的Map以理解它的工作原理
我之前通过在我的实现中创建了2个私有列表来实现它但被告知要使用Entry类所以我现在的主要问题是如何比较存储在列表中的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);
    }
}
}
"put"方法没有完全编写我添加了"else if"因为没有它"put"方法不会测试具有相同键但不同值的条目只有当Entry实例完全相同包括键和值时才会进行测试当我尝试使用相同键但不同值的新条目实例进行put时它不会覆盖先前具有相同键的条目实例而是添加一个新的实例因此列表的大小会增加此外"get"方法的实现不起作用第一条语句引发了NullPointerException另一条语句将对象的类CorrectMapImpl$Entry@cd440b02输出而不是设置为键的值
英文:

So I am trying to implement my own Map to understand how it works.
I did it by making 2 private lists in my implementation before, but I was told to use and Entry class. so the main question for me now is how can I compare a key of the Entry that is stored in the list? here is my code

   import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public class CorrectMapImpl implements Map {
private List&lt;Entry&gt; entries = new ArrayList&lt;&gt;();
@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 -&gt; e.getKey().equals(key)).findFirst().orElse(null).getValue();
/*Optional&lt;Entry&gt; optionalEntry = entries.stream().filter(e -&gt; 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) &amp;&amp;
Objects.equals(value, entry.value);
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
}

}
the "put" is not complitely written. I addet "else if" because without it "put" did't test the entries for the same key/different value, only if the instance of the Entry fully the same, both key and the value. And when I try to entry.put an new instance of entry with the same key, but different value, it doesnt overwrite the previous instance of the entry with the same key, as it has to, but adds a new instance so the size of the list increments.
Also "get" implementation doesn't work. the first statement thows a NullPointerException, and the other tipes the class of the object like (CorrectMapImpl$Entry@cd440b02) instead of the value that is set to the key.

答案1

得分: 3

以下是翻译的部分:

"Right now you have a list of Entry objects. See the java API which states:

> [contains] Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that (o==null ? e==null : o.equals(e)).

That means when you wrote:

if (entries.contains(entry)) {
that is effectively equivalent to

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

Your code for the equals() in the Entry class,

@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);
}
Means that a.equals(b) will only return true if both the key and the value are the same.

That's why you're code is failing. I don't think the correct solution would be to change the way you currently implement .equals() because the way you implemented it does define the equality of two Entry objects.

My suggestion would be to replace the .contains(entry) code with a manual loop through the list and manually comparing the keys. Something like this

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

请注意,原文中包含的HTML编码已被保留。

英文:

Right now you have a list of Entry objects. See the java API which states:

> [contains] Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that (o==null ? e==null : o.equals(e)).

That means when you wrote:

if (entries.contains(entry)) {

that is effectively equivalent to

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

Your code for the equals() in the Entry class,

@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) &amp;&amp;
Objects.equals(value, entry.value);
}

Means that a.equals(b) will only return true if both the key and the value are the same.

That's why you're code is failing. I don't think the correct solution would be to change the way you currently implement .equals() because the way you implemented it does define the equality of two Entry objects.

My suggestion would be to replace the .contains(entry) code with a manual loop through the list and manually comparing the keys. Something like this

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

答案2

得分: 2

Your Entry类应该实现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;
        }
    }

    // 当循环结束时,要么您找到了具有相同键的条目,要么没有。
    // - 如果找到了条目,您需要更新其值。
    // - 如果没有找到条目,您需要创建一个新条目并将其添加到映射中。
    // 不要忘记您需要返回旧条目的值。

    if (foundEntry == null) {
        // 键不在映射中:创建新的Entry
        entries.add(new Entry(key, value));
        return null;
    } else {
        // 键已经在映射中:更新Entry
        Object oldValue = foundEntry.getValue();
        foundEntry.setValue(value);
        return oldValue;
    }
}

get方法应该类似于put方法的第一部分:首先查找具有正确键的条目。如果找到这样的条目,则返回其值。否则,返回null

您需要为Entry添加一个toString方法。请参考https://stackoverflow.com/questions/29140402/how-do-i-print-my-java-object-without-getting-sometype2f92e0f4

英文:

Your Entry class should implement the Map.Entry interface.

The put method should look for an existing entry with the given key. You can do that with a for - loop:

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

When the loop finishes, either you have found an entry that has the same key, or not.

  • If you have found an entry, you have to update its value.
  • If you haven't found an entry, you have to create a new entry and add it to the map.

Don't forget you have to return the old value of the 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;
}
}

The get method should look similar to the first part of the put method: First look for an entry that has the right key. If you find such an entry, return its value. Otherwise, return null.

> the other tipes the class of the object like [CorrectMapImpl$Entry@cd440b02)

You need to add a toString method to Entry. See https://stackoverflow.com/questions/29140402/how-do-i-print-my-java-object-without-getting-sometype2f92e0f4

huangapple
  • 本文由 发表于 2020年7月22日 23:14:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/63037567.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定