Files
Android-pyApi/android_pyapi/java/util_stream.py
T
shuiyu1123 a51854455b feat: 大规模扩充至212个模块/175K行代码 — 覆盖android/java/javax/org/dalvik全包
- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等)
- java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等)
- javax/ 4个模块 (net/crypto/security/sql)
- org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http)
- dalvik/ 1个模块 (system)
- ~3053个类/接口,方法签名完全对齐Android SDK
- 桌面跨平台运行 (Windows/macOS/Linux)
- 修复所有导入错误和Python关键字冲突
2026-06-24 14:15:56 +00:00

1380 lines
37 KiB
Python

"""
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