不懂就问, LinkedHashSet 为什么要这样设计?

2023-01-28 17:28:21 +08:00
 codewld

LinkedHashSet 源码可以精简如下:

public class LinkedHashSet<E> extends HashSet<E> {
	
    public LinkedHashSet() {
        super(16, .75f, true);
    }
    
}

其中,super 关键字调用的是父类中 "only used by LinkedHashSet" 的构造函数,如下:

public class HashSet<E> {
	
    /**
     * Constructs a new, empty linked hash set.  (This package private
     * constructor is only used by LinkedHashSet.) The backing
     * HashMap instance is a LinkedHashMap with the specified initial
     * capacity and the specified load factor.
     */
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }
    
}

在这样的设计下,HashSet 需要额外携带一部分不属于它的代码,实在不够优雅。

2060 次点击
所在节点    Java
11 条回复
Origami404
2023-01-28 17:47:47 +08:00
说不定就是因为懒得再写一次代码呢,每个映射只需要多付出一个指针的大小就可以立得一个 set ,多快乐啊

有些语言支持零大小类型,这种语言的 xxSet<T> 可以直接是 xxMap<T ,Void> ,毫无额外开销。我记得 Rust 标准库里的似乎就是这样实现的,但是我不确定了。
TtTtTtT
2023-01-28 18:04:06 +08:00
HashSet 本身也没有多少逻辑,本质上就是用 HashMap 实现 Set 。
因此,基于继承的方案下,这里应该就是为了保护了 map 的 private ,然后开个 package private 的 constructor 给 LinkedHashSet 。

也有其他几种方案能达到这个效果,比如开个 package private 的 constructor 传一个 map factory 之类的,或者把 map 变成 package private 的。但是都挺奇怪的。

如果一定要说是根本问题是啥,就怪到 JVM 的单继承上,hhh
xtreme1
2023-01-28 18:05:28 +08:00
codewld
2023-01-28 18:05:35 +08:00
@Origami404 除了开销,代码书写上也有问题。这个构造函数有且只有 LinkedHashSet 会用到,那为什么不直接把这些代码挪到 LinkedHashSet 里面呢?
Bingchunmoli
2023-01-28 18:07:47 +08:00
@codewld 如果我拓展 hashset 这个是不是有可能用到
codewld
2023-01-28 18:08:30 +08:00
@TtTtTtT 我觉得"增加一个 map 的构造器"这个方案比现有的好得多
codewld
2023-01-28 18:11:35 +08:00
@Bingchunmoli 这个构造函数只和 LinkedHashSet 相关,假设代码已经挪出去,直接继承 LinkedHashSet 扩展就好了。
Bingchunmoli
2023-01-29 10:06:41 +08:00
@codewld linked 是链表,我不用链表呢
codewld
2023-01-29 12:05:41 +08:00
@Bingchunmoli 这个问题正是现有设计无法解决的,不管用不用链表,HashSet 中都始终持有这一部分只属于链表的代码。
Bingchunmoli
2023-01-29 12:41:00 +08:00
@codewld 😯,是的,看差了
MineDog
2023-02-11 13:44:51 +08:00
@codewld #9 2 楼提了一下,可能就是为了保证内部 map 的私有性,毕竟这里是 HashSet ,它一般也只会用到 HashMap 作为内部实现,当然写成一个默认访问级别的 map 传参构造方法也行,只是人家选了现在的写法。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/911118

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX