【问题标题】:java.lang.StackOverflowError adding set to set itselfjava.lang.StackOverflowError 添加设置来设置自己
【发布时间】:2018-09-09 11:41:06
【问题描述】:

为什么下面的代码给出 java.lang.StackOverflowError 错误

Set s = new HashSet();
s.add(s);
s.add(s);

操作集在内部执行什么操作,为什么每次都计算哈希码?

Exception in thread "main" java.lang.StackOverflowError
    at java.util.HashMap$KeyIterator.<init>(HashMap.java:1459)
    at java.util.HashMap$KeySet.iterator(HashMap.java:916)
    at java.util.HashSet.iterator(HashSet.java:172)
    at java.util.AbstractSet.hashCode(AbstractSet.java:122)
    at java.util.AbstractSet.hashCode(AbstractSet.java:126)
    at java.util.AbstractSet.hashCode(AbstractSet.java:126)
    at java.util.AbstractSet.hashCode(AbstractSet.java:126)
    at java.util.AbstractSet.hashCode(AbstractSet.java:126)

【问题讨论】:

  • 您在其中添加了 Set 实例,因此它在没有任何退出条件的情况下递归调用其方法。
  • 为什么要给自己加Set,请解释一下?
  • @Prabhav,不幸的是我在添加确认时遇到了这个错误。
  • 但我不认为,我们需要在现实生活中为自身添加集合。
  • 是的,完全正确.. 通过查看 HashSet 的实现,为什么它每次都调用哈希码,即使我们自己添加了一个元素来找到正确的存储桶.. 理解以下来自 Paul Boddington 的答案。跨度>

标签: java hashmap hashset


【解决方案1】:

您的 Set 每次都在计算哈希码,因为您使用 HashSet 实现来计算该集合内每个对象的哈希,并使用该哈希来确保没有重复的元素。而且由于您正在向自身添加某些内容,因此它会变得递归而没有结束条件并填满堆栈->堆栈溢出;)

【讨论】:

    【解决方案2】:

    你可以通过这样做得到同样的异常

    Set s = new HashSet();
    s.add(s);
    s.hashCode();
    

    原因是SethashCode 被指定为元素的hashCodes 之和(使用0 表示null)。换句话说,hashCode 等价于:

    public int hashCode() {
        int result = 0;
        for (Object o : this) {
            result += (o == null ? 0 : o.hashCode());   // <== This line is the problem
        }
        return result;
    }
    

    在您的情况下,由于集合包含自身,因此在主体中对 hashCode 的调用实际上是递归的,因此会导致 StackOverflowError

    至于为什么要调用hashCode,这就是HashSet 的工作原理。当你添加一个元素时,它的hashCode 值用于确定将元素放在哪个桶中。这个过程意味着HashSet 有一个非常快速高效的contains 方法。

    【讨论】:

      【解决方案3】:

      如果您使用的是 Lombok 和 Java。

      @Getter 和 @Setter 而不是 @Data。

      因为@Data注解包含@EqualsAndHashCode。

      例子:

      @Data
      class Example {
      
      }
      
      @Getter
      @Setter
      class Example {
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-24
        • 1970-01-01
        • 2011-08-12
        • 1970-01-01
        • 2011-09-05
        相关资源
        最近更新 更多