• Guava源码分析——Immutable Collections(3)


    这一次,我们来分析ImmutableSet,与ImmutableList大同小异,建议大家先看完上一篇Immutable Collections(2),在继续往下看

    相同:

    • ImmutableSet底层也采用数组实现
    • of()、copyOf()方法实现逻辑也相同
    • 元素也是按传入顺序排列的
    • 实现是根据元素个数,分为EmptyImmutableSet、SingletonImmutableSet、RegularImmutableSet

    不同:

    • construct()方法的实现不再是简单的copy,需要计算hash值,并且ImmutableSet内部维护两套数组(后面会说到)

    EmptyImmutableSet、SingletonImmutableSet不需要在做更多详细的说明,他们的存在的意义在于,对单个元素和空集合的操作优化,RegularImmutableSet的实现比较巧妙,它内部维护了两套数组,一套依照传入元素顺序,记录元素。另一套根据Guava自定义的hash算法产生经过hash后的集合的位置,Guava的hash算法效率高于HashSet内部提供的hash算法,而且元素保证传入顺序。

    private static <E> ImmutableSet<E> construct(int n, Object... elements) {
        //依然是根据元素个数的不同,选择不同的实现方式
        switch (n) {
          case 0:
            return of();
          case 1:
            @SuppressWarnings("unchecked") // safe; elements contains only E's
            E elem = (E) elements[0];
            return of(elem);
          default:
            // continue below to handle the general case
        }
        int tableSize = chooseTableSize(n);
        Object[] table = new Object[tableSize];
        int mask = tableSize - 1;
        int hashCode = 0;
        int uniques = 0;
        for (int i = 0; i < n; i++) {
          Object element = checkElementNotNull(elements[i], i);
          int hash = element.hashCode();
          for (int j = Hashing.smear(hash); ; j++) {
            int index = j & mask;
            Object value = table[index];
            if (value == null) {
              // Came to an empty slot. Put the element here.
              elements[uniques++] = element;//原有元素完全不变的copy到elements集合中
              table[index] = element;//table中存的是hash计算后的元素
              hashCode += hash;//hash值
              break;
            } else if (value.equals(element)) {
              break;
            }
          }
        }
        Arrays.fill(elements, uniques, n, null);
        if (uniques == 1) {
          // There is only one element or elements are all duplicates
          @SuppressWarnings("unchecked") // we are careful to only pass in E
          E element = (E) elements[0];
          return new SingletonImmutableSet<E>(element, hashCode);
        //如果table的size和uniques差的很多,证明重复元素很多,需要重新计算table的size,避免空间浪费
        } else if (tableSize != chooseTableSize(uniques)) {
          return construct(uniques, elements);
        } else {
          Object[] uniqueElements = (uniques < elements.length)
              ? ObjectArrays.arraysCopyOf(elements, uniques)
              : elements;
          return new RegularImmutableSet<E>(uniqueElements, hashCode, table, mask);
        }
      }
    View Code

    而且不必担心空间的浪费,其实两套数组内部,只是维护元素的引用。如果传入的元素集合存在大量的重复元素,ImmutableSet会copy后重新构造Set,以减少table数组(hash过后的)的空间浪费。详见代码。

    那么,在RegularImmutableSet中,与set相关的O(1)操作,就会转为对table的操作,而对set的遍历等操作,会转为对elements数组的操作,代码如下:

        RegularImmutableSet(
            Object[] elements, int hashCode, Object[] table, int mask) {
            this.elements = elements;//维护原有集合顺序
            this.table = table;//经过hash后的集合
            this.mask = mask;
            this.hashCode = hashCode;
        }
    
        //contains操作,使用经过hash后的table
        @Override
        public boolean contains(Object target) {
            if (target == null) {
                return false;
            }
            for (int i = Hashing.smear(target.hashCode()); true; i++) {
                Object candidate = table[i & mask];
                if (candidate == null) {
                    return false;
                }
                if (candidate.equals(target)) {
                    return true;
                }
            }
        }
    
        @Override
        public int size() {
            return elements.length;//size的实现肯定使用elements,因为table在有少量重复元素的情况下,稍大于elements
        }
  • 相关阅读:
    Ubuntu 12.04 root账户开启及密码重设
    Notepad++ 开启「切分窗口」同时检视、比对两份文件
    第11章 Java异常与异常处理
    第10章 Java类的三大特性之一:多态
    第9章 Java类的三大特性之一:继承
    第8章 Java类的三大特性之一:封装
    第7章 类和对象
    java 经典程序 100 例
    第6章 Java类中的方法
    第5章 Java数组
  • 原文地址:https://www.cnblogs.com/pona/p/4549998.html
Copyright © 2020-2023  润新知