
org.jooq.lambda.WindowImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jool Show documentation
Show all versions of jool Show documentation
jOOλ is part of the jOOQ series (along with jOOQ, jOOX, jOOR, jOOU) providing some useful extensions to Java 8 lambdas.
/**
* Copyright (c) 2014-2016, Data Geekery GmbH, [email protected]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jooq.lambda;
import java.util.Collection;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.comparing;
import static java.util.Collections.binarySearch;
import static org.jooq.lambda.Seq.seq;
import static org.jooq.lambda.tuple.Tuple.tuple;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.jooq.lambda.tuple.Tuple2;
/**
* @author Lukas Eder
*/
class WindowImpl implements Window {
final Tuple2 value;
final int index;
final Partition partition;
final Comparator super T> order;
final long lower;
final long upper;
@SuppressWarnings({ "unchecked" })
WindowImpl(
Tuple2 value,
Partition partition,
WindowSpecification specification
) {
this.value = value;
this.partition = partition;
this.order = specification.order().orElse((Comparator super T>) naturalOrder());
this.lower = specification.lower();
this.upper = specification.upper();
int i = specification.order().isPresent()
? binarySearch(partition.list, value, comparing((Tuple2 t) -> t.v1, specification.order().get()).thenComparing(t -> t.v2))
: binarySearch(partition.list, value, comparing(t -> t.v2));
this.index = (i >= 0 ? i : -i - 1);
}
// Accessor methods
// -------------------------------------------------------------------------
@Override
public T value() {
return value.v1;
}
@Override
public Seq window() {
return Seq.seq(partition.list.subList(lower(), upper() + 1)).map(t -> t.v1);
}
// Utilities
// -------------------------------------------------------------------------
private int lower() {
// TODO: What about under/overflows?
return lower == Long.MIN_VALUE ? 0 : (int) Math.max(0L, index + lower);
}
private boolean lowerInPartition() {
// TODO: What about under/overflows?
return lower == Long.MIN_VALUE || (index + lower >= 0L && index + lower < partition.list.size());
}
private int upper() {
// TODO: What about under/overflows?
return upper == Long.MAX_VALUE ? partition.list.size() - 1 : (int) Math.min(partition.list.size() - 1, (index + upper));
}
private boolean upperInPartition() {
// TODO: What about under/overflows?
return upper == Long.MAX_VALUE || (index + upper >= 0L && index + upper < partition.list.size());
}
private boolean completePartition() {
return count() == partition.list.size();
}
// Ranking functions
// -------------------------------------------------------------------------
@Override
public long rowNumber() {
return (long) index;
}
@Override
public long rank() {
return seq(partition.list).map(t -> t.v1).collect(Agg.rank(value.v1, order)).get();
}
@Override
public long denseRank() {
return seq(partition.list).map(t -> t.v1).collect(Agg.denseRank(value.v1, order)).get();
}
@Override
public double percentRank() {
return ((double) rank()) / ((double) (partition.list.size() - 1));
}
@Override
public long ntile(long bucket) {
return (bucket * rowNumber() / partition.list.size());
}
@Override
public Optional lead() {
return lead(1);
}
@Override
public Optional lead(long lead) {
return lead0(lead);
}
@Override
public Optional lag() {
return lag(1);
}
@Override
public Optional lag(long lag) {
return lead0(-lag);
}
private Optional lead0(long lead) {
if (lead == 0)
return Optional.of(value.v1);
else if (index + lead >= 0 && index + lead < partition.list.size())
return Optional.of(partition.list.get(index + (int) lead).v1);
else
return Optional.empty();
}
@Override
public Optional firstValue() {
return firstValue(t -> t);
}
@Override
public Optional firstValue(Function super T, ? extends U> function) {
return lowerInPartition()
? Optional.of(function.apply(partition.list.get(lower()).v1))
: upperInPartition()
? Optional.of(function.apply(partition.list.get(0).v1))
: Optional.empty();
}
@Override
public Optional lastValue() {
return lastValue(t -> t);
}
@Override
public Optional lastValue(Function super T, ? extends U> function) {
return upperInPartition()
? Optional.of(function.apply(partition.list.get(upper()).v1))
: lowerInPartition()
? Optional.of(function.apply(partition.list.get(partition.list.size() - 1).v1))
: Optional.empty();
}
@Override
public Optional nthValue(long n) {
return nthValue(n, t -> t);
}
@Override
public Optional nthValue(long n, Function super T, ? extends U> function) {
return lower() + n <= upper()
? Optional.of(function.apply(partition.list.get(lower() + (int) n).v1))
: Optional.empty();
}
// Aggregate functions
// -------------------------------------------------------------------------
@Override
public long count() {
return 1 + upper() - lower();
}
@Override
public long count(Predicate super T> predicate) {
return partition.cacheIf(completePartition(), tuple("count", predicate), () -> window().count(predicate));
}
@Override
public long countDistinct() {
return partition.cacheIf(completePartition(), "countDistinct", () -> window().countDistinct());
}
@Override
public long countDistinct(Predicate super T> predicate) {
return partition.cacheIf(completePartition(), tuple("countDistinct", predicate), () -> window().countDistinct(predicate));
}
@Override
public long countDistinctBy(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("countDistinctBy", function), () -> window().countDistinctBy(function));
}
@Override
public long countDistinctBy(Function super T, ? extends U> function, Predicate super U> predicate) {
return partition.cacheIf(completePartition(), tuple("countDistinctBy", function, predicate), () -> window().countDistinctBy(function, predicate));
}
@Override
public Optional sum() {
return partition.cacheIf(completePartition(), "sum", () -> window().sum());
}
@Override
public Optional sum(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("sum", function), () -> window().sum(function));
}
@Override
public int sumInt(ToIntFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("sumInt", function), () -> window().sumInt(function));
}
@Override
public long sumLong(ToLongFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("sumLong", function), () -> window().sumLong(function));
}
@Override
public double sumDouble(ToDoubleFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("sumDouble", function), () -> window().sumDouble(function));
}
@Override
public Optional avg() {
return partition.cacheIf(completePartition(), "avg", () -> window().avg());
}
@Override
public Optional avg(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("avg", function), () -> window().avg(function));
}
@Override
public double avgInt(ToIntFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("avgInt", function), () -> window().avgInt(function));
}
@Override
public double avgLong(ToLongFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("avgLong", function), () -> window().avgLong(function));
}
@Override
public double avgDouble(ToDoubleFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("avgDouble", function), () -> window().avgDouble(function));
}
@Override
@SuppressWarnings("unchecked")
public Optional min() {
return partition.cacheIf(completePartition(), "min", () -> window().min((Comparator) naturalOrder()));
}
@Override
public Optional min(Comparator super T> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("min", comparator), () -> window().min(comparator));
}
@Override
public > Optional min(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("min", function), () -> window().min(function));
}
@Override
public Optional min(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("min", function, comparator), () -> window().min(function, comparator));
}
@Override
public > Optional minBy(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("minBy", function), () -> window().minBy(function));
}
@Override
public Optional minBy(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("minBy", function, comparator), () -> window().minBy(function, comparator));
}
@Override
@SuppressWarnings("unchecked")
public Seq minAll() {
return partition.cacheIf(completePartition(), "minAll", () -> window().minAll((Comparator) naturalOrder()));
}
@Override
public Seq minAll(Comparator super T> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("minAll", comparator), () -> window().minAll(comparator));
}
@Override
public > Seq minAll(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("minAll", function), () -> window().minAll(function));
}
@Override
public Seq minAll(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("minAll", function, comparator), () -> window().minAll(function, comparator));
}
@Override
public > Seq minAllBy(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("minAllBy", function), () -> window().minAllBy(function));
}
@Override
public Seq minAllBy(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("minAllBy", function, comparator), () -> window().minAllBy(function, comparator));
}
@Override
@SuppressWarnings("unchecked")
public Optional max() {
return partition.cacheIf(completePartition(), "max", () -> window().max((Comparator) naturalOrder()));
}
@Override
public Optional max(Comparator super T> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("max", comparator), () -> window().max(comparator));
}
@Override
public > Optional max(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("max", function), () -> window().max(function));
}
@Override
public Optional max(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("max", function, comparator), () -> window().max(function, comparator));
}
@Override
public > Optional maxBy(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("maxBy", function), () -> window().maxBy(function));
}
@Override
public Optional maxBy(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("maxBy", function, comparator), () -> window().maxBy(function, comparator));
}
@Override
@SuppressWarnings("unchecked")
public Seq maxAll() {
return partition.cacheIf(completePartition(), "maxAll", () -> window().maxAll((Comparator) naturalOrder()));
}
@Override
public Seq maxAll(Comparator super T> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("maxAll", comparator), () -> window().maxAll(comparator));
}
@Override
public > Seq maxAll(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("maxAll", function), () -> window().maxAll(function));
}
@Override
public Seq maxAll(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("maxAll", function, comparator), () -> window().maxAll(function, comparator));
}
@Override
public > Seq maxAllBy(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("maxAllBy", function), () -> window().maxAllBy(function));
}
@Override
public Seq maxAllBy(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("maxAllBy", function, comparator), () -> window().maxAllBy(function, comparator));
}
@Override
@SuppressWarnings("unchecked")
public Optional median() {
return partition.cacheIf(completePartition(), "median", () -> window().median((Comparator) naturalOrder()));
}
@Override
public Optional median(Comparator super T> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("median", comparator), () -> window().median(comparator));
}
@Override
public > Optional medianBy(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("medianBy", function), () -> window().medianBy(function));
}
@Override
public Optional medianBy(Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("medianBy", function, comparator), () -> window().medianBy(function, comparator));
}
@Override
@SuppressWarnings("unchecked")
public Optional percentile(double percentile) {
return partition.cacheIf(completePartition(), () -> tuple("percentile", percentile), () -> window().percentile(percentile, (Comparator) naturalOrder()));
}
@Override
public Optional percentile(double percentile, Comparator super T> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("percentile", percentile, comparator), () -> window().percentile(percentile, comparator));
}
@Override
public > Optional percentileBy(double percentile, Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("percentileBy", percentile, function), () -> window().percentileBy(percentile, function));
}
@Override
public Optional percentileBy(double percentile, Function super T, ? extends U> function, Comparator super U> comparator) {
return partition.cacheIf(completePartition(), () -> tuple("percentileBy", percentile, function, comparator), () -> window().percentileBy(percentile, function, comparator));
}
@Override
public Optional mode() {
return partition.cacheIf(completePartition(), "mode", () -> window().mode());
}
@Override
public Optional modeBy(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), tuple("modeBy", function), () -> window().modeBy(function));
}
@Override
public Seq modeAll() {
return partition.cacheIf(completePartition(), "modeAll", () -> window().modeAll());
}
@Override
public Seq modeAllBy(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), tuple("modeAllBy", function), () -> window().modeAllBy(function));
}
@Override
public boolean allMatch(Predicate super T> predicate) {
return partition.cacheIf(completePartition(), () -> tuple("allMatch", predicate), () -> window().allMatch(predicate));
}
@Override
public boolean anyMatch(Predicate super T> predicate) {
return partition.cacheIf(completePartition(), () -> tuple("anyMatch", predicate), () -> window().anyMatch(predicate));
}
@Override
public boolean noneMatch(Predicate super T> predicate) {
return partition.cacheIf(completePartition(), () -> tuple("noneMatch", predicate), () -> window().noneMatch(predicate));
}
@Override
public Optional bitAnd() {
return partition.cacheIf(completePartition(), () -> tuple("bitAnd"), () -> window().bitAnd());
}
@Override
public Optional bitAnd(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("bitAnd", function), () -> window().bitAnd(function));
}
@Override
public int bitAndInt(ToIntFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("bitAndInt", function), () -> window().bitAndInt(function));
}
@Override
public long bitAndLong(ToLongFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("bitAndLong", function), () -> window().bitAndLong(function));
}
@Override
public Optional bitOr() {
return partition.cacheIf(completePartition(), () -> tuple("bitOr"), () -> window().bitOr());
}
@Override
public Optional bitOr(Function super T, ? extends U> function) {
return partition.cacheIf(completePartition(), () -> tuple("bitOr", function), () -> window().bitOr(function));
}
@Override
public int bitOrInt(ToIntFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("bitOrInt", function), () -> window().bitOrInt(function));
}
@Override
public long bitOrLong(ToLongFunction super T> function) {
return partition.cacheIf(completePartition(), () -> tuple("bitOrLong", function), () -> window().bitOrLong(function));
}
@Override
public R collect(Collector super T, A, R> collector) {
return partition.cacheIf(completePartition(), () -> tuple("collect", collector), () -> window().collect(collector));
}
@Override
public List toList() {
return partition.cacheIf(completePartition(), "toList", () -> window().toList());
}
@Override
public > L toList(Supplier factory) {
return partition.cacheIf(completePartition(), () -> tuple("toList", factory), () -> window().toList(factory));
}
@Override
public Set toSet() {
return partition.cacheIf(completePartition(), "toSet", () -> window().toSet());
}
@Override
public > S toSet(Supplier factory) {
return partition.cacheIf(completePartition(), () -> tuple("toSet", factory), () -> window().toSet(factory));
}
@Override
public > C toCollection(Supplier factory) {
return partition.cacheIf(completePartition(), () -> tuple("toCollection", factory), () -> window().toCollection(factory));
}
@Override
public Map toMap(Function super T, ? extends K> keyMapper, Function super T, ? extends V> valueMapper) {
return partition.cacheIf(completePartition(), () -> tuple("toMap", keyMapper, valueMapper), () -> window().toMap(keyMapper, valueMapper));
}
@Override
public Map toMap(Function super T, ? extends K> keyMapper) {
return toMap(keyMapper, Function.identity());
}
@Override
public String toString() {
return partition.cacheIf(completePartition(), "toString", () -> window().toString());
}
@Override
public String toString(CharSequence delimiter) {
return partition.cacheIf(completePartition(), () -> tuple("toString", delimiter), () -> Seq.toString(window(), delimiter));
}
@Override
public String toString(CharSequence delimiter, CharSequence prefix, CharSequence suffix) {
return partition.cacheIf(completePartition(), () -> tuple("toString", delimiter, prefix, suffix), () -> window().map(Objects::toString).collect(Collectors.joining(delimiter, prefix, suffix)));
}
@Override
public String commonPrefix() {
return partition.cacheIf(completePartition(), () -> "commonPrefix", () -> window().commonPrefix());
}
@Override
public String commonSuffix() {
return partition.cacheIf(completePartition(), () -> "commonSuffix", () -> window().commonSuffix());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy