All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.lacuna.bifurcan.IList Maven / Gradle / Ivy

package io.lacuna.bifurcan;

import io.lacuna.bifurcan.Lists.VirtualList;

import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.LongFunction;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * @author ztellman
 */
@SuppressWarnings("unchecked")
public interface IList extends
  ISplittable>,
  Iterable,
  IForkable>,
  ILinearizable> {

  /**
   * @return the element at {@code idx}
   * @throws IndexOutOfBoundsException when {@code idx} is not within {@code [0, size-1]}
   */
  V nth(long idx);

  /**
   * @return the element at {@code idx}, or {@code defaultValue} if it is not within {@code [0, size-1]}
   */
  default V nth(long idx, V defaultValue) {
    if (idx < 0 || idx >= size()) {
      return defaultValue;
    }
    return nth(idx);
  }

  /**
   * @return the length of the list
   */
  long size();

  default IList update(long idx, Function updateFn) {
    return set(idx, updateFn.apply(nth(idx)));
  }

  /**
   * @return true, if the list is linear
   */
  default boolean isLinear() {
    return false;
  }

  /**
   * @return a new list, with {@code value} appended
   */
  default IList addLast(V value) {
    return new VirtualList<>(this).addLast(value);
  }

  /**
   * @return a new list, with {@code value} prepended
   */
  default IList addFirst(V value) {
    return new VirtualList<>(this).addFirst(value);
  }

  /**
   * @return a new list with the last value removed, or the same list if already empty
   */
  default IList removeLast() {
    return new VirtualList(this).removeLast();
  }

  /**
   * @return a new list with the first value removed, or the same value if already empty
   */
  default IList removeFirst() {
    return new VirtualList(this).removeFirst();
  }

  /**
   * @return a new list, with the element at {@code idx} overwritten with {@code value}. If {@code idx} is equal to {@code size()}, the value is appended.
   * @throws IndexOutOfBoundsException when {@code idx} is not within {@code [0, count]}
   */
  default IList set(long idx, V value) {
    return new VirtualList(this).set(idx, value);
  }

  /**
   * @return a {@code java.util.stream.Stream}, representing the elements in the list
   */
  default Stream stream() {
    return StreamSupport.stream(spliterator(), false);
  }

  @Override
  default Spliterator spliterator() {
    return Spliterators.spliterator(iterator(), size(), Spliterator.ORDERED);
  }

  default Iterator iterator() {
    return Lists.iterator(this);
  }

  /**
   * @return the elements of the list, in an array
   */
  default Object[] toArray() {
    Object[] ary = new Object[(int) size()];
    IntStream.range(0, ary.length).forEach(i -> ary[i] = nth(i));
    return ary;
  }

  /**
   * @param allocator a function which creates an array of the specified size
   * @return the elements of the list, in a typed array
   */
  default V[] toArray(IntFunction allocator) {
    V[] ary = allocator.apply((int) size());
    for (int i = 0; i < ary.length; i++) {
      ary[i] = nth(i);
    }
    return ary;
  }

  /**
   * @return the collection, represented as a normal Java {@code ListNodes}, which will throw an {@code UnsupportedOperationException} for any write
   */
  default java.util.List toList() {
    return Lists.toList(this);
  }

  @Override
  default IList> split(int parts) {
    parts = Math.max(1, Math.min((int) size(), parts));
    IList[] ary = new IList[parts];

    long subSize = size() / parts;
    long offset = 0;
    for (int i = 0; i < parts; i++) {
      ary[i] = Lists.slice(this, offset, i == (parts - 1) ? size() : offset + subSize);
      offset += subSize;
    }

    return Lists.from(ary);
  }

  /**
   * @param start the inclusive start of the range
   * @param end   the exclusive end of the range
   * @return a read-only view into this sub-range of the list
   */
  default IList slice(long start, long end) {
    return Lists.slice(this, start, end);
  }

  /**
   * @param l another list
   * @return a new collection representing the concatenation of the two lists
   */
  default IList concat(IList l) {
    return Lists.concat(this, l);
  }

  /**
   * @return the first element
   * @throws IndexOutOfBoundsException if the collection is empty
   */
  default V first() {
    if (size() == 0) {
      throw new IndexOutOfBoundsException();
    }
    return nth(0);
  }

  /**
   * @return the last element
   * @throws IndexOutOfBoundsException if the collection is empty
   */
  default V last() {
    if (size() == 0) {
      throw new IndexOutOfBoundsException();
    }
    return nth(size() - 1);
  }

  @Override
  default IList forked() {
    return this;
  }

  @Override
  default IList linear() {
    return new VirtualList(this).linear();
  }

  IList clone();

  default boolean equals(Object o, BiPredicate equals) {
    if (o instanceof IList) {
      return Lists.equals(this, (IList) o, equals);
    }
    return false;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy