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 当我不得不学习它时)
因此,正如其他人所说:
- 从代码中学习(有些技术真的很好)
- 改进它们(有些明显不好)
最后是您提到的要点:
dummy
参数。这是一种非常罕见的情况,即便如此,大多数情况下也只发生在 quality-of-life 中:不是只有一个 CTOR 有 3 个参数,还有另一个 CTOR 有 2 个参数
- 关于编译时间递归:Java编译器可以比作multi-pass编译器,所以'recursion'不玩角色。这个实现有一点不好 - 一个非常 theoretical/academic 的抱怨 - 是
HashSet
和 LinkedHashSet
现在在两个方向上都是静态绑定的。 LinkedHashSet -> HashSet
会很好(否则如何实现继承!?),但 HashSet -> LinkedHashSet
有点麻烦。但是,嗯,学术,因为这两个 类 在同一个包中,甚至新的 Modules 系统也不会把它们分开。所以除非你写了一个在这么低层次上识别的打包工具(像我一样),否则这一点没有实际影响。
我正在努力学习设计模式作为良好的编码实践,我想知道 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 当我不得不学习它时)
因此,正如其他人所说:
- 从代码中学习(有些技术真的很好)
- 改进它们(有些明显不好)
最后是您提到的要点:
dummy
参数。这是一种非常罕见的情况,即便如此,大多数情况下也只发生在 quality-of-life 中:不是只有一个 CTOR 有 3 个参数,还有另一个 CTOR 有 2 个参数- 关于编译时间递归:Java编译器可以比作multi-pass编译器,所以'recursion'不玩角色。这个实现有一点不好 - 一个非常 theoretical/academic 的抱怨 - 是
HashSet
和LinkedHashSet
现在在两个方向上都是静态绑定的。LinkedHashSet -> HashSet
会很好(否则如何实现继承!?),但HashSet -> LinkedHashSet
有点麻烦。但是,嗯,学术,因为这两个 类 在同一个包中,甚至新的 Modules 系统也不会把它们分开。所以除非你写了一个在这么低层次上识别的打包工具(像我一样),否则这一点没有实际影响。