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

javaslang.collection.LinearSeq Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
/*     / \____  _    _  ____   ______  / \ ____  __    _______
 *    /  /    \/ \  / \/    \ /  /\__\/  //    \/  \  //  /\__\   JΛVΛSLΛNG
 *  _/  /  /\  \  \/  /  /\  \\__\\  \  //  /\  \ /\\/ \ /__\ \   Copyright 2014-2016 Javaslang, http://javaslang.io
 * /___/\_/  \_/\____/\_/  \_/\__\/__/\__\_/  \_//  \__/\_____/   Licensed under the Apache License, Version 2.0
 */
package javaslang.collection;

import javaslang.Tuple;
import javaslang.Tuple2;
import javaslang.control.Option;

import java.util.Comparator;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;

/**
 * Interface for immutable, linear sequences.
 * 

* Efficient {@code head()}, {@code tail()}, and {@code isEmpty()} methods are characteristic for linear sequences. * * @param component type * @author Daniel Dietrich * @since 2.0.0 */ public interface LinearSeq extends Seq { long serialVersionUID = 1L; /** * Narrows a widened {@code LinearSeq} to {@code LinearSeq} * by performing a type safe-cast. This is eligible because immutable/read-only * collections are covariant. * * @param linearSeq A {@code LinearSeq}. * @param Component type of the {@code LinearSeq}. * @return the given {@code linearSeq} instance as narrowed type {@code LinearSeq}. */ @SuppressWarnings("unchecked") static LinearSeq narrow(LinearSeq linearSeq) { return (LinearSeq) linearSeq; } // -- Adjusted return types of Seq methods @Override LinearSeq append(T element); @Override LinearSeq appendAll(Iterable elements); @Override LinearSeq> combinations(); @Override LinearSeq> combinations(int k); @Override Iterator> crossProduct(int power); @Override LinearSeq distinct(); @Override LinearSeq distinctBy(Comparator comparator); @Override LinearSeq distinctBy(Function keyExtractor); @Override LinearSeq drop(long n); @Override LinearSeq dropRight(long n); @Override LinearSeq dropUntil(Predicate predicate); @Override LinearSeq dropWhile(Predicate predicate); @Override LinearSeq filter(Predicate predicate); @Override LinearSeq flatMap(Function> mapper); @Override Map> groupBy(Function classifier); @Override Iterator> grouped(long size); @Override default int indexWhere(Predicate predicate, int from) { Objects.requireNonNull(predicate, "predicate is null"); int i = from; LinearSeq these = drop(from); while (!these.isEmpty()) { if (predicate.test(these.head())) { return i; } i++; these = these.tail(); } return -1; } @Override LinearSeq init(); @Override Option> initOption(); @Override LinearSeq insert(int index, T element); @Override LinearSeq insertAll(int index, Iterable elements); @Override LinearSeq intersperse(T element); @Override default int lastIndexOfSlice(Iterable that, int end) { return LinearSeqModule.LastIndexOfSlice.lastIndexOfSlice(this, unit(that), end); } @Override default int lastIndexWhere(Predicate predicate, int end) { Objects.requireNonNull(predicate, "predicate is null"); int i = 0; LinearSeq these = this; int last = -1; while (!these.isEmpty() && i <= end) { if (predicate.test(these.head())) { last = i; } these = these.tail(); i++; } return last; } @Override LinearSeq map(Function mapper); @Override LinearSeq padTo(int length, T element); @Override LinearSeq patch(int from, Iterable that, int replaced); @Override Tuple2, ? extends LinearSeq> partition(Predicate predicate); @Override LinearSeq peek(Consumer action); @Override LinearSeq> permutations(); @Override LinearSeq prepend(T element); @Override LinearSeq prependAll(Iterable elements); @Override LinearSeq remove(T element); @Override LinearSeq removeFirst(Predicate predicate); @Override LinearSeq removeLast(Predicate predicate); @Override LinearSeq removeAt(int index); @Override LinearSeq removeAll(T element); @Override LinearSeq removeAll(Iterable elements); @Override LinearSeq replace(T currentElement, T newElement); @Override LinearSeq replaceAll(T currentElement, T newElement); @Override LinearSeq retainAll(Iterable elements); @Override LinearSeq reverse(); @Override default Iterator reverseIterator() { return reverse().iterator(); } @Override LinearSeq scan(T zero, BiFunction operation); @Override LinearSeq scanLeft(U zero, BiFunction operation); @Override LinearSeq scanRight(U zero, BiFunction operation); @Override default int segmentLength(Predicate predicate, int from) { Objects.requireNonNull(predicate, "predicate is null"); int i = 0; LinearSeq these = this.drop(from); while (!these.isEmpty() && predicate.test(these.head())) { i++; these = these.tail(); } return i; } @Override LinearSeq slice(long beginIndex, long endIndex); @Override Iterator> sliding(long size); @Override Iterator> sliding(long size, long step); @Override LinearSeq sorted(); @Override LinearSeq sorted(Comparator comparator); @Override > LinearSeq sortBy(Function mapper); @Override LinearSeq sortBy(Comparator comparator, Function mapper); @Override Tuple2, ? extends LinearSeq> span(Predicate predicate); @Override LinearSeq subSequence(int beginIndex); @Override LinearSeq subSequence(int beginIndex, int endIndex); @Override LinearSeq tail(); @Override Option> tailOption(); @Override LinearSeq take(long n); @Override LinearSeq takeRight(long n); @Override LinearSeq takeUntil(Predicate predicate); @Override LinearSeq takeWhile(Predicate predicate); @Override LinearSeq unit(Iterable iterable); @Override Tuple2, ? extends LinearSeq> unzip(Function> unzipper); @Override LinearSeq update(int index, T element); @Override LinearSeq> zip(Iterable that); @Override LinearSeq> zipAll(Iterable that, T thisElem, U thatElem); @Override LinearSeq> zipWithIndex(); /** * Searches this sequence for a specific element using a linear search. The sequence must already be sorted into * ascending natural order. If it is not sorted, the results are undefined. * * @param element the element to find * @return the index of the search element, if it is contained in the sequence; * otherwise, (-(insertion point) - 1). The * insertion point is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. * @throws ClassCastException if T cannot be cast to {@code Comparable} */ @Override @SuppressWarnings("unchecked") default int search(T element) { ToIntFunction comparison = current -> { Comparable comparable = (Comparable) element; return comparable.compareTo(current); }; return LinearSeqModule.Search.linearSearch(this, comparison); } /** * Searches this sequence for a specific element using a linear search. The sequence must already be sorted into * ascending order according to the specified comparator. If it is not sorted, the results are undefined. * * @param element the element to find * @param comparator the comparator by which this sequence is ordered * @return the index of the search element, if it is contained in the sequence; * otherwise, (-(insertion point) - 1). The * insertion point is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. */ @Override default int search(T element, Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); ToIntFunction comparison = current -> comparator.compare(element, current); return LinearSeqModule.Search.linearSearch(this, comparison); } } interface LinearSeqModule { interface LastIndexOfSlice { static int lastIndexOfSlice(LinearSeq t, LinearSeq slice, int end) { if (end < 0) { return -1; } if (t.isEmpty()) { return slice.isEmpty() ? 0 : -1; } if (slice.isEmpty()) { int len = t.length(); return len < end ? len : end; } int p = 0; int result = -1; while (t.length() >= slice.length()) { Tuple2, Integer> r = findSlice(t, slice); if (r == null) { return result; } if (p + r._2 <= end) { result = p + r._2; p += r._2 + 1; t = r._1.tail(); } else { return result; } } return result; } static Tuple2, Integer> findSlice(LinearSeq t, LinearSeq slice) { int p = 0; while (t.length() >= slice.length()) { if (t.startsWith(slice)) { return Tuple.of(t, p); } p++; t = t.tail(); } return null; } } interface Search { static int linearSearch(LinearSeq seq, ToIntFunction comparison) { int idx = 0; for (T current : seq) { int cmp = comparison.applyAsInt(current); if (cmp == 0) { return idx; } else if (cmp < 0) { return -(idx + 1); } idx += 1; } return -(idx + 1); } } }