打算用面向对象思想,写个求最小生成树问题。写了一半,就出现问题了import java.util.HashMap;
public class City { private String cityName; private HashMap<City, Double> adjCities = new HashMap<City, Double>(); public City(String cityName) { this.cityName = cityName; } public void addAjdCity(City city, double cost) { adjCities.put(city, cost); // System.out.println("test1"); city.adjCities.put(this, cost); // System.out.println("test2"); } public void removeAjdCity(City city) { } public void removeAjdCity(String cityName) { } public String toString() { return cityName + ":" + "\n" + adjCities; } public static void main(String[] args) { City c1 = new City("上海"); City c2 = new City("杭州"); c1.addAjdCity(c2, 100); // 怎么输出c1 c2时会出问题?StackOverflowError异常。如果把最后两句println注释掉,就不会报错?? System.out.println(c1); System.out.println(c2); } }
你的toString方法里递归调用了,死循环出不来了...
这是AbstractMap的toString方法:
[code="java"]
public String toString() {
Iterator> i = entrySet().iterator();
if (! i.hasNext())
return "{}";
StringBuilder sb = new StringBuilder();
sb.append('{');
for (;;) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
sb.append(key == this ? "(this Map)" : key);
sb.append('=');
sb.append(value == this ? "(this Map)" : value);
if (! i.hasNext())
return sb.append('}').toString();
sb.append(", ");
}
}
[/code]
由于你的Map里Key还是City对象,所以执行Map的toString时这一行 sb.append(key == this ? "(this Map)" : key);会自动调用key的toString方法,这样又进入了City的toString方法,然后就挂了.....
由于c1.adjCities包含c2,同时c2.adjCities包含c1。
而hashmap的打印方法是打印所有的key-value对。
所以打印c1就是打印c1.toString()。
c1.toString()包含c1.adjCities.toString()。
c1.adjCities.toString()包含c2.toString(),
c2.toString()也包含c2.adjCities.toString(),其中又包含c1.toString()。
因此,就无限递归了,栈爆了。
最好把City.toString()改成:return cityName + ":" + adjCities.keySet();
[code="java"] public void addAjdCity(City city, double cost) {
adjCities.put(city, cost);
// System.out.println("test1");
city.adjCities.put(this, cost);
// System.out.println("test2");
} [/code]
上面代码,两个对象city1称为我、city2成为你,两个 互相绑定了。我拥有你,你拥有我。。。
你打印我的时候,我包含了你,也要把你弄出来吧。。但是你又包含了我。。完了。就这样一直包含来包含去,无限循环,栈满了。
这和hashMap没关系,是设计的问题
错误原因在这句
[code="java"] city.adjCities.put(this, cost); [/code]
去掉这个,肯定不会报异常,但是你的C2的hashMap就什么都没加进去
你在一个class City里面叫另外一个class City,无限初始化肯定溢出
说实话啊,这个程序我完全没理解你的用意
你这里的 this 是C1
难道你要把2个city 互相加到对方的hashMap里? 8)