code: protected <E> List<E> merge(final List<E> leftElements, final List<E> rightElements) {
      int leftIndex = 0;
      int leftSize = leftElements.size();
      int rightIndex = 0;
      int rightSize = rightElements.size();
  
      List<E> mergedElements = new ArrayList<>(leftSize + rightSize);
  
      for (int mergeIndex = 0, mergeSize = (leftSize + rightSize); mergeIndex < mergeSize; mergeIndex++) {
        if (leftIndex == leftSize) {
          mergedElements.add(rightElements.get(rightIndex++));
        }
        else if (rightIndex == rightSize) {
          mergedElements.add(leftElements.get(leftIndex++));
        }
        else {
          E leftElement = leftElements.get(leftIndex);
          E rightElement = rightElements.get(rightIndex);
  
          if (getOrderBy().compare(leftElement, rightElement) <= 0) {
            mergedElements.add(leftElement);
            leftIndex++;
          }
          else {
            mergedElements.add(rightElement);
            rightIndex++;
          }
        }
      }
  
      return mergedElements;
    }
docs: TODO solve the ArrayList allocation (memory resource consumption) problem