论坛首页 Java企业应用论坛

CoreJava: 第一次用LinkedHashSet带来的思考(一)

浏览 5006 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-02-14  
OO

     用Java虽说时间不是很长,但也有将近两年, 不过这个LinkedHashSet还是第一次用, 以前只是在学Java的Collections时知道有这么个类,它可在Set的基础排重的基础上有List的保持原有顺序的作用.理解归理解,但实际中 还是一直也没遇到真正用它的场景. 在这篇博客里 ,很遗憾与这个类仅仅是擦肩而过,也没能真正地往下想想.

    在 上面那博客里提到LinkedHashSet有"排重"的作用, 其中的一个用处就是可以把List或Array中的元素放到一个HashSet里以把重复的元素去掉,不过当时没想到,用HashSet就够了, 但却为什么用了LinkedHashSet呢? 今天的一个问题逼着我想到这里LinkedHashSet的好处了: 保持List或Array里元素的顺序. 具体实例可以有: 若从数据库里取出一个List的数组, 当然可能通过SQL里的关键字distinct而在数据库里就排重,但可能出于什么特殊的考虑而没有调用distinct,这样在Java里想排重就自然 地想到了Set,而初次想到的当然也就是HashSet, 但写出来后测试时一看结果, 不对呀, 原来从数据库里取出数据明明是已Order好的, 怎么显示出的却乱了, 转念一想可不是嘛: 在用Set的HashSet排重时,它并不关心你原来数据的顺序.这时LinkedHashSet就可救火了.

    进 而往下想, LinkedHashSet内部又是怎么来保序的呢? 看LinkedHashSet的源码时,没找到答案. LinkedHashSet类里除了四个构造方法外,什么也没了. 这是怎么回事?再往下看四个构造方法中都调用了父类HashSet的构造方法, 调了又怎样呢? 难不成是HashSet也有LinkedHashSet的功能吧? 带着这个问题再看HashSet里被LinkedHashSet调用的构造方法吧, 代码如下:
          HashSet(int initialCapacity, float loadFactor, boolean dummy) {
              map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
         }
    这 里有两个注意点,首先构造方法HashSet前没有任何访问修饰符, 也就是说只能在Java标准库里的java.util包下的类对能访问. 这也怎样呢? 下面会用到. 其次是构造方法里给map属性赋的值是一个LinkedHashMap实例. 看到这明白了: LinkedHashSet的保序功能是通过其属性LinkedHashMap实现的. 那一般的HashSet实例怎么又没有这个功能呢? 我们看HashSet的源码发现,除上面提到的那个构造方法外,它还有四个, 这四个构造方法都是public的, 在构造方法中,属性map的值都是HashMap的实例,自然也就没有Linked*所具有的保序功能了,我们所new出来的HashSet都是通过这四 个public的构造方法生成的, 自然也就没有保序功能了.

    看到这里, "保序"的实现虽说没有彻底搞明白,但知道了, 它是通过LinkedHashMap实现的, 这就不必再为
LinkedHashSet自身的实现所困惑了.如有时间再考虑人家 LinkedHashMap是怎么实现"保序"功能的.

    不过,通过这个问题的研究, 另一个设计上的启示渐渐浮出水面, LinkedHashSet在设计上又有什么启示呢?在下一篇关于LinkedHashSet的思考里将做详细的说明.

   发表时间:2009-02-15  
java集合里的Set都是基于Map的,set相当于map里所有的key指向同一个value。
应该是花时间去学习Map的代码。
0 请登录后投票
   发表时间:2009-02-15  
不错,我也没有用过linkedhashmap
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics