HashSet 写的好吗class?

Is HashSet a well-written class?

我正在努力学习设计模式作为良好的编码实践,我想知道 HashSet 是否被认为是一个写得很好的 class?例如:

要构建 LinkedHashSet,我们使用以下构造函数

public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
}

哪个叫这个:

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

所以有一个无用的参数,这样做正确吗?

此外,我看到 LinkedHashSet 扩展了 HashSet

LinkedHashSet<E> extends HashSet 

并且 HashSet 在其代码中引用了 LinkedHashSet,为什么那里没有编译时递归之类的东西?

// Create backing HashMap
        map = (((HashSet<?>)this) instanceof LinkedHashSet ?
               new LinkedHashMap<E,Object>(capacity, loadFactor) :
               new HashMap<E,Object>(capacity, loadFactor));

这是严重基于选项的。

而且在很多情况下,程序员不得不做出艰难的选择。而且工作的团队太多了,自然会出现下面的一些问题。

但是,我对这个话题的看法是:

  • 大部分 JDK 代码都是乱七八糟的。不必要的代码,现代 Java JIT 编译器很容易做得更好的复杂代码
  • 有很多微优化,但最终可以重写很多实现,使其更快、更简洁、更兼容。
  • ArrayList这样简单的类已经是乱七八糟了,如果自己写实现,速度会快一倍。
  • Input/OuputStream系统一团糟,应该在最顶层有一个接口。
  • 许多解决方案,如 ThreadLocal,使用起来本质上是不安全的,如果不是更严重的问题,可能会导致泄漏。
  • 有很多不应该重复的代码
  • 严重缺乏对默认转换的支持,尤其是 String 对其他东西的支持,应该有像 s.toInt(int default) 这样的默认方法
  • java.util. 函数和 FunctionalInterface 是一团糟,有许多不同的名称,这些名称本可以以更合乎逻辑和直观的方式构建,还包括所有收集器和其他东西。可以简单得多。

另一方面:

  • Collections 结构(继承、接口等)总体上实现得很好,只缺少很少的功能
  • java.nio的东西真不错
  • 异常(RuntimeException、Throwable)层次结构非常好,为其他自定义提供了稳定的基础类(人们可能更喜欢/应该使用)

某些方面不针对 类 的实现,而是语言规范:

  • 他们如何引入和集成 Lambdas 和 Streams(整个功能展示)
  • 泛型和 Covariance/Contravariance
  • 反射和注释

总而言之,如果您使用像 Project Lombok 这样的库(添加 AOP 和其他东西)为您的默认值 Java 提供一点提升,那就太棒了。我真的很喜欢它,到目前为止还没有其他语言可以 un-favorite Java(即使我讨厌 Java 当我不得不学习它时)

因此,正如其他人所说:

  • 从代码中学习(有些技术真的很好)
  • 改进它们(有些明显不好)

最后是您提到的要点:

  1. dummy参数。这是一种非常罕见的情况,即便如此,大多数情况下也只发生在 quality-of-life 中:不是只有一个 CTOR 有 3 个参数,还有另一个 CTOR 有 2 个参数
  2. 关于编译时间递归:Java编译器可以比作multi-pass编译器,所以'recursion'不玩角色。这个实现有一点不好 - 一个非常 theoretical/academic 的抱怨 - 是 HashSetLinkedHashSet 现在在两个方向上都是静态绑定的。 LinkedHashSet -> HashSet 会很好(否则如何实现继承!?),但 HashSet -> LinkedHashSet 有点麻烦。但是,嗯,学术,因为这两个 类 在同一个包中,甚至新的 Modules 系统也不会把它们分开。所以除非你写了一个在这么低层次上识别的打包工具(像我一样),否则这一点没有实际影响。