我正在为一些研究项目编写确定性有限自动机的实现,并且有一些弧导致相同的状态.
我为State写了这个课,但是
我想知道为什么代码会产生Stackoverflow:
我为State写了这个课,但是
我想知道为什么代码会产生Stackoverflow:
public class State extends HashMap<Character,HashSet<State>> { public static void main(String[]args) { State t=new State(); t.addTransition('a',t); t.addTransition('b',t); } public void addTransition(Character symbol,State t ) { if(!this.containsKey(symbol)) { this.put(symbol,new HashSet<State>()); } this.get(symbol).add(t); } }
令人惊讶的是,如果我删除其中一个“addTransition”调用,则没有错误.
我的Java版本是JDK 1.6.37,操作系统是Ubuntu Linux 12.04.
* UPD:*堆栈跟踪是:
Exception in thread "main" java.lang.StackOverflowError at java.util.HashMap$KeyIterator.<init>(HashMap.java:843) at java.util.HashMap$KeyIterator.<init>(HashMap.java:843) at java.util.HashMap.newKeyIterator(HashMap.java:857) at java.util.HashMap$KeySet.iterator(HashMap.java:891) at java.util.HashSet.iterator(HashSet.java:170) at java.util.AbstractSet.hashCode(AbstractSet.java:122) at java.util.HashMap$Entry.hashCode(HashMap.java:737) at java.util.AbstractMap.hashCode(AbstractMap.java:494) at java.util.AbstractSet.hashCode(AbstractSet.java:126) at java.util.HashMap$Entry.hashCode(HashMap.java:737) at java.util.AbstractMap.hashCode(AbstractMap.java:494) at java.util.AbstractSet.hashCode(AbstractSet.java:126) at java.util.HashMap$Entry.hashCode(HashMap.java:737) ... at java.util.AbstractMap.hashCode(AbstractMap.java:494) at java.util.AbstractSet.hashCode(AbstractSet.java:126) at java.util.HashMap$Entry.hashCode(HashMap.java:737) at java.util.AbstractMap.hashCode(AbstractMap.java:494) at java.util.AbstractSet.hashCode(AbstractSet.java:126) at java.util.HashMap$Entry.hashCode(HashMap.java:737)
任何意见?
解决方法
运行此程序后,我认为问题如下:由于您要添加从节点到自身的转换,因此您最终会得到一个将字符映射到自身的HashMap.当您尝试添加第二个转换时,它需要将对象添加到HashSet中.问题是,为了做到这一点,它需要为您的对象计算哈希码.由于您的对象扩展了HashMap,它使用HashMap代码来计算对象的哈希代码.为此,它尝试递归地构造HashMap中包含其自身的所有对象的哈希代码.因此,它递归地尝试计算自己的哈希码,这需要它计算自己的哈希码,这需要它计算自己的哈希码等.
我不确定这是什么最好的解决方案,但我会从没有这个对象扩展HashMap开始. It is generally considered a bad idea to use inheritance when you mean to use composition.将HashMap作为对象的直接字段意味着您将打破此循环,因为Java将使用hashCode的默认实现,而hashCode不会尝试为对象计算深度哈希代码.
希望这可以帮助!