将对象添加到HashSet中

3

我想将一个 Object (Exception) 添加到一个 Set 中,但是它会添加所有的 Exception,即使有些是重复的。debug

在我的情况下,重复的 Exception 具有相同的 Detail 消息。

如何才能正确地将 Exceptions 添加到 HashSet 中,并且仅在 Exception.getDetails() 不存在时添加?

除了 HashSet,是否有其他方法可行?

这里性能很关键,二次方解决方案 (O(n^2)) 不是一个选项。


4
为你的异常实现正确的hashCode()和equals()方法。 - Michal
你能告诉我们你为什么这么做吗? - Tim Biegeleisen
为了在前端正确显示我的 messageFactory - 0x2E5
3个回答

4

您有几个选项:

  • 在您的异常类中覆盖hashcodeequals
  • 使用带有自定义ComparatorTreeSet
  • 使用Map<String, Exception>,其中键是getDetails()的结果(例如,HashMap

1
你需要覆盖异常比较的方式,以便它按照你想要的方式识别重复项。你无法对HashSet执行此操作,但可以对TreeSet执行。
Set<Exception> exceptions = new TreeSet<>(Comparator.comparing(Object::toString));

这个例子比较的是大多数情况下异常类型和消息的toString方法。
如果你真的想使用HashSet,你需要将异常包装在一个实现了你需要的hashCode和equals方法的类中。
如果你只关心类型和消息,你可以只存储每个异常的toString。
final Set<String> exceptions = new HashSet<>();

public void addException(Exception e) {
    exceptions.add(e.toString());
}

1
实际上,仅使用toString是不够的,因为我之后还需要进一步处理它。但是您的TreeSet解决方案具有log(n)的效果,非常好用。 - 0x2E5
在这种情况下,您可以考虑使用Map<String,Exception>,每次添加的时间复杂度为O(1),这是assylias的建议。 - Peter Lawrey

1
你需要重新定义equalshashCode方法。
如果detail是一个String,你可以按照以下方式重新定义它们。
public boolean equals(Object obj) {
   if (!(obj instanceof YourException)) {
     return false;
   } 
   return getDetail().equals(((YourException) obj).getDetail());
}

public int hashCode() {
   return getDetail().hashCode();
}

Consider this code as a base to program. You have to check for null values for example.
Once redefined equals and hashCode inserting YourException in a TreeSet is an operation done in O(log(n)) where n is the size of the set, from javadoc:
This implementation provides guaranteed log(n) time cost for the basic operations (add, remove and contains).

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接