不懂就问, LinkedHashSet 为什么要这样设计? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
codewld
V2EX    Java

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

  •  
  •   codewld 2023-01-28 17:28:21 +08:00 2465 次点击
    这是一个创建于 988 天前的主题,其中的信息可能已经有所发展或是发生改变。

    LinkedHashSet 源码可以精简如下:

    public class LinkedHashSet<E> extends HashSet<E> { public inkedHashSet() { 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 需要额外携带一部分不属于它的代码,实在不够优雅。

    11 条回复    2023-02-11 13:44:51 +08:00
    Origami404
        1
    Origami404  
       2023-01-28 17:47:47 +08:00 via Android
    说不定就是因为懒得再写一次代码呢,每个映射只需要多付出一个指针的大小就可以立得一个 set ,多快乐啊

    有些语言支持零大小类型,这种语言的 xxSet<T> 可以直接是 xxMap<T ,Void> ,毫无额外开销。我记得 Rust 标准库里的似乎就是这样实现的,但是我不确定了。
    TtTtTtT
        2
    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
        3
    xtreme1  
       2023-01-28 18:05:28 +08:00
    codewld
        4
    codewld  
    OP
       2023-01-28 18:05:35 +08:00
    @Origami404 除了开销,代码书写上也有问题。这个构造函数有且只有 LinkedHashSet 会用到,那为什么不直接把这些代码挪到 LinkedHashSet 里面呢?
    Bingchunmoli
        5
    Bingchunmoli  
       2023-01-28 18:07:47 +08:00 via Android
    @codewld 如果我拓展 hashset 这个是不是有可能用到
    codewld
        6
    codewld  
    OP
       2023-01-28 18:08:30 +08:00 div class="sep5">
    @TtTtTtT 我觉得"增加一个 map 的构造器"这个方案比现有的好得多
    codewld
        7
    codewld  
    OP
       2023-01-28 18:11:35 +08:00
    @Bingchunmoli 这个构造函数只和 LinkedHashSet 相关,假设代码已经挪出去,直接继承 LinkedHashSet 扩展就好了。
    Bingchunmoli
        8
    Bingchunmoli  
       2023-01-29 10:06:41 +08:00 via Android
    @codewld linked 是链表,我不用链表呢
    codewld
        9
    codewld  
    OP
       2023-01-29 12:05:41 +08:00
    @Bingchunmoli 这个问题正是现有设计无法解决的,不管用不用链表,HashSet 中都始终持有这一部分只属于链表的代码。
    Bingchunmoli
        10
    Bingchunmoli  
       2023-01-29 12:41:00 +08:00 via Android
    @codewld ,是的,看差了
    MineDog
        11
    MineDog  
       2023-02-11 13:44:51 +08:00
    @codewld #9 2 楼提了一下,可能就是为了保证内部 map 的私有性,毕竟这里是 HashSet ,它一般也只会用到 HashMap 作为内部实现,当然写成一个默认访问级别的 map 传参构造方法也行,只是人家选了现在的写法。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5882 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 36ms UTC 03:20 PVG 11:20 LAX 20:20 JFK 23:20
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86