semantic-typescript 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/readme.cn.md +441 -247
- package/readme.de.md +434 -240
- package/readme.es.md +434 -240
- package/readme.fr.md +434 -240
- package/readme.jp.md +434 -240
- package/readme.kr.md +441 -247
- package/readme.md +434 -240
- package/readme.ru.md +529 -0
- package/readme.tw.md +441 -247
package/readme.es.md
CHANGED
|
@@ -1,335 +1,529 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Framework de Procesamiento de Flujos Semantic-TypeScript
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Proporciona construcciones funcionales compuestas para trabajar con colecciones, flujos y secuencias — con soporte para ordenar, filtrar, agrupar, realizar análisis estadísticos y más.
|
|
3
|
+
## Introducción
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Semantic-TypeScript es una librería moderna de procesamiento de flujos inspirada en GeneratorFunction de JavaScript, Java Stream e Índices de MySQL. La filosofía de diseño central se basa en construir pipelines eficientes de procesamiento de datos mediante indexación de datos, proporcionando una experiencia de operación de streaming en estilo funcional y type-safe para el desarrollo frontend.
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
A diferencia del procesamiento sincrónico tradicional, Semantic emplea un modelo de procesamiento asíncrono. Al crear flujos de datos, el momento de recepción de datos terminales depende completamente de cuándo la corriente superior llama a las funciones callback `accept` e `interrupt`. Este diseño permite que la librería maneje elegantemente flujos de datos en tiempo real, grandes conjuntos de datos y fuentes de datos asíncronas.
|
|
9
8
|
|
|
10
|
-
##
|
|
9
|
+
## Características Principales
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- ✅ Diseño basado en **iteradores y generadores** — ideal para grandes volúmenes o datos asíncronos
|
|
11
|
+
| Característica | Descripción | Ventaja |
|
|
12
|
+
|------|------|------|
|
|
13
|
+
| **Genéricos Type-Safe** | Soporte completo de tipos TypeScript | Detección de errores en tiempo de compilación, mejor experiencia de desarrollo |
|
|
14
|
+
| **Programación Funcional** | Estructuras de datos inmutables y funciones puras | Código más predecible, más fácil de probar y mantener |
|
|
15
|
+
| **Evaluación Perezosa** | Cálculo bajo demanda, optimización de rendimiento | Alta eficiencia de memoria al procesar grandes conjuntos de datos |
|
|
16
|
+
| **Procesamiento Asíncrono de Flujos** | Flujos de datos asíncronos basados en generadores | Adecuado para datos en tiempo real y escenarios orientados a eventos |
|
|
17
|
+
| **Colectores Multi-Paradigma** | Estrategias de recolección ordenadas, desordenadas y estadísticas | Selección de estrategia óptima basada en diferentes escenarios |
|
|
18
|
+
| **Análisis Estadístico** | Funciones completas integradas de cálculo estadístico | Generación integrada de análisis de datos e informes |
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
## Consideraciones de Rendimiento
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
**Nota Importante**: Los siguientes métodos sacrifican rendimiento para recolectar y ordenar datos, resultando en colecciones de datos ordenadas:
|
|
23
|
+
- `toOrdered()`
|
|
24
|
+
- `toWindow()`
|
|
25
|
+
- `toNumericStatistics()`
|
|
26
|
+
- `toBigIntStatistics()`
|
|
27
|
+
- `sorted()`
|
|
28
|
+
- `sorted(comparator)`
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## 🧠 Conceptos clave
|
|
33
|
-
|
|
34
|
-
### 1. `Optional<T>` — Manejo seguro de valores nulos
|
|
35
|
-
|
|
36
|
-
Un contenedor monádico para valores que pueden ser `null` o `undefined`.
|
|
30
|
+
Especialmente importante notar: `sorted()` y `sorted(comparator)` anularán los resultados de los siguientes métodos:
|
|
31
|
+
- `redirect(redirector)`
|
|
32
|
+
- `translate(translator)`
|
|
33
|
+
- `shuffle(mapper)`
|
|
37
34
|
|
|
38
|
-
|
|
35
|
+
## Métodos de Fábrica
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|--------|-------------|---------|
|
|
42
|
-
| `of(value)` | Envolver un valor (puede ser nulo) | `Optional.of(null)` |
|
|
43
|
-
| `ofNullable(v)` | Envolver, permite valores nulos | `Optional.ofNullable(someVar)` |
|
|
44
|
-
| `ofNonNull(v)` | Envolver, lanza excepción si es nulo/undefined | `Optional.ofNonNull(5)` |
|
|
45
|
-
| `get()` | Obtener el valor (o lanzar excepción si está vacío) | `opt.get()` |
|
|
46
|
-
| `getOrDefault(d)` | Obtener el valor o un valor por defecto | `opt.getOrDefault(0)` |
|
|
47
|
-
| `ifPresent(fn)` | Ejecutar un efecto secundario si hay valor | `opt.ifPresent(x => console.log(x))` |
|
|
48
|
-
| `map(fn)` | Transformar el valor si existe | `opt.map(x => x + 1)` |
|
|
49
|
-
| `filter(fn)` | Conservar el valor solo si cumple el predicado | `opt.filter(x => x > 0)` |
|
|
50
|
-
| `isEmpty()` | Verificar si está vacío | `opt.isEmpty()` |
|
|
51
|
-
| `isPresent()` | Verificar si tiene un valor | `opt.isPresent()` |
|
|
37
|
+
### Fábricas de Creación de Flujos
|
|
52
38
|
|
|
53
|
-
|
|
39
|
+
| Método | Firma | Descripción | Ejemplo |
|
|
40
|
+
|------|------|------|------|
|
|
41
|
+
| `blob` | `(blob: Blob, chunk?: bigint) => Semantic<Uint8Array>` | Convertir Blob a flujo de bytes | `blob(fileBlob, 1024n)` |
|
|
42
|
+
| `empty` | `<E>() => Semantic<E>` | Crear flujo vacío | `empty<number>()` |
|
|
43
|
+
| `fill` | `<E>(element: E, count: bigint) => Semantic<E>` | Llenar con número especificado de elementos | `fill("hello", 5n)` |
|
|
44
|
+
| `from` | `<E>(iterable: Iterable<E>) => Semantic<E>` | Crear flujo desde objeto iterable | `from([1, 2, 3])` |
|
|
45
|
+
| `range` | `<N extends number\|bigint>(start: N, end: N, step?: N) => Semantic<N>` | Crear flujo de rango numérico | `range(1, 10, 2)` |
|
|
46
|
+
| `iterate` | `<E>(generator: Generator<E>) => Semantic<E>` | Crear flujo desde función generadora | `iterate(myGenerator)` |
|
|
47
|
+
| `websocket` | `(websocket: WebSocket) => Semantic<MessageEvent>` | Crear flujo de eventos desde WebSocket | `websocket(socket)` |
|
|
54
48
|
|
|
49
|
+
**Suplemento de Ejemplo de Código:**
|
|
55
50
|
```typescript
|
|
56
|
-
import {
|
|
51
|
+
import { from, range, fill, empty } from 'semantic-typescript';
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
// Crear flujo desde array
|
|
54
|
+
const numberStream = from([1, 2, 3, 4, 5]);
|
|
59
55
|
|
|
60
|
-
|
|
56
|
+
// Crear flujo de rango numérico
|
|
57
|
+
const rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
|
|
61
58
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.map(v => v * 2)
|
|
65
|
-
.getOrDefault(0);
|
|
59
|
+
// Llenar con elementos repetidos
|
|
60
|
+
const filledStream = fill("hello", 3n); // "hello", "hello", "hello"
|
|
66
61
|
|
|
67
|
-
|
|
62
|
+
// Crear flujo vacío
|
|
63
|
+
const emptyStream = empty<number>();
|
|
68
64
|
```
|
|
69
65
|
|
|
70
|
-
|
|
66
|
+
### Fábricas de Funciones de Utilidad
|
|
71
67
|
|
|
72
|
-
|
|
68
|
+
| Método | Firma | Descripción | Ejemplo |
|
|
69
|
+
|------|------|------|------|
|
|
70
|
+
| `validate` | `<T>(t: MaybeInvalid<T>) => t is T` | Validar si el valor es válido | `validate(null)` → `false` |
|
|
71
|
+
| `invalidate` | `<T>(t: MaybeInvalid<T>) => t is null\|undefined` | Validar si el valor es inválido | `invalidate(0)` → `false` |
|
|
72
|
+
| `useCompare` | `<T>(t1: T, t2: T) => number` | Función de comparación genérica | `useCompare("a", "b")` → `-1` |
|
|
73
|
+
| `useRandom` | `<T = number\|bigint>(index: T) => T` | Generador de números pseudoaleatorios | `useRandom(5)` → número aleatorio |
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
**Suplemento de Ejemplo de Código:**
|
|
76
|
+
```typescript
|
|
77
|
+
import { validate, invalidate, useCompare, useRandom } from 'semantic-typescript';
|
|
75
78
|
|
|
76
|
-
|
|
79
|
+
// Validar validez de datos
|
|
80
|
+
const data: string | null = "hello";
|
|
81
|
+
if (validate(data)) {
|
|
82
|
+
console.log(data.toUpperCase()); // Llamada segura porque validate asegura que data no es null
|
|
83
|
+
}
|
|
77
84
|
|
|
78
|
-
|
|
85
|
+
const nullData: string | null = null;
|
|
86
|
+
if (invalidate(nullData)) {
|
|
87
|
+
console.log("Datos inválidos"); // Se ejecutará porque invalidate detectó null
|
|
88
|
+
}
|
|
79
89
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
| `from(iterable)` | Crear desde un Array, Set, Iterable | `from([1, 2, 3])` |
|
|
83
|
-
| `range(start, end, step?)` | Generar una secuencia de números | `range(0, 5)` → 0,1,2,3,4 |
|
|
84
|
-
| `fill(element, count)` | Repetir un elemento N veces | `fill('a', 3n)` |
|
|
85
|
-
| `iterate(gen)` | Usar una función generadora personalizada | `iterate(genFn)` |
|
|
90
|
+
// Comparar valores
|
|
91
|
+
const comparison = useCompare("apple", "banana"); // -1
|
|
86
92
|
|
|
87
|
-
|
|
93
|
+
// Generar número aleatorio
|
|
94
|
+
const randomNum = useRandom(42); // Número aleatorio basado en semilla 42
|
|
95
|
+
```
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
|--------|-------------|---------|
|
|
91
|
-
| `map(fn)` | Transformar cada elemento | `.map(x => x * 2)` |
|
|
92
|
-
| `filter(fn)` | Conservar elementos que cumplen el predicado | `.filter(x => x > 10)` |
|
|
93
|
-
| `limit(n)` | Limitar a los primeros N elementos | `.limit(5)` |
|
|
94
|
-
| `skip(n)` | Saltar los primeros N elementos | `.skip(2)` |
|
|
95
|
-
| `distinct()` | Eliminar duplicados (usa Set por defecto) | `.distinct()` |
|
|
96
|
-
| `sorted()` | Ordenar elementos (orden natural) | `.sorted()` |
|
|
97
|
-
| `sorted(comparator)` | Ordenar con un comparador personalizado | `.sorted((a, b) => a - b)` |
|
|
98
|
-
| `toOrdered()` | Ordenar y devolver un `OrderedCollectable` | `.toOrdered()` |
|
|
99
|
-
| `toUnordered()` | **Sin ordenar** — el más rápido | `.toUnordered()` ✅ |
|
|
100
|
-
| `collect(collector)` | Agregar usando un `Collector` | `.collect(Collector.full(...))` |
|
|
101
|
-
| `toArray()` | Convertir a Array | `.toArray()` |
|
|
102
|
-
| `toSet()` | Convertir a Set | `.toSet()` |
|
|
103
|
-
| `toMap(keyFn, valFn)` | Convertir a Map | `.toMap(x => x.id, x => x)` |
|
|
97
|
+
## Detalles de la Clase Principal
|
|
104
98
|
|
|
105
|
-
|
|
99
|
+
### Optional<T> - Manejo Seguro de Valores Nulos
|
|
106
100
|
|
|
107
|
-
|
|
101
|
+
La clase Optional proporciona un enfoque funcional para manejar seguramente valores que pueden ser null o undefined.
|
|
108
102
|
|
|
109
|
-
|
|
103
|
+
| Método | Tipo de Retorno | Descripción | Complejidad Temporal |
|
|
104
|
+
|------|----------|------|------------|
|
|
105
|
+
| `filter(predicate: Predicate<T>)` | `Optional<T>` | Filtrar valores que satisfacen condición | O(1) |
|
|
106
|
+
| `get()` | `T` | Obtener valor, lanza error si está vacío | O(1) |
|
|
107
|
+
| `getOrDefault(defaultValue: T)` | `T` | Obtener valor o valor por defecto | O(1) |
|
|
108
|
+
| `ifPresent(action: Consumer<T>)` | `void` | Ejecutar acción si existe valor | O(1) |
|
|
109
|
+
| `isEmpty()` | `boolean` | Verificar si está vacío | O(1) |
|
|
110
|
+
| `isPresent()` | `boolean` | Verificar si existe valor | O(1) |
|
|
111
|
+
| `map<R>(mapper: Functional<T, R>)` | `Optional<R>` | Mapear y transformar valor | O(1) |
|
|
112
|
+
| `static of<T>(value: MaybeInvalid<T>)` | `Optional<T>` | Crear instancia Optional | O(1) |
|
|
113
|
+
| `static ofNullable<T>(value?)` | `Optional<T>` | Crear Optional nullable | O(1) |
|
|
114
|
+
| `static ofNonNull<T>(value: T)` | `Optional<T>` | Crear Optional no nulo | O(1) |
|
|
110
115
|
|
|
116
|
+
**Suplemento de Ejemplo de Código:**
|
|
111
117
|
```typescript
|
|
112
|
-
|
|
113
|
-
```
|
|
118
|
+
import { Optional } from 'semantic-typescript';
|
|
114
119
|
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
// Crear instancia Optional
|
|
121
|
+
const optionalValue = Optional.ofNullable<string>(Math.random() > 0.5 ? "hello" : null);
|
|
117
122
|
|
|
118
|
-
|
|
123
|
+
// Operaciones en cadena
|
|
124
|
+
const result = optionalValue
|
|
125
|
+
.filter(val => val.length > 3) // Filtrar valores más largos que 3
|
|
126
|
+
.map(val => val.toUpperCase()) // Convertir a mayúsculas
|
|
127
|
+
.getOrDefault("default"); // Obtener valor o por defecto
|
|
119
128
|
|
|
120
|
-
|
|
129
|
+
console.log(result); // "HELLO" o "default"
|
|
121
130
|
|
|
122
|
-
|
|
131
|
+
// Operaciones seguras
|
|
132
|
+
optionalValue.ifPresent(val => {
|
|
133
|
+
console.log(`Valor existe: ${val}`);
|
|
134
|
+
});
|
|
123
135
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
136
|
+
// Verificar estado
|
|
137
|
+
if (optionalValue.isPresent()) {
|
|
138
|
+
console.log("Tiene valor");
|
|
139
|
+
} else if (optionalValue.isEmpty()) {
|
|
140
|
+
console.log("Está vacío");
|
|
141
|
+
}
|
|
128
142
|
```
|
|
129
143
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
144
|
+
### Semantic<E> - Flujo de Datos Perezoso
|
|
145
|
+
|
|
146
|
+
Semantic es la clase principal de procesamiento de flujos, que proporciona operadores ricos de flujos.
|
|
147
|
+
|
|
148
|
+
#### Operaciones de Transformación de Flujos
|
|
149
|
+
|
|
150
|
+
| Método | Tipo de Retorno | Descripción | Impacto en Rendimiento |
|
|
151
|
+
|------|----------|------|----------|
|
|
152
|
+
| `concat(other: Semantic<E>)` | `Semantic<E>` | Concatenar dos flujos | O(n+m) |
|
|
153
|
+
| `distinct()` | `Semantic<E>` | Eliminar duplicados (usando Set) | O(n) |
|
|
154
|
+
| `distinct(comparator)` | `Semantic<E>` | Eliminación de duplicados con comparador personalizado | O(n²) |
|
|
155
|
+
| `dropWhile(predicate)` | `Semantic<E>` | Descartar elementos iniciales que satisfacen condición | O(n) |
|
|
156
|
+
| `filter(predicate)` | `Semantic<E>` | Filtrar elementos | O(n) |
|
|
157
|
+
| `flat(mapper)` | `Semantic<E>` | Aplanar flujos anidados | O(n×m) |
|
|
158
|
+
| `flatMap(mapper)` | `Semantic<R>` | Mapear y aplanar | O(n×m) |
|
|
159
|
+
| `limit(n)` | `Semantic<E>` | Limitar número de elementos | O(n) |
|
|
160
|
+
| `map(mapper)` | `Semantic<R>` | Mapear y transformar elementos | O(n) |
|
|
161
|
+
| `peek(consumer)` | `Semantic<E>` | Ver elementos sin modificación | O(n) |
|
|
162
|
+
| `redirect(redirector)` | `Semantic<E>` | Redirigir índices | O(n) |
|
|
163
|
+
| `reverse()` | `Semantic<E>` | Invertir orden del flujo | O(n) |
|
|
164
|
+
| `shuffle()` | `Semantic<E>` | Barajar orden aleatoriamente | O(n) |
|
|
165
|
+
| `shuffle(mapper)` | `Semantic<E>` | Lógica de barajado personalizada | O(n) |
|
|
166
|
+
| `skip(n)` | `Semantic<E>` | Saltar primeros n elementos | O(n) |
|
|
167
|
+
| `sub(start, end)` | `Semantic<E>` | Obtener subflujo | O(n) |
|
|
168
|
+
| `takeWhile(predicate)` | `Semantic<E>` | Obtener elementos iniciales que satisfacen condición | O(n) |
|
|
169
|
+
| `translate(offset)` | `Semantic<E>` | Traducir índices | O(n) |
|
|
170
|
+
| `translate(translator)` | `Semantic<E>` | Transformación de índices personalizada | O(n) |
|
|
171
|
+
|
|
172
|
+
**Suplemento de Ejemplo de Código:**
|
|
173
|
+
```typescript
|
|
174
|
+
import { from } from 'semantic-typescript';
|
|
135
175
|
|
|
136
|
-
|
|
176
|
+
const stream = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
137
177
|
|
|
138
|
-
|
|
178
|
+
// Ejemplos de operaciones de transformación de flujos
|
|
179
|
+
const processedStream = stream
|
|
180
|
+
.filter(x => x % 2 === 0) // Filtrar números pares
|
|
181
|
+
.map(x => x * 2) // Multiplicar cada elemento por 2
|
|
182
|
+
.distinct() // Eliminar duplicados
|
|
183
|
+
.limit(3) // Limitar a primeros 3 elementos
|
|
184
|
+
.peek((val, index) => console.log(`Elemento ${val} en índice ${index}`)); // Ver elementos
|
|
139
185
|
|
|
140
|
-
|
|
141
|
-
Collector.full(identity, accumulator, finisher)
|
|
142
|
-
Collector.shortable(identity, interruptor, accumulator, finisher)
|
|
186
|
+
// Nota: El flujo aún no se ha ejecutado, necesita conversión a Collectable para operaciones terminales
|
|
143
187
|
```
|
|
144
188
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
---
|
|
189
|
+
#### Operaciones Terminales de Flujos
|
|
148
190
|
|
|
149
|
-
|
|
191
|
+
| Método | Tipo de Retorno | Descripción | Características de Rendimiento |
|
|
192
|
+
|------|----------|------|----------|
|
|
193
|
+
| `toOrdered()` | `OrderedCollectable<E>` | Convertir a colección ordenada | Operación de ordenación, menor rendimiento |
|
|
194
|
+
| `toUnordered()` | `UnorderedCollectable<E>` | Convertir a colección desordenada | Más rápido, sin ordenación |
|
|
195
|
+
| `toWindow()` | `WindowCollectable<E>` | Convertir a colección de ventana | Operación de ordenación, menor rendimiento |
|
|
196
|
+
| `toNumericStatistics()` | `Statistics<E, number>` | Análisis estadístico numérico | Operación de ordenación, menor rendimiento |
|
|
197
|
+
| `toBigintStatistics()` | `Statistics<E, bigint>` | Análisis estadístico de big integer | Operación de ordenación, menor rendimiento |
|
|
198
|
+
| `sorted()` | `OrderedCollectable<E>` | Ordenación natural | Anula resultados de redirección |
|
|
199
|
+
| `sorted(comparator)` | `OrderedCollectable<E>` | Ordenación personalizada | Anula resultados de redirección |
|
|
150
200
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
- `UnorderedCollectable<E>` — Sin ordenar, el más rápido
|
|
155
|
-
- `WindowCollectable<E>` — Ventanas deslizantes
|
|
156
|
-
- `Statistics<E, D>` — Estadísticas agregadas
|
|
201
|
+
**Suplemento de Ejemplo de Código:**
|
|
202
|
+
```typescript
|
|
203
|
+
import { from } from 'semantic-typescript';
|
|
157
204
|
|
|
158
|
-
|
|
205
|
+
const semanticStream = from([5, 2, 8, 1, 9, 3, 7, 4, 6]);
|
|
159
206
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
| `count()` | Contar elementos | `.count()` |
|
|
163
|
-
| `toArray()` | Convertir a Array | `.toArray()` |
|
|
164
|
-
| `toSet()` | Convertir a Set | `.toSet()` |
|
|
165
|
-
| `toMap(k, v)` | Convertir a Map | `.toMap(x => x.id, x => x)` |
|
|
166
|
-
| `group(k)` | Agrupar por clave | `.group(x => x.category)` |
|
|
167
|
-
| `findAny()` | Encontrar cualquier elemento (Optional) | `.findAny()` |
|
|
168
|
-
| `findFirst()` | Encontrar el primer elemento (Optional) | `.findFirst()` |
|
|
169
|
-
| `reduce(...)` | Reducción personalizada | `.reduce((a,b) => a + b, 0)` |
|
|
207
|
+
// Convertir a colección ordenada (menor rendimiento)
|
|
208
|
+
const ordered = semanticStream.toOrdered();
|
|
170
209
|
|
|
171
|
-
|
|
210
|
+
// Convertir a colección desordenada (más rápido)
|
|
211
|
+
const unordered = semanticStream.toUnordered();
|
|
172
212
|
|
|
173
|
-
|
|
213
|
+
// Ordenación natural
|
|
214
|
+
const sortedNatural = semanticStream.sorted();
|
|
174
215
|
|
|
175
|
-
|
|
216
|
+
// Ordenación personalizada
|
|
217
|
+
const sortedCustom = semanticStream.sorted((a, b) => b - a); // Orden descendente
|
|
176
218
|
|
|
177
|
-
|
|
219
|
+
// Convertir a objeto estadístico
|
|
220
|
+
const stats = semanticStream.toNumericStatistics();
|
|
178
221
|
|
|
179
|
-
|
|
180
|
-
const sorted = new OrderedCollectable(stream);
|
|
181
|
-
const customSorted = new OrderedCollectable(stream, (a, b) => b - a);
|
|
222
|
+
// Nota: Debe llamar a los métodos anteriores a través de la instancia Semantic para obtener Collectable antes de usar métodos terminales
|
|
182
223
|
```
|
|
183
224
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
---
|
|
225
|
+
### Collector<E, A, R> - Colector de Datos
|
|
187
226
|
|
|
188
|
-
|
|
227
|
+
Los colectores se utilizan para agregar datos de flujos en estructuras específicas.
|
|
189
228
|
|
|
190
|
-
|
|
229
|
+
| Método | Descripción | Escenario de Uso |
|
|
230
|
+
|------|------|----------|
|
|
231
|
+
| `collect(generator)` | Ejecutar recolección de datos | Operación terminal de flujo |
|
|
232
|
+
| `static full(identity, accumulator, finisher)` | Crear colector completo | Requiere procesamiento completo |
|
|
233
|
+
| `static shortable(identity, interruptor, accumulator, finisher)` | Crear colector interrumpible | Puede terminar temprano |
|
|
191
234
|
|
|
235
|
+
**Suplemento de Ejemplo de Código:**
|
|
192
236
|
```typescript
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
237
|
+
import { Collector } from 'semantic-typescript';
|
|
238
|
+
|
|
239
|
+
// Crear colector personalizado
|
|
240
|
+
const sumCollector = Collector.full(
|
|
241
|
+
() => 0, // Valor inicial
|
|
242
|
+
(acc, value) => acc + value, // Acumulador
|
|
243
|
+
result => result // Función finalizadora
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
// Usar colector (requiere conversión de Semantic a Collectable primero)
|
|
247
|
+
const numbers = from([1, 2, 3, 4, 5]);
|
|
248
|
+
const sum = numbers.toUnordered().collect(sumCollector); // 15
|
|
196
249
|
```
|
|
197
250
|
|
|
198
|
-
|
|
199
|
-
✅ **Mejor rendimiento cuando el orden no importa**
|
|
200
|
-
|
|
201
|
-
---
|
|
251
|
+
### Collectable<E> - Clase Abstracta de Datos Colectables
|
|
202
252
|
|
|
203
|
-
|
|
253
|
+
Proporciona métodos ricos de agregación y transformación de datos. **Nota: Primero debe obtener una instancia Collectable llamando a sorted(), toOrdered(), etc. a través de la instancia Semantic antes de usar los siguientes métodos.**
|
|
204
254
|
|
|
205
|
-
|
|
255
|
+
#### Operaciones de Consulta de Datos
|
|
206
256
|
|
|
207
|
-
|
|
257
|
+
| Método | Tipo de Retorno | Descripción | Ejemplo |
|
|
258
|
+
|------|----------|------|------|
|
|
259
|
+
| `anyMatch(predicate)` | `boolean` | Si algún elemento coincide | `anyMatch(x => x > 0)` |
|
|
260
|
+
| `allMatch(predicate)` | `boolean` | Si todos los elementos coinciden | `allMatch(x => x > 0)` |
|
|
261
|
+
| `count()` | `bigint` | Estadísticas de conteo de elementos | `count()` → `5n` |
|
|
262
|
+
| `isEmpty()` | `boolean` | Si el flujo está vacío | `isEmpty()` |
|
|
263
|
+
| `findAny()` | `Optional<E>` | Encontrar cualquier elemento | `findAny()` |
|
|
264
|
+
| `findFirst()` | `Optional<E>` | Encontrar primer elemento | `findFirst()` |
|
|
265
|
+
| `findLast()` | `Optional<E>` | Encontrar último elemento | `findLast()` |
|
|
208
266
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
##### Métodos estadísticos comunes:
|
|
267
|
+
**Suplemento de Ejemplo de Código:**
|
|
268
|
+
```typescript
|
|
269
|
+
import { from } from 'semantic-typescript';
|
|
213
270
|
|
|
214
|
-
|
|
215
|
-
|--------|-------------|---------|
|
|
216
|
-
| `mean()` | Media | `.mean()` |
|
|
217
|
-
| `median()` | Mediana | `.median()` |
|
|
218
|
-
| `mode()` | Moda (valor más frecuente) | `.mode()` |
|
|
219
|
-
| `minimum()` | Mínimo | `.minimum()` |
|
|
220
|
-
| `maximum()` | Máximo | `.maximum()` |
|
|
221
|
-
| `range()` | Rango (máximo - mínimo) | `.range()` |
|
|
222
|
-
| `variance()` | Varianza | `.variance()` |
|
|
223
|
-
| `standardDeviation()` | Desviación estándar | `.standardDeviation()` |
|
|
224
|
-
| `summate()` | Suma total | `.summate()` |
|
|
225
|
-
| `quantile(q)` | Valor en el percentil q (0–1) | `.quantile(0.5)` → mediana |
|
|
226
|
-
| `frequency()` | Frecuencia como Map | `.frequency()` |
|
|
271
|
+
const numbers = from([1, 2, 3, 4, 5]);
|
|
227
272
|
|
|
228
|
-
|
|
273
|
+
// Debe convertir a Collectable antes de usar métodos terminales
|
|
274
|
+
const collectable = numbers.toUnordered();
|
|
229
275
|
|
|
230
|
-
|
|
276
|
+
// Operaciones de consulta de datos
|
|
277
|
+
const hasEven = collectable.anyMatch(x => x % 2 === 0); // true
|
|
278
|
+
const allPositive = collectable.allMatch(x => x > 0); // true
|
|
279
|
+
const count = collectable.count(); // 5n
|
|
280
|
+
const isEmpty = collectable.isEmpty(); // false
|
|
281
|
+
const firstElement = collectable.findFirst(); // Optional.of(1)
|
|
282
|
+
const anyElement = collectable.findAny(); // Cualquier elemento
|
|
283
|
+
```
|
|
231
284
|
|
|
285
|
+
#### Operaciones de Agregación de Datos
|
|
286
|
+
|
|
287
|
+
| Método | Tipo de Retorno | Descripción | Complejidad |
|
|
288
|
+
|------|----------|------|--------|
|
|
289
|
+
| `group(classifier)` | `Map<K, E[]>` | Agrupar por clasificador | O(n) |
|
|
290
|
+
| `groupBy(keyExtractor, valueExtractor)` | `Map<K, V[]>` | Agrupar por extractores de clave-valor | O(n) |
|
|
291
|
+
| `join()` | `string` | Unir como cadena | O(n) |
|
|
292
|
+
| `join(delimiter)` | `string` | Unir con delimitador | O(n) |
|
|
293
|
+
| `partition(count)` | `E[][]` | Particionar por conteo | O(n) |
|
|
294
|
+
| `partitionBy(classifier)` | `E[][]` | Particionar por clasificador | O(n) |
|
|
295
|
+
| `reduce(accumulator)` | `Optional<E>` | Operación de reducción | O(n) |
|
|
296
|
+
| `reduce(identity, accumulator)` | `E` | Reducción con identidad | O(n) |
|
|
297
|
+
| `toArray()` | `E[]` | Convertir a array | O(n) |
|
|
298
|
+
| `toMap(keyExtractor, valueExtractor)` | `Map<K, V>` | Convertir a Map | O(n) |
|
|
299
|
+
| `toSet()` | `Set<E>` | Convertir a Set | O(n) |
|
|
300
|
+
|
|
301
|
+
**Suplemento de Ejemplo de Código:**
|
|
232
302
|
```typescript
|
|
233
|
-
import { from
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
303
|
+
import { from } from 'semantic-typescript';
|
|
304
|
+
|
|
305
|
+
const people = from([
|
|
306
|
+
{ name: "Alice", age: 25, city: "New York" },
|
|
307
|
+
{ name: "Bob", age: 30, city: "London" },
|
|
308
|
+
{ name: "Charlie", age: 25, city: "New York" }
|
|
309
|
+
]);
|
|
310
|
+
|
|
311
|
+
// Debe convertir a Collectable antes de usar operaciones de agregación
|
|
312
|
+
const collectable = people.toUnordered();
|
|
313
|
+
|
|
314
|
+
// Operaciones de agrupación
|
|
315
|
+
const byCity = collectable.group(person => person.city);
|
|
316
|
+
// Map { "New York" => [{name: "Alice", ...}, {name: "Charlie", ...}], "London" => [{name: "Bob", ...}] }
|
|
317
|
+
|
|
318
|
+
const byAge = collectable.groupBy(
|
|
319
|
+
person => person.age,
|
|
320
|
+
person => person.name
|
|
321
|
+
);
|
|
322
|
+
// Map { 25 => ["Alice", "Charlie"], 30 => ["Bob"] }
|
|
323
|
+
|
|
324
|
+
// Convertir a colecciones
|
|
325
|
+
const array = collectable.toArray(); // Array original
|
|
326
|
+
const set = collectable.toSet(); // Colección Set
|
|
327
|
+
const map = collectable.toMap(
|
|
328
|
+
person => person.name,
|
|
329
|
+
person => person.age
|
|
330
|
+
); // Map { "Alice" => 25, "Bob" => 30, "Charlie" => 25 }
|
|
331
|
+
|
|
332
|
+
// Operaciones de reducción
|
|
333
|
+
const totalAge = collectable.reduce(0, (acc, person) => acc + person.age); // 80
|
|
334
|
+
const oldest = collectable.reduce((a, b) => a.age > b.age ? a : b); // Optional.of({name: "Bob", age: 30, ...})
|
|
253
335
|
```
|
|
254
336
|
|
|
255
|
-
|
|
337
|
+
### Implementaciones Específicas de Colectores
|
|
256
338
|
|
|
257
|
-
|
|
339
|
+
#### UnorderedCollectable<E>
|
|
340
|
+
- **Características**: Colector más rápido, sin ordenación
|
|
341
|
+
- **Escenarios de Uso**: Orden no importante, máximo rendimiento deseado
|
|
342
|
+
- **Métodos**: Hereda todos los métodos de Collectable
|
|
258
343
|
|
|
259
|
-
|
|
344
|
+
#### OrderedCollectable<E>
|
|
345
|
+
- **Características**: Garantiza orden de elementos, menor rendimiento
|
|
346
|
+
- **Escenarios de Uso**: Requieren resultados ordenados
|
|
347
|
+
- **Métodos Especiales**: Hereda todos los métodos, mantiene estado de orden interno
|
|
260
348
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
| `useCompare(a, b)` | Función de comparación universal |
|
|
268
|
-
| `useRandom(x)` | Generador de números aleatorios (divertido) |
|
|
349
|
+
#### WindowCollectable<E>
|
|
350
|
+
- **Características**: Soporta operaciones de ventana deslizante
|
|
351
|
+
- **Escenarios de Uso**: Análisis de datos de series temporales
|
|
352
|
+
- **Métodos Especiales**:
|
|
353
|
+
- `slide(size, step)` - Ventana deslizante
|
|
354
|
+
- `tumble(size)` - Ventana de tumble
|
|
269
355
|
|
|
270
|
-
|
|
356
|
+
**Suplemento de Ejemplo de Código:**
|
|
357
|
+
```typescript
|
|
358
|
+
import { from } from 'semantic-typescript';
|
|
271
359
|
|
|
272
|
-
|
|
360
|
+
const data = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
273
361
|
|
|
274
|
-
|
|
362
|
+
// Colector desordenado (más rápido)
|
|
363
|
+
const unordered = data.toUnordered();
|
|
364
|
+
const unorderedArray = unordered.toArray(); // Puede mantener orden original [1, 2, 3, ...]
|
|
275
365
|
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
accept(i, BigInt(i));
|
|
280
|
-
if (i === 5) interrupt(i);
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
const s = new Semantic(gen);
|
|
285
|
-
```
|
|
366
|
+
// Colector ordenado
|
|
367
|
+
const ordered = data.toOrdered();
|
|
368
|
+
const orderedArray = ordered.toArray(); // Orden garantizado [1, 2, 3, ...]
|
|
286
369
|
|
|
287
|
-
|
|
370
|
+
// Colector de ventana
|
|
371
|
+
const windowed = data.toWindow();
|
|
372
|
+
const slidingWindows = windowed.slide(3n, 2n); // Tamaño de ventana 3, paso 2
|
|
373
|
+
// Ventana 1: [1, 2, 3], Ventana 2: [3, 4, 5], Ventana 3: [5, 6, 7], ...
|
|
288
374
|
|
|
289
|
-
|
|
290
|
-
|
|
375
|
+
const tumblingWindows = windowed.tumble(4n); // Ventana de tumble tamaño 4
|
|
376
|
+
// Ventana 1: [1, 2, 3, 4], Ventana 2: [5, 6, 7, 8], ...
|
|
291
377
|
```
|
|
292
378
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
379
|
+
### Statistics<E, D> - Análisis Estadístico
|
|
380
|
+
|
|
381
|
+
Clase base de análisis estadístico que proporciona métodos ricos de cálculo estadístico. **Nota: Primero debe obtener una instancia Statistics llamando a toNumericStatistics() o toBigIntStatistics() a través de la instancia Semantic antes de usar los siguientes métodos.**
|
|
382
|
+
|
|
383
|
+
#### Operaciones de Cálculo Estadístico
|
|
384
|
+
|
|
385
|
+
| Método | Tipo de Retorno | Descripción | Complejidad de Algoritmo |
|
|
386
|
+
|------|----------|------|------------|
|
|
387
|
+
| `maximum()` | `Optional<E>` | Valor máximo | O(n) |
|
|
388
|
+
| `minimum()` | `Optional<E>` | Valor mínimo | O(n) |
|
|
389
|
+
| `range()` | `D` | Rango (max-min) | O(n) |
|
|
390
|
+
| `variance()` | `D` | Varianza | O(n) |
|
|
391
|
+
| `standardDeviation()` | `D` | Desviación estándar | O(n) |
|
|
392
|
+
| `mean()` | `D` | Valor medio | O(n) |
|
|
393
|
+
| `median()` | `D` | Valor mediano | O(n log n) |
|
|
394
|
+
| `mode()` | `D` | Valor modal | O(n) |
|
|
395
|
+
| `frequency()` | `Map<D, bigint>` | Distribución de frecuencia | O(n) |
|
|
396
|
+
| `summate()` | `D` | Sumatoria | O(n) |
|
|
397
|
+
| `quantile(quantile)` | `D` | Cuantil | O(n log n) |
|
|
398
|
+
| `interquartileRange()` | `D` | Rango intercuartílico | O(n log n) |
|
|
399
|
+
| `skewness()` | `D` | Asimetría | O(n) |
|
|
400
|
+
| `kurtosis()` | `D` | Curtosis | O(n) |
|
|
401
|
+
|
|
402
|
+
**Suplemento de Ejemplo de Código:**
|
|
403
|
+
```typescript
|
|
404
|
+
import { from } from 'semantic-typescript';
|
|
405
|
+
|
|
406
|
+
const numbers = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
407
|
+
|
|
408
|
+
// Debe convertir a objeto estadístico antes de usar métodos estadísticos
|
|
409
|
+
const stats = numbers.toNumericStatistics();
|
|
410
|
+
|
|
411
|
+
// Estadísticas básicas
|
|
412
|
+
const count = stats.count(); // 10n
|
|
413
|
+
const max = stats.maximum(); // Optional.of(10)
|
|
414
|
+
const min = stats.minimum(); // Optional.of(1)
|
|
415
|
+
const range = stats.range(); // 9
|
|
416
|
+
const mean = stats.mean(); // 5.5
|
|
417
|
+
const median = stats.median(); // 5.5
|
|
418
|
+
const sum = stats.summate(); // 55
|
|
419
|
+
|
|
420
|
+
// Estadísticas avanzadas
|
|
421
|
+
const variance = stats.variance(); // 8.25
|
|
422
|
+
const stdDev = stats.standardDeviation(); // 2.872
|
|
423
|
+
const mode = stats.mode(); // Cualquier valor (ya que todos aparecen una vez)
|
|
424
|
+
const q1 = stats.quantile(0.25); // 3.25
|
|
425
|
+
const q3 = stats.quantile(0.75); // 7.75
|
|
426
|
+
const iqr = stats.interquartileRange(); // 4.5
|
|
427
|
+
|
|
428
|
+
// Distribución de frecuencia
|
|
429
|
+
const freq = stats.frequency(); // Map {1 => 1n, 2 => 1n, ...}
|
|
430
|
+
```
|
|
298
431
|
|
|
299
|
-
|
|
432
|
+
#### Clases Específicas de Implementación Estadística
|
|
300
433
|
|
|
301
|
-
|
|
434
|
+
**NumericStatistics<E>**
|
|
435
|
+
- Maneja análisis estadístico de tipo number
|
|
436
|
+
- Todos los cálculos estadísticos retornan tipo number
|
|
302
437
|
|
|
303
|
-
|
|
438
|
+
**BigIntStatistics<E>**
|
|
439
|
+
- Maneja análisis estadístico de tipo bigint
|
|
440
|
+
- Todos los cálculos estadísticos retornan tipo bigint
|
|
304
441
|
|
|
305
|
-
|
|
442
|
+
**Suplemento de Ejemplo de Código:**
|
|
443
|
+
```typescript
|
|
444
|
+
import { from } from 'semantic-typescript';
|
|
306
445
|
|
|
307
|
-
|
|
446
|
+
// Estadísticas numéricas
|
|
447
|
+
const numberData = from([10, 20, 30, 40, 50]);
|
|
448
|
+
const numericStats = numberData.toNumericStatistics();
|
|
308
449
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
| Manejar nulos con seguridad | `Optional<T>` |
|
|
312
|
-
| Crear un flujo | `from([...])`, `range()`, `fill()` |
|
|
313
|
-
| Transformar datos | `map()`, `filter()` |
|
|
314
|
-
| Ordenar datos | `sorted()`, `toOrdered()` |
|
|
315
|
-
| Sin ordenar (más rápido) | `toUnordered()` ✅ |
|
|
316
|
-
| Agrupar / Agregar | `toMap()`, `group()`, `Collector` |
|
|
317
|
-
| Estadísticas | `NumericStatistics`, `mean()`, `median()`, etc. |
|
|
450
|
+
console.log(numericStats.mean()); // 30
|
|
451
|
+
console.log(numericStats.summate()); // 150
|
|
318
452
|
|
|
319
|
-
|
|
453
|
+
// Estadísticas de big integer
|
|
454
|
+
const bigintData = from([100n, 200n, 300n, 400n, 500n]);
|
|
455
|
+
const bigintStats = bigintData.toBigIntStatistics();
|
|
320
456
|
|
|
321
|
-
|
|
457
|
+
console.log(bigintStats.mean()); // 300n
|
|
458
|
+
console.log(bigintStats.summate()); // 1500n
|
|
322
459
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
460
|
+
// Estadísticas usando funciones mapeadoras
|
|
461
|
+
const objectData = from([
|
|
462
|
+
{ value: 15 },
|
|
463
|
+
{ value: 25 },
|
|
464
|
+
{ value: 35 },
|
|
465
|
+
{ value: 45 }
|
|
466
|
+
]);
|
|
326
467
|
|
|
327
|
-
|
|
468
|
+
const objectStats = objectData.toNumericStatistics();
|
|
469
|
+
const meanWithMapper = objectStats.mean(obj => obj.value); // 30
|
|
470
|
+
const sumWithMapper = objectStats.summate(obj => obj.value); // 120
|
|
471
|
+
```
|
|
328
472
|
|
|
329
|
-
|
|
473
|
+
## Ejemplo Completo de Uso
|
|
330
474
|
|
|
331
|
-
|
|
475
|
+
```typescript
|
|
476
|
+
import { from, validate, invalidate } from 'semantic-typescript';
|
|
477
|
+
|
|
478
|
+
// 1. Crear flujo de datos
|
|
479
|
+
const rawData = [5, 2, 8, 1, null, 9, 3, undefined, 7, 4, 6];
|
|
480
|
+
const semanticStream = from(rawData);
|
|
481
|
+
|
|
482
|
+
// 2. Pipeline de procesamiento de flujo
|
|
483
|
+
const processedStream = semanticStream
|
|
484
|
+
.filter(val => validate(val)) // Filtrar null y undefined
|
|
485
|
+
.map(val => val! * 2) // Multiplicar cada valor por 2 (usando ! porque validate asegura no vacío)
|
|
486
|
+
.distinct(); // Eliminar duplicados
|
|
487
|
+
|
|
488
|
+
// 3. Convertir a Collectable y usar operaciones terminales
|
|
489
|
+
const collectable = processedStream.toUnordered();
|
|
490
|
+
|
|
491
|
+
// 4. Validación de datos y uso
|
|
492
|
+
if (!collectable.isEmpty()) {
|
|
493
|
+
const results = collectable
|
|
494
|
+
.filter(x => x > 5) // Filtrar nuevamente
|
|
495
|
+
.toArray(); // Convertir a array
|
|
496
|
+
|
|
497
|
+
console.log("Resultados del procesamiento:", results); // [16, 18, 14, 8, 12]
|
|
498
|
+
|
|
499
|
+
// Información estadística
|
|
500
|
+
const stats = processedStream.toNumericStatistics();
|
|
501
|
+
console.log("Valor medio:", stats.mean()); // 11.2
|
|
502
|
+
console.log("Suma total:", stats.summate()); // 56
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// 5. Manejar datos potencialmente inválidos
|
|
506
|
+
const potentiallyInvalidData: Array<number | null> = [1, null, 3, 4, null];
|
|
507
|
+
const validData = potentiallyInvalidData.filter(validate);
|
|
508
|
+
const invalidData = potentiallyInvalidData.filter(invalidate);
|
|
509
|
+
|
|
510
|
+
console.log("Datos válidos:", validData); // [1, 3, 4]
|
|
511
|
+
console.log("Datos inválidos:", invalidData); // [null, null]
|
|
512
|
+
```
|
|
332
513
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
514
|
+
## Resumen de Reglas Importantes de Uso
|
|
515
|
+
|
|
516
|
+
1. **Crear Flujo**: Usar métodos de fábrica `from()`, `range()`, `fill()`, etc. para crear instancias Semantic
|
|
517
|
+
2. **Transformación de Flujo**: Llamar métodos `map()`, `filter()`, `distinct()`, etc. en instancias Semantic
|
|
518
|
+
3. **Convertir a Collectable**: Debe llamar a uno de los siguientes métodos a través de la instancia Semantic:
|
|
519
|
+
- `toOrdered()` - Colector ordenado
|
|
520
|
+
- `toUnordered()` - Colector desordenado (más rápido)
|
|
521
|
+
- `toWindow()` - Colector de ventana
|
|
522
|
+
- `toNumericStatistics()` - Estadísticas numéricas
|
|
523
|
+
- `toBigIntStatistics()` - Estadísticas de big integer
|
|
524
|
+
- `sorted()` - Ordenación natural
|
|
525
|
+
- `sorted(comparator)` - Ordenación personalizada
|
|
526
|
+
4. **Operaciones Terminales**: Llamar métodos terminales `toArray()`, `count()`, `summate()`, etc. en instancias Collectable
|
|
527
|
+
5. **Validación de Datos**: Usar `validate()` para asegurar que los datos no son null/undefined, usar `invalidate()` para verificar datos inválidos
|
|
528
|
+
|
|
529
|
+
Este diseño garantiza seguridad de tipos y optimización de rendimiento mientras proporciona funcionalidad rica de procesamiento de flujos.
|