@Test
  public void testTransformAndFilter() throws InterruptedException {
    testRandomSelection(
        perThreadTrees,
        4,
        false,
        false,
        false,
        (selection) -> {
          Map<Integer, Integer> update = new LinkedHashMap<>();
          for (Integer i : selection.testKeys) update.put(i, new Integer(i));

          CountingFunction function;
          Object[] original = selection.testAsSet.tree();
          Object[] transformed;

          // test replacing none, leaving all present
          function = new CountingFunction((x) -> x);
          transformed = BTree.transformAndFilter(original, function);
          Assert.assertEquals(BTree.size(original), function.count);
          Assert.assertSame(original, transformed);

          // test replacing some, leaving all present
          function = new CountingFunction((x) -> update.containsKey(x) ? update.get(x) : x);
          transformed = BTree.transformAndFilter(original, function);
          Assert.assertEquals(BTree.size(original), function.count);
          assertSame(transform(selection.canonicalList, function.wrapped), iterable(transformed));

          // test replacing some, removing some
          function = new CountingFunction(update::get);
          transformed = BTree.transformAndFilter(original, function);
          Assert.assertEquals(BTree.size(original), function.count);
          assertSame(
              filter(transform(selection.canonicalList, function.wrapped), notNull()),
              iterable(transformed));

          // test replacing none, removing some
          function = new CountingFunction((x) -> update.containsKey(x) ? null : x);
          transformed = BTree.transformAndFilter(selection.testAsList.tree(), function);
          Assert.assertEquals(BTree.size(original), function.count);
          assertSame(
              filter(transform(selection.canonicalList, function.wrapped), notNull()),
              iterable(transformed));
        });
  }
 BTreeRange(
     Object[] tree,
     Comparator<? super V> comparator,
     V lowerBound,
     boolean inclusiveLowerBound,
     V upperBound,
     boolean inclusiveUpperBound) {
   this(
       tree,
       comparator,
       lowerBound == null
           ? 0
           : inclusiveLowerBound
               ? BTree.ceilIndex(tree, comparator, lowerBound)
               : BTree.higherIndex(tree, comparator, lowerBound),
       upperBound == null
           ? BTree.size(tree) - 1
           : inclusiveUpperBound
               ? BTree.floorIndex(tree, comparator, upperBound)
               : BTree.lowerIndex(tree, comparator, upperBound));
 }
 @Override
 public int size() {
   return BTree.size(tree);
 }