""" Java java.util.stream standard library APIs implemented in Python. java.util.stream package - Stream, IntStream, LongStream, DoubleStream, Collectors, etc. """ from __future__ import annotations from .._core import Stub from ..java.util import Optional, NoSuchElementException from ..java.lang import RuntimeException import typing as _typing import itertools as _itertools import functools as _functools import math as _py_math __all__ = [ "Stream", "IntStream", "LongStream", "DoubleStream", "Collector", "Collectors", "StreamSupport", "BaseStream", "Sink", "TerminalOp", "TerminalSink", "AbstractPipeline", "ReferencePipeline", "IntPipeline", "LongPipeline", "DoublePipeline", "SliceOps", "WhileOps", "DistinctOps", "SortedOps", "FindOps", "MatchOps", "ReduceOps", "ForEachOps", "MapOps", "FilterOps", "FlatMapOps", "PeekOps", ] T = _typing.TypeVar("T") R = _typing.TypeVar("R") A = _typing.TypeVar("A") # ============================================================ # BaseStream # ============================================================ class BaseStream(Stub): """java.util.stream.BaseStream""" def __init__(self): super().__init__() self._closed = False self._parallel = False def iterator(self): raise NotImplementedError def spliterator(self): raise NotImplementedError def isParallel(self): return self._parallel def sequential(self): self._parallel = False return self def parallel(self): self._parallel = True return self def unordered(self): return self def onClose(self, close_handler): return self def close(self): self._closed = True # ============================================================ # Builder # ============================================================ class StreamBuilder(Stub): """java.util.stream.Stream.Builder""" def __init__(self): super().__init__() self._elements = [] def accept(self, t): self._elements.append(t) def add(self, t): self._elements.append(t) return self def build(self): return Stream(self._elements[:]) def toString(self): return "Stream.Builder" class IntStreamBuilder(Stub): """java.util.stream.IntStream.Builder""" def __init__(self): super().__init__() self._elements = [] def accept(self, t): self._elements.append(int(t)) def add(self, t): self._elements.append(int(t)) return self def build(self): return IntStream(self._elements[:]) class LongStreamBuilder(Stub): """java.util.stream.LongStream.Builder""" def __init__(self): super().__init__() self._elements = [] def accept(self, t): self._elements.append(int(t)) def add(self, t): self._elements.append(int(t)) return self def build(self): return LongStream(self._elements[:]) class DoubleStreamBuilder(Stub): """java.util.stream.DoubleStream.Builder""" def __init__(self): super().__init__() self._elements = [] def accept(self, t): self._elements.append(float(t)) def add(self, t): self._elements.append(float(t)) return self def build(self): return DoubleStream(self._elements[:]) # ============================================================ # Stream # ============================================================ class Stream(BaseStream): """java.util.stream.Stream""" def __init__(self, data=None): super().__init__() self._data = list(data) if data is not None else [] self._intermediate_ops = [] def filter(self, predicate): result = [x for x in self._get_data() if predicate.test(x)] return Stream(result) def map(self, mapper): result = [mapper.apply(x) for x in self._get_data()] return Stream(result) def mapToInt(self, mapper): result = [mapper.applyAsInt(x) for x in self._get_data()] return IntStream(result) def mapToLong(self, mapper): result = [mapper.applyAsLong(x) for x in self._get_data()] return LongStream(result) def mapToDouble(self, mapper): result = [mapper.applyAsDouble(x) for x in self._get_data()] return DoubleStream(result) def flatMap(self, mapper): results = [] for x in self._get_data(): stream = mapper.apply(x) if isinstance(stream, Stream): results.extend(stream._get_data()) elif hasattr(stream, '__iter__'): results.extend(stream) return Stream(results) def distinct(self): seen = set() result = [] for x in self._get_data(): if x not in seen: seen.add(x) result.append(x) return Stream(result) def sorted(self, comparator=None): result = list(self._get_data()) if comparator: from functools import cmp_to_key result.sort(key=cmp_to_key( lambda a, b: comparator.compare(a, b) )) else: result.sort() return Stream(result) def peek(self, action): for x in self._get_data(): action.accept(x) return Stream(self._get_data()) def limit(self, max_size): return Stream(self._get_data()[:max_size]) def skip(self, n): return Stream(self._get_data()[n:]) def forEach(self, action): for x in self._get_data(): action.accept(x) def forEachOrdered(self, action): self.forEach(action) def toArray(self, generator=None): data = self._get_data() if generator is not None: arr = generator.apply(len(data)) for i, x in enumerate(data): arr[i] = x return arr return list(data) def reduce(self, identity_or_accumulator, accumulator=None, combiner=None): data = self._get_data() if accumulator is None: # reduce(BinaryOperator) acc = identity_or_accumulator if not data: return Optional.empty() result = data[0] for x in data[1:]: result = acc.apply(result, x) return Optional.of(result) else: # reduce(identity, accumulator) result = identity_or_accumulator for x in data: result = accumulator.apply(result, x) if combiner: result = combiner.apply(result, result) return result def collect(self, supplier_or_collector, accumulator=None, combiner=None): data = self._get_data() if accumulator is None: return supplier_or_collector # Collector container = supplier_or_collector.get() for x in data: accumulator.accept(container, x) return container def min(self, comparator): data = self._get_data() if not data: return Optional.empty() return Optional.of(min(data, key=_functools.cmp_to_key( lambda a, b: comparator.compare(a, b) ))) def max(self, comparator): data = self._get_data() if not data: return Optional.empty() return Optional.of(max(data, key=_functools.cmp_to_key( lambda a, b: comparator.compare(a, b) ))) def count(self): return len(self._get_data()) def anyMatch(self, predicate): return any(predicate.test(x) for x in self._get_data()) def allMatch(self, predicate): return all(predicate.test(x) for x in self._get_data()) def noneMatch(self, predicate): return not any(predicate.test(x) for x in self._get_data()) def findFirst(self): data = self._get_data() if data: return Optional.of(data[0]) return Optional.empty() def findAny(self): data = self._get_data() if data: return Optional.of(data[0]) return Optional.empty() def flatMapToInt(self, mapper): results = [] for x in self._get_data(): stream = mapper.apply(x) if isinstance(stream, IntStream): results.extend(stream._get_data()) return IntStream(results) def flatMapToLong(self, mapper): results = [] for x in self._get_data(): stream = mapper.apply(x) if isinstance(stream, LongStream): results.extend(stream._get_data()) return LongStream(results) def flatMapToDouble(self, mapper): results = [] for x in self._get_data(): stream = mapper.apply(x) if isinstance(stream, DoubleStream): results.extend(stream._get_data()) return DoubleStream(results) def iterator(self): return iter(self._get_data()) def spliterator(self): return Spliterator(self._get_data()) def isParallel(self): return self._parallel def _get_data(self): return self._data @staticmethod def of(*args): return Stream(list(args)) @staticmethod def empty(): return Stream([]) @staticmethod def concat(a, b): return Stream(list(a._get_data()) + list(b._get_data())) @staticmethod def generate(supplier): return Stream([]) @staticmethod def iterate(seed, has_next_or_predicate, next_fn=None): if next_fn is None: fn = seed return Stream([]) result = [] current = seed while has_next_or_predicate.test(current): result.append(current) current = next_fn.apply(current) return Stream(result) # Nested Builder class class Builder: def __init__(self): self._impl = StreamBuilder() def accept(self, t): self._impl.accept(t) def add(self, t): self._impl.add(t) return self def build(self): return self._impl.build() # ============================================================ # IntStream # ============================================================ class IntStream(BaseStream): """java.util.stream.IntStream""" def __init__(self, data=None): super().__init__() self._data = [int(x) for x in (data or [])] def filter(self, predicate): return IntStream([x for x in self._data if predicate.test(x)]) def map(self, mapper): return IntStream([mapper.applyAsInt(x) for x in self._data]) def mapToObj(self, mapper): return Stream([mapper.apply(x) for x in self._data]) def mapToLong(self, mapper): return LongStream([mapper.applyAsLong(x) for x in self._data]) def mapToDouble(self, mapper): return DoubleStream([mapper.applyAsDouble(x) for x in self._data]) def flatMap(self, mapper): results = [] for x in self._data: stream = mapper.apply(x) if isinstance(stream, IntStream): results.extend(stream._data) return IntStream(results) def distinct(self): return IntStream(list(set(self._data))) def sorted(self): return IntStream(sorted(self._data)) def peek(self, action): for x in self._data: action.accept(x) return IntStream(self._data[:]) def limit(self, max_size): return IntStream(self._data[:max_size]) def skip(self, n): return IntStream(self._data[n:]) def forEach(self, action): for x in self._data: action.accept(x) def forEachOrdered(self, action): self.forEach(action) def toArray(self): return list(self._data) def reduce(self, identity_or_op, op=None): if op is None: if not self._data: return Optional.empty() result = self._data[0] for x in self._data[1:]: result = identity_or_op.applyAsInt(result, x) return Optional.of(result) result = identity_or_op for x in self._data: result = op.applyAsInt(result, x) return result def collect(self, supplier, accumulator, combiner): container = supplier.get() for x in self._data: accumulator.accept(container, x) return container def sum(self): return sum(self._data) def min(self): if not self._data: return Optional.empty() return Optional.of(min(self._data)) def max(self): if not self._data: return Optional.empty() return Optional.of(max(self._data)) def count(self): return len(self._data) def average(self): if not self._data: return Optional.empty() return Optional.of(sum(self._data) / len(self._data)) def summaryStatistics(self): return IntSummaryStatistics(self._data) def anyMatch(self, predicate): return any(predicate.test(x) for x in self._data) def allMatch(self, predicate): return all(predicate.test(x) for x in self._data) def noneMatch(self, predicate): return not any(predicate.test(x) for x in self._data) def findFirst(self): if self._data: return Optional.of(self._data[0]) return Optional.empty() def findAny(self): return self.findFirst() def asDoubleStream(self): return DoubleStream([float(x) for x in self._data]) def asLongStream(self): return LongStream(self._data[:]) def boxed(self): return Stream(self._data[:]) def iterator(self): return iter(self._data) def _get_data(self): return self._data @staticmethod def of(*args): return IntStream(list(args)) @staticmethod def empty(): return IntStream([]) @staticmethod def concat(a, b): return IntStream(list(a._data) + list(b._data)) @staticmethod def range(start, end): return IntStream(list(range(start, end))) @staticmethod def rangeClosed(start, end): return IntStream(list(range(start, end + 1))) @staticmethod def generate(supplier): return IntStream([]) @staticmethod def iterate(seed, has_next, next_fn): return IntStream([]) class Builder: def __init__(self): self._impl = IntStreamBuilder() def accept(self, t): self._impl.accept(t) def add(self, t): self._impl.add(t) return self def build(self): return self._impl.build() # ============================================================ # LongStream # ============================================================ class LongStream(BaseStream): """java.util.stream.LongStream""" def __init__(self, data=None): super().__init__() self._data = [int(x) for x in (data or [])] def filter(self, predicate): return LongStream([x for x in self._data if predicate.test(x)]) def map(self, mapper): return LongStream([mapper.applyAsLong(x) for x in self._data]) def mapToObj(self, mapper): return Stream([mapper.apply(x) for x in self._data]) def mapToInt(self, mapper): return IntStream([mapper.applyAsInt(x) for x in self._data]) def mapToDouble(self, mapper): return DoubleStream([mapper.applyAsDouble(x) for x in self._data]) def flatMap(self, mapper): results = [] for x in self._data: stream = mapper.apply(x) if isinstance(stream, LongStream): results.extend(stream._data) return LongStream(results) def distinct(self): return LongStream(list(set(self._data))) def sorted(self): return LongStream(sorted(self._data)) def peek(self, action): for x in self._data: action.accept(x) return LongStream(self._data[:]) def limit(self, max_size): return LongStream(self._data[:max_size]) def skip(self, n): return LongStream(self._data[n:]) def forEach(self, action): for x in self._data: action.accept(x) def forEachOrdered(self, action): self.forEach(action) def toArray(self): return list(self._data) def reduce(self, identity_or_op, op=None): if op is None: if not self._data: return Optional.empty() result = self._data[0] for x in self._data[1:]: result = identity_or_op.applyAsLong(result, x) return Optional.of(result) result = identity_or_op for x in self._data: result = op.applyAsLong(result, x) return result def sum(self): return sum(self._data) def min(self): if not self._data: return Optional.empty() return Optional.of(min(self._data)) def max(self): if not self._data: return Optional.empty() return Optional.of(max(self._data)) def count(self): return len(self._data) def average(self): if not self._data: return Optional.empty() return Optional.of(sum(self._data) / len(self._data)) def summaryStatistics(self): return LongSummaryStatistics(self._data) def anyMatch(self, predicate): return any(predicate.test(x) for x in self._data) def allMatch(self, predicate): return all(predicate.test(x) for x in self._data) def noneMatch(self, predicate): return not any(predicate.test(x) for x in self._data) def findFirst(self): if self._data: return Optional.of(self._data[0]) return Optional.empty() def findAny(self): return self.findFirst() def asDoubleStream(self): return DoubleStream([float(x) for x in self._data]) def boxed(self): return Stream(self._data[:]) def iterator(self): return iter(self._data) def _get_data(self): return self._data @staticmethod def of(*args): return LongStream(list(args)) @staticmethod def empty(): return LongStream([]) @staticmethod def concat(a, b): return LongStream(list(a._data) + list(b._data)) @staticmethod def range(start, end): return LongStream(list(range(start, end))) @staticmethod def rangeClosed(start, end): return LongStream(list(range(start, end + 1))) class Builder: def __init__(self): self._impl = LongStreamBuilder() def accept(self, t): self._impl.accept(t) def add(self, t): self._impl.add(t) return self def build(self): return self._impl.build() # ============================================================ # DoubleStream # ============================================================ class DoubleStream(BaseStream): """java.util.stream.DoubleStream""" def __init__(self, data=None): super().__init__() self._data = [float(x) for x in (data or [])] def filter(self, predicate): return DoubleStream([x for x in self._data if predicate.test(x)]) def map(self, mapper): return DoubleStream([mapper.applyAsDouble(x) for x in self._data]) def mapToObj(self, mapper): return Stream([mapper.apply(x) for x in self._data]) def mapToInt(self, mapper): return IntStream([mapper.applyAsInt(x) for x in self._data]) def mapToLong(self, mapper): return LongStream([mapper.applyAsLong(x) for x in self._data]) def flatMap(self, mapper): results = [] for x in self._data: stream = mapper.apply(x) if isinstance(stream, DoubleStream): results.extend(stream._data) return DoubleStream(results) def distinct(self): return DoubleStream(list(set(self._data))) def sorted(self): return DoubleStream(sorted(self._data)) def peek(self, action): for x in self._data: action.accept(x) return DoubleStream(self._data[:]) def limit(self, max_size): return DoubleStream(self._data[:max_size]) def skip(self, n): return DoubleStream(self._data[n:]) def forEach(self, action): for x in self._data: action.accept(x) def forEachOrdered(self, action): self.forEach(action) def toArray(self): return list(self._data) def reduce(self, identity_or_op, op=None): if op is None: if not self._data: return Optional.empty() result = self._data[0] for x in self._data[1:]: result = identity_or_op.applyAsDouble(result, x) return Optional.of(result) result = identity_or_op for x in self._data: result = op.applyAsDouble(result, x) return result def sum(self): return sum(self._data) def min(self): if not self._data: return Optional.empty() return Optional.of(min(self._data)) def max(self): if not self._data: return Optional.empty() return Optional.of(max(self._data)) def count(self): return len(self._data) def average(self): if not self._data: return Optional.empty() return Optional.of(sum(self._data) / len(self._data)) def summaryStatistics(self): return DoubleSummaryStatistics(self._data) def anyMatch(self, predicate): return any(predicate.test(x) for x in self._data) def allMatch(self, predicate): return all(predicate.test(x) for x in self._data) def noneMatch(self, predicate): return not any(predicate.test(x) for x in self._data) def findFirst(self): if self._data: return Optional.of(self._data[0]) return Optional.empty() def findAny(self): return self.findFirst() def iterator(self): return iter(self._data) def _get_data(self): return self._data @staticmethod def of(*args): return DoubleStream(list(args)) @staticmethod def empty(): return DoubleStream([]) @staticmethod def concat(a, b): return DoubleStream(list(a._data) + list(b._data)) @staticmethod def generate(supplier): return DoubleStream([]) class Builder: def __init__(self): self._impl = DoubleStreamBuilder() def accept(self, t): self._impl.accept(t) def add(self, t): self._impl.add(t) return self def build(self): return self._impl.build() # ============================================================ # Collector # ============================================================ class Collector(Stub): """java.util.stream.Collector""" class Characteristics: CONCURRENT = "CONCURRENT" UNORDERED = "UNORDERED" IDENTITY_FINISH = "IDENTITY_FINISH" def __init__(self, supplier, accumulator, combiner, finisher=None, characteristics=None): super().__init__() self._supplier = supplier self._accumulator = accumulator self._combiner = combiner self._finisher = finisher self._characteristics = characteristics or [] def supplier(self): return self._supplier def accumulator(self): return self._accumulator def combiner(self): return self._combiner def finisher(self): return self._finisher def characteristics(self): return self._characteristics # ============================================================ # Collectors # ============================================================ class Collectors(Stub): """java.util.stream.Collectors""" @staticmethod def toList(): class ToListCollector(Collector): def __init__(self): s = lambda: [] a = lambda lst, item: lst.append(item) or lst c = lambda l1, l2: l1 + l2 super().__init__(s, a, c) return ToListCollector() @staticmethod def toSet(): class ToSetCollector(Collector): def __init__(self): s = lambda: set() a = lambda st, item: st.add(item) or st c = lambda s1, s2: s1 | s2 super().__init__(s, a, c) return ToSetCollector() @staticmethod def joining(delimiter="", prefix="", suffix=""): class JoiningCollector(Collector): def __init__(self): s = lambda: [] a = lambda lst, item: lst.append(str(item)) or lst c = lambda l1, l2: l1 + l2 f = lambda lst: prefix + delimiter.join(lst) + suffix super().__init__(s, a, c, f) return JoiningCollector() @staticmethod def mapping(mapper, downstream): class MappingCollector(Collector): def __init__(self): s = downstream.supplier() a = lambda container, item: downstream.accumulator()(container, mapper(item)) c = downstream.combiner() f = downstream.finisher() super().__init__(s, a, c, f) return MappingCollector() @staticmethod def filtering(predicate, downstream): class FilteringCollector(Collector): def __init__(self): s = downstream.supplier() a = lambda container, item: ( downstream.accumulator()(container, item) if predicate(item) else container ) c = downstream.combiner() f = downstream.finisher() super().__init__(s, a, c, f) return FilteringCollector() @staticmethod def collectingAndThen(downstream, finisher): class CollectingAndThenCollector(Collector): def __init__(self): s = downstream.supplier() a = downstream.accumulator() c = downstream.combiner() f = lambda result: finisher(downstream.finisher()(result)) if downstream.finisher() else finisher(result) super().__init__(s, a, c, f) return CollectingAndThenCollector() @staticmethod def counting(): class CountingCollector(Collector): def __init__(self): s = lambda: [0] a = lambda cnt, item: [cnt[0] + 1] c = lambda c1, c2: [c1[0] + c2[0]] f = lambda cnt: cnt[0] super().__init__(s, a, c, f) return CountingCollector() @staticmethod def summingInt(mapper): class SummingIntCollector(Collector): def __init__(self): s = lambda: [0] a = lambda total, item: [total[0] + mapper(item)] c = lambda t1, t2: [t1[0] + t2[0]] f = lambda total: total[0] super().__init__(s, a, c, f) return SummingIntCollector() @staticmethod def summingLong(mapper): class SummingLongCollector(Collector): def __init__(self): s = lambda: [0] a = lambda total, item: [total[0] + mapper(item)] c = lambda t1, t2: [t1[0] + t2[0]] f = lambda total: total[0] super().__init__(s, a, c, f) return SummingLongCollector() @staticmethod def summingDouble(mapper): class SummingDoubleCollector(Collector): def __init__(self): s = lambda: [0.0] a = lambda total, item: [total[0] + mapper(item)] c = lambda t1, t2: [t1[0] + t2[0]] f = lambda total: total[0] super().__init__(s, a, c, f) return SummingDoubleCollector() @staticmethod def averagingInt(mapper): class AveragingIntCollector(Collector): def __init__(self): s = lambda: [0, 0] # [sum, count] a = lambda acc, item: [acc[0] + mapper(item), acc[1] + 1] c = lambda a1, a2: [a1[0] + a2[0], a1[1] + a2[1]] f = lambda acc: acc[0] / acc[1] if acc[1] > 0 else 0.0 super().__init__(s, a, c, f) return AveragingIntCollector() @staticmethod def averagingLong(mapper): class AveragingLongCollector(Collector): def __init__(self): s = lambda: [0, 0] a = lambda acc, item: [acc[0] + mapper(item), acc[1] + 1] c = lambda a1, a2: [a1[0] + a2[0], a1[1] + a2[1]] f = lambda acc: acc[0] / acc[1] if acc[1] > 0 else 0.0 super().__init__(s, a, c, f) return AveragingLongCollector() @staticmethod def averagingDouble(mapper): class AveragingDoubleCollector(Collector): def __init__(self): s = lambda: [0.0, 0] a = lambda acc, item: [acc[0] + mapper(item), acc[1] + 1] c = lambda a1, a2: [a1[0] + a2[0], a1[1] + a2[1]] f = lambda acc: acc[0] / acc[1] if acc[1] > 0 else 0.0 super().__init__(s, a, c, f) return AveragingDoubleCollector() @staticmethod def reducing(identity, mapper_or_op, op=None): class ReducingCollector(Collector): def __init__(self): if op is None: s = lambda: [identity] a = lambda acc, item: [acc[0] + mapper_or_op(item)] c = lambda a1, a2: [a1[0] + a2[0]] f = lambda acc: acc[0] else: s = lambda: [identity] a = lambda acc, item: [mapper_or_op.apply(acc[0], item)] c = lambda a1, a2: [a1[0] + a2[0]] f = lambda acc: acc[0] super().__init__(s, a, c, f) return ReducingCollector() @staticmethod def groupingBy(classifier, downstream_or_map_factory=None, downstream=None): class GroupingByCollector(Collector): def __init__(self): s = lambda: {} a = lambda m, item: ( m.setdefault(classifier(item), []).append(item) or m ) c = lambda m1, m2: ( {k: m1.get(k, []) + m2.get(k, []) for k in set(m1) | set(m2)} ) f = None super().__init__(s, a, c, f) return GroupingByCollector() @staticmethod def partitioningBy(predicate, downstream=None): class PartitioningByCollector(Collector): def __init__(self): s = lambda: {True: [], False: []} a = lambda m, item: ( m[True].append(item) if predicate(item) else m[False].append(item) ) or m c = lambda m1, m2: { True: m1[True] + m2[True], False: m1[False] + m2[False] } super().__init__(s, a, c) return PartitioningByCollector() @staticmethod def toMap(key_mapper, value_mapper, merge_function=None, map_supplier=None): class ToMapCollector(Collector): def __init__(self): s = map_supplier or dict a = lambda m, item: ( m.__setitem__(key_mapper(item), value_mapper(item)) or m ) c = lambda m1, m2: {**m1, **m2} super().__init__(s, a, c) return ToMapCollector() # ============================================================ # StreamSupport # ============================================================ class StreamSupport(Stub): """java.util.stream.StreamSupport""" @staticmethod def stream(spliterator, parallel=False): return Stream([]) @staticmethod def intStream(spliterator, parallel=False): return IntStream([]) @staticmethod def longStream(spliterator, parallel=False): return LongStream([]) @staticmethod def doubleStream(spliterator, parallel=False): return DoubleStream([]) # ============================================================ # Spliterator # ============================================================ class Spliterator(Stub): """java.util.Spliterator""" def __init__(self, data): super().__init__() self._data = list(data) self._index = 0 def tryAdvance(self, action): if self._index < len(self._data): action.accept(self._data[self._index]) self._index += 1 return True return False def forEachRemaining(self, action): while self._index < len(self._data): action.accept(self._data[self._index]) self._index += 1 def estimateSize(self): return len(self._data) - self._index def getExactSizeIfKnown(self): return self.estimateSize() def characteristics(self): return 0 ORDERED = 16 DISTINCT = 1 SORTED = 4 SIZED = 64 NONNULL = 256 IMMUTABLE = 1024 CONCURRENT = 4096 SUBSIZED = 16384 # ============================================================ # Summary Statistics # ============================================================ class IntSummaryStatistics(Stub): def __init__(self, data=None): super().__init__() self._data = list(data) if data else [] def getCount(self): return len(self._data) def getSum(self): return sum(self._data) def getMin(self): return min(self._data) if self._data else 0 def getMax(self): return max(self._data) if self._data else 0 def getAverage(self): return sum(self._data) / len(self._data) if self._data else 0.0 def accept(self, value): self._data.append(int(value)) def combine(self, other): self._data.extend(other._data) class LongSummaryStatistics(Stub): def __init__(self, data=None): super().__init__() self._data = list(data) if data else [] def getCount(self): return len(self._data) def getSum(self): return sum(self._data) def getMin(self): return min(self._data) if self._data else 0 def getMax(self): return max(self._data) if self._data else 0 def getAverage(self): return sum(self._data) / len(self._data) if self._data else 0.0 def accept(self, value): self._data.append(int(value)) def combine(self, other): self._data.extend(other._data) class DoubleSummaryStatistics(Stub): def __init__(self, data=None): super().__init__() self._data = list(data) if data else [] def getCount(self): return len(self._data) def getSum(self): return sum(self._data) def getMin(self): return min(self._data) if self._data else 0.0 def getMax(self): return max(self._data) if self._data else 0.0 def getAverage(self): return sum(self._data) / len(self._data) if self._data else 0.0 def accept(self, value): self._data.append(float(value)) def combine(self, other): self._data.extend(other._data) # ============================================================ # Pipeline / Operations stubs # ============================================================ class AbstractPipeline(BaseStream): """java.util.stream.AbstractPipeline""" pass class ReferencePipeline(AbstractPipeline): """java.util.stream.ReferencePipeline""" pass class IntPipeline(AbstractPipeline): """java.util.stream.IntPipeline""" pass class LongPipeline(AbstractPipeline): """java.util.stream.LongPipeline""" pass class DoublePipeline(AbstractPipeline): """java.util.stream.DoublePipeline""" pass class Sink(Stub): """java.util.stream.Sink""" def begin(self, size): pass def end(self): pass def cancellationRequested(self): return False def accept(self, t): pass class TerminalOp(Stub): """java.util.stream.TerminalOp""" pass class TerminalSink(Sink): """java.util.stream.TerminalSink""" def get(self): return None class SliceOps(Stub): """java.util.stream.SliceOps""" pass class WhileOps(Stub): """java.util.stream.WhileOps""" pass class DistinctOps(Stub): """java.util.stream.DistinctOps""" pass class SortedOps(Stub): """java.util.stream.SortedOps""" pass class FindOps(Stub): """java.util.stream.FindOps""" pass class MatchOps(Stub): """java.util.stream.MatchOps""" pass class ReduceOps(Stub): """java.util.stream.ReduceOps""" pass class ForEachOps(Stub): """java.util.stream.ForEachOps""" pass class MapOps(Stub): """java.util.stream.MapOps""" pass class FilterOps(Stub): """java.util.stream.FilterOps""" pass class FlatMapOps(Stub): """java.util.stream.FlatMapOps""" pass class PeekOps(Stub): """java.util.stream.PeekOps""" pass