Пример #1
0
  /**
   * Appends the given array to this builder.
   *
   * @param arr array to append
   * @return self reference for convenience
   */
  public ArrayBuilder append(final Array arr) {
    if (!(arr instanceof BigArray)) {
      for (final Value val : arr.members()) append(val);
      return this;
    }

    final BigArray big = (BigArray) arr;
    final Value[] ls = big.left, rs = big.right;
    final FingerTree<Value, Value> midTree = big.middle;
    if (midTree.isEmpty()) {
      for (final Value l : big.left) append(l);
      for (final Value r : big.right) append(r);
      return this;
    }

    // merge middle digits
    if (tree.isEmpty()) {
      final int k = inLeft + inRight;
      final Value[] temp = new Value[k];
      final int l = (mid - inLeft + CAP) % CAP, m = CAP - l;
      if (k <= m) {
        System.arraycopy(vals, l, temp, 0, k);
      } else {
        System.arraycopy(vals, l, temp, 0, m);
        System.arraycopy(vals, 0, temp, m, k - m);
      }

      inLeft = inRight = 0;
      tree.append(midTree);
      for (int i = ls.length; --i >= 0; ) prepend(ls[i]);
      for (int i = k; --i >= 0; ) prepend(temp[i]);
      for (final Value r : rs) append(r);
      return this;
    }

    final int inMiddle = inRight + big.left.length,
        leaves = (inMiddle + Array.MAX_LEAF - 1) / Array.MAX_LEAF,
        leafSize = (inMiddle + leaves - 1) / leaves;
    for (int i = 0, l = 0; l < leaves; l++) {
      final int inLeaf = Math.min(leafSize, inMiddle - i);
      final Value[] leaf = new Value[inLeaf];
      for (int p = 0; p < inLeaf; p++) {
        leaf[p] = i < inRight ? vals[(mid + i) % CAP] : big.left[i - inRight];
        i++;
      }
      tree.append(new LeafNode(leaf));
    }

    tree.append(big.middle);
    inRight = 0;
    for (final Value r : big.right) append(r);
    return this;
  }
Пример #2
0
  /**
   * Adds an element to the end of the array.
   *
   * @param elem element to add
   * @return self reference for convenience
   */
  public ArrayBuilder append(final Value elem) {
    if (inRight < Array.MAX_DIGIT) {
      // just insert the element
      vals[(mid + inRight) % CAP] = elem;
      inRight++;
    } else if (tree.isEmpty() && inLeft < Array.MAX_DIGIT) {
      // move the middle to the right
      mid = (mid + 1) % CAP;
      vals[(mid + inRight + CAP - 1) % CAP] = elem;
      inLeft++;
    } else {
      // push leaf node into the tree
      final Value[] leaf = new Value[NODE_SIZE];
      final int start = mid;
      for (int i = 0; i < NODE_SIZE; i++) leaf[i] = vals[(start + i) % CAP];
      tree.append(new LeafNode(leaf));

      // move rest of the nodes to the right
      final int rest = inRight - NODE_SIZE;
      for (int i = 0; i < rest; i++) {
        final int to = (mid + i) % CAP, from = (to + NODE_SIZE) % CAP;
        vals[to] = vals[from];
      }

      // insert the element
      vals[(mid + rest) % CAP] = elem;
      inRight = rest + 1;
    }
    return this;
  }