【问题标题】:Is HashSet a well-written class? [closed]HashSet 是一个写得很好的类吗? [关闭]
【发布时间】:2021-09-20 04:08:37
【问题描述】:

我正在尝试将设计模式作为良好的编码实践来学习,我想知道 HashSet 是否被认为是一个编写良好的类?例如:

要构造 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));

【问题讨论】:

  • 首先:“这是精心设计的”是非常基于意见的,因此不是关于 SO 的主题。第二:由于各种原因,JDK 类做了普通类通常不应该做的事情。对于这些类中的一个微优化实际上是有回报的,因为它们被大量使用,而且这些类将始终使用特定的 JVM 实现运行(因此优化可以考虑到这一点)。不要将 JDK 类的实现作为通用代码的灵感来源。
  • 感谢@JoachimSauer 的评论,我曾经看过内部JVM代码来尝试向他们学习:P
  • 我不是说“不要向他们学习”。只是不要假设您在其中看到的所有内容实际上都是非 JDK 代码的最佳实践。
  • 这些集合的不同功能避免了代码重复,但像中国拼图一样粘在一起。带有虚拟参数的重载构造函数就是这样的工件。我会开始学习算法和专用数据结构,而不是代码“架构”。

标签: java design-patterns hashmap linkedhashmap


【解决方案1】:

这严重基于选项。

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

但是,这是我对该主题的看法:

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

另一方面:

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

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

  • 他们如何引入和集成 Lambda 和 Streams(整个功能展示)
  • 泛型和协方差/逆变
  • 反思和注释

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

所以,正如其他人所说:

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

最后是你提到的几点:

  1. dummy 参数。这是一种非常罕见的情况,即使这样也大多只发生在生活质量方面:不是只有一个具有 3 个参数的 CTOR,还具有另一个具有 2 个参数的 CTOR
  2. 关于编译时递归:Java 编译器可以比作多遍编译器,因此“递归”不起作用。这个实现有点糟糕 - 一个非常理论/学术的抱怨 - 是 HashSetLinkedHashSet 现在在两个方向上都是静态绑定的。 LinkedHashSet -&gt; HashSet 会很好(否则如何实现继承!?),但 HashSet -&gt; LinkedHashSet 有点麻烦。但是,好吧,学术,因为这两个类在同一个包中,即使是新的 Modules 系统也不会将它们分开。因此,除非您编写的打包工具能够识别如此低的级别(就像我所做的那样),否则这一点不会产生实际影响。

【讨论】:

  • 感谢@JayC667,如上所述,这是一个基于选项的选项,因此由于您提供的所有额外信息,我选择您作为正确答案,非常有用!
  • 我多次更新了我的问题。再看一遍,希望我写了更多有用的东西;-)
猜你喜欢
  • 2012-06-27
  • 1970-01-01
  • 2011-04-23
  • 2016-03-15
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 2015-08-03
相关资源
最近更新 更多