[英]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;
}
}
当循环结束时,要么你找到了一个具有相同键的条目,要么没有。
不要忘记您必须返回条目的旧值。
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.