我正在探索地图和树集的工作方式,目前正在编写自己的Java TreeMap实现。我在打印对象数组中节点的名称和值时遇到麻烦。该方法有时会成功编译并打印,但是大多数情况下会引发OutOfBoundsException。我可以通过在toString方法中声明数组时增加数组的大小来解决此问题,但这会留下一个空的数组插槽。
以下是我认为与该错误有关的方法
private int entryArray(Object[] arr, int index, Node n) {
if (n == null) {
return index;
} else {
index = entryArray(arr, index, n.left);
arr[index++] = new AbstractMap.SimpleEntry(n.key, n.value);
return entryArray(arr, index, n.right);
}
}
public class EntrySet extends SetAdapter {
Object[] arr;
EntrySet(Object[] arr) {
this.arr = arr;
}
@Override
public Iterator<Map.Entry<K,V>> iterator() {
return new Iterator<Map.Entry<K,V>>() {
int i = 0;
@Override
public boolean hasNext() {
return i < arr.length;
}
@Override
@SuppressWarnings("unchecked")
public Map.Entry<K,V> next() {
return (Map.Entry<K,V>) arr[i++];
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
};
}
}
@Override
public String toString() {
Object[] arr = new Object[size];
entryArray(arr, 0, root);
String str = java.util.Arrays.toString(arr);
str = "{" + str.substring(1, str.length() - 1) + "}";
return str;
}
@Override
@SuppressWarnings("unchecked")
public Set<Map.Entry<K,V>> entrySet() {
Object[] arr = new Object[size];
entryArray(arr, 0, root);
return new EntrySet(arr);
}
这是Main()
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import util.SearchTreeMap;
public class TestRemove {
public static void main(String[] args) {
TreeMap<String, Integer> java_map = new TreeMap();
SearchTreeMap<String, Integer> my_map = new SearchTreeMap();
String[] keys = {
"jerry", "paul", "erin", "kevin", "helen",
"bill", "john", "bob", "rick", "tim", "eddie",
};
// create random entries
List<Map.Entry<String, Integer>> entries = new ArrayList<>();
Random rand = new Random();
int num_entries = 12;
for (int i = 0; i < num_entries; i++) {
String name = keys[rand.nextInt(keys.length)];
int value = rand.nextInt(10);
Integer age = value == 0 ? null : 10 + value;
entries.add(new AbstractMap.SimpleEntry<>(name, age));
}
System.out.println("entries: " + entries);
entries.forEach((entry) -> {
java_map.put(entry.getKey(), entry.getValue());
my_map.put(entry.getKey(), entry.getValue());
});
Integer value;
int remove_index;
String remove_key;
// choose a random entry index, or 0 (the root)
remove_index = rand.nextInt(entries.size());
// remove_index = 0;
// get the key from the chosen index
// or, pick a key that's known to not be in the tree:
remove_key = entries.get(remove_index).getKey();
//remove_key = "tim";
System.out.println("remove key = " + remove_key);
System.out.println("\n================ java: ");
System.out.println("before: " + java_map);
System.out.println("size = " + java_map.size());
value = java_map.remove(remove_key);
System.out.printf("remove(%s)=%s\n", remove_key, value);
System.out.println("after: " + java_map);
System.out.println("size = " + java_map.size());
System.out.println("\n================= me: ");
System.out.println("before: "+ my_map);
System.out.println("size = "+ my_map.size());
System.out.println("-----------");
my_map.reverseInorderOutput();
System.out.println("-----------");
value = my_map.remove(remove_key);
System.out.printf("remove(%s)=%s\n", remove_key, value);
System.out.println("after: " + my_map);
System.out.println("size = " + my_map.size());
my_map.reverseInorderOutput();
}
}
让我感到困惑的是为什么它有时起作用而不是别人起作用, 这是成功编译的示例。
entries: [paul=14, bob=null, bob=14, rick=19, erin=null, tim=16, paul=12, jerry=19, john=18, jerry=11, john=16, paul=19]
remove key = paul
================ java:
before: {bob=14, erin=null, jerry=11, john=16, paul=19, rick=19, tim=16}
size = 7
remove(paul)=19
after: {bob=14, erin=null, jerry=11, john=16, rick=19, tim=16}
size = 6
================= me:
before: {bob=14, erin=null, jerry=11, john=16, paul=19, rick=19, tim=16}
size = 7
-----------
tim=16
rick=19
paul=19
john=16
jerry=11
erin=null
bob=14
-----------
remove(paul)=19
after: {erin=null, jerry=11, john=16, paul=19, rick=19, tim=16}
size = 6
tim=16
rick=19
paul=19
john=16
jerry=11
erin=null
Process finished with exit code 0
这是编译失败的痕迹
entries: [bob=15, jerry=18, erin=11, erin=17, helen=18, bill=15, paul=17, rick=15, helen=12, kevin=16, kevin=16, jerry=14]
remove key = erin
================ java:
before: {bill=15, bob=15, erin=17, helen=12, jerry=14, kevin=16, paul=17, rick=15}
size = 8
remove(erin)=17
after: {bill=15, bob=15, helen=12, jerry=14, kevin=16, paul=17, rick=15}
size = 7
================= me:
before: {bill=15, bob=15, erin=17, helen=12, jerry=14, kevin=16, paul=17, rick=15}
size = 8
-----------
rick=15
paul=17
kevin=16
jerry=14
helen=12
erin=17
bob=15
bill=15
-----------
remove(erin)=17
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 7
at util.SearchTreeMap.entryArray(SearchTreeMap.java:132)
at util.SearchTreeMap.entryArray(SearchTreeMap.java:133)
at util.SearchTreeMap.entryArray(SearchTreeMap.java:133)
at util.SearchTreeMap.entryArray(SearchTreeMap.java:133)
at util.SearchTreeMap.toString(SearchTreeMap.java:171)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at prog2.TestRemove.main(TestRemove.java:76)
Process finished with exit code 1
任何指导将不胜感激。如果涉及其他方法,请告诉我,我会提供。
谢谢