Skip to contentPackage: Stream$2$1
Stream$2$1
Coverage
1: /*
2: * Copyright (c) 2012, 2020 Oracle and/or its affiliates and others.
3: * All rights reserved.
4: *
5: * This program and the accompanying materials are made available under the
6: * terms of the Eclipse Public License v. 2.0, which is available at
7: * http://www.eclipse.org/legal/epl-2.0.
8: *
9: * This Source Code may also be made available under the following Secondary
10: * Licenses when the conditions for such availability set forth in the
11: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
12: * version 2 with the GNU Classpath Exception, which is available at
13: * https://www.gnu.org/software/classpath/license.html.
14: *
15: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
16: */
17:
18: package com.sun.el.stream;
19:
20: import java.util.ArrayList;
21: import java.util.Comparator;
22: import java.util.HashSet;
23: import java.util.Iterator;
24: import java.util.PriorityQueue;
25: import java.util.Set;
26:
27: import jakarta.el.ELException;
28: import jakarta.el.LambdaExpression;
29:
30: import com.sun.el.lang.ELArithmetic;
31: import com.sun.el.lang.ELSupport;
32:
33: /*
34: */
35:
36: public class Stream {
37:
38: private Iterator<Object> source;
39: private Stream upstream;
40: private Operator op;
41:
42: Stream(Iterator<Object> source) {
43: this.source = source;
44: }
45:
46: Stream(Stream upstream, Operator op) {
47: this.upstream = upstream;
48: this.op = op;
49: }
50:
51: public Iterator<Object> iterator() {
52: if (source != null) {
53: return source;
54: }
55:
56: return op.iterator(upstream.iterator());
57: }
58:
59: public Stream filter(final LambdaExpression predicate) {
60: return new Stream(this, new Operator() {
61: @Override
62: public Iterator<Object> iterator(final Iterator<Object> upstream) {
63: return new Iterator2(upstream) {
64: @Override
65: public void doItem(Object item) {
66: if ((Boolean) predicate.invoke(item)) {
67: yield(item);
68: }
69: }
70: };
71: }
72: });
73: }
74:
75: public Stream map(final LambdaExpression mapper) {
76: return new Stream(this, new Operator() {
77: @Override
78: public Iterator<Object> iterator(final Iterator<Object> up) {
79: return new Iterator1(up) {
80: @Override
81: public Object next() {
82: return mapper.invoke(iter.next());
83: }
84: };
85: }
86: });
87: }
88:
89: public Stream peek(final LambdaExpression comsumer) {
90: return new Stream(this, new Operator() {
91: @Override
92: public Iterator<Object> iterator(final Iterator<Object> up) {
93: return new Iterator2(up) {
94: @Override
95: void doItem(Object item) {
96: comsumer.invoke(item);
97: yield(item);
98: }
99: };
100: }
101: });
102: }
103:
104: public Stream limit(final long n) {
105: if (n < 0) {
106: throw new IllegalArgumentException("limit must be non-negative");
107: }
108: return new Stream(this, new Operator() {
109: @Override
110: public Iterator<Object> iterator(final Iterator<Object> up) {
111: return new Iterator0() {
112: long limit = n;
113:
114: @Override
115: public boolean hasNext() {
116: return (limit > 0) ? up.hasNext() : false;
117: }
118:
119: @Override
120: public Object next() {
121: limit--;
122: return up.next();
123: }
124: };
125: }
126: });
127: }
128:
129: public Stream substream(final long startIndex) {
130: if (startIndex < 0) {
131: throw new IllegalArgumentException("substream index must be non-negative");
132: }
133: return new Stream(this, new Operator() {
134: long skip = startIndex;
135:
136: @Override
137: public Iterator<Object> iterator(final Iterator<Object> up) {
138: while (skip > 0 && up.hasNext()) {
139: up.next();
140: skip--;
141: }
142: return up;
143: }
144: });
145: }
146:
147: public Stream substream(long startIndex, long endIndex) {
148: return substream(startIndex).limit(endIndex - startIndex);
149: }
150:
151: public Stream distinct() {
152: return new Stream(this, new Operator() {
153: @Override
154: public Iterator<Object> iterator(final Iterator<Object> up) {
155: return new Iterator2(up) {
156: private Set<Object> set = new HashSet<Object>();
157:
158: @Override
159: public void doItem(Object item) {
160: if (set.add(item)) {
161: yield(item);
162: }
163: }
164: };
165: }
166: });
167: }
168:
169: public Stream sorted() {
170: return new Stream(this, new Operator() {
171:
172: private PriorityQueue<Object> queue = null;
173:
174: @Override
175: public Iterator<Object> iterator(final Iterator<Object> up) {
176: if (queue == null) {
177: queue = new PriorityQueue<Object>(16, new Comparator<Object>() {
178: @Override
179: public int compare(Object o1, Object o2) {
180: @SuppressWarnings("unchecked")
181: int result = ((Comparable<Object>) o1).compareTo(o2);
182: return result;
183: }
184: });
185:
186: while (up.hasNext()) {
187: queue.add(up.next());
188: }
189: }
190:
191: return new Iterator0() {
192: @Override
193: public boolean hasNext() {
194: return !queue.isEmpty();
195: }
196:
197: @Override
198: public Object next() {
199: return queue.remove();
200: }
201: };
202: }
203: });
204: }
205:
206: public Stream sorted(final LambdaExpression comparator) {
207: return new Stream(this, new Operator() {
208:
209: private PriorityQueue<Object> queue = null;
210:
211: @Override
212: public Iterator<Object> iterator(final Iterator<Object> up) {
213: if (queue == null) {
214: queue = new PriorityQueue<Object>(16, new Comparator<Object>() {
215: @Override
216: public int compare(Object o1, Object o2) {
217: return (Integer) ELSupport.coerceToType(comparator.invoke(o1, o2), Integer.class);
218: }
219: });
220:
221: while (up.hasNext()) {
222: queue.add(up.next());
223: }
224: }
225:
226: return new Iterator0() {
227: @Override
228: public boolean hasNext() {
229: return !queue.isEmpty();
230: }
231:
232: @Override
233: public Object next() {
234: return queue.remove();
235: }
236: };
237: }
238: });
239: }
240:
241: public Stream flatMap(final LambdaExpression mapper) {
242: return new Stream(this, new Operator() {
243: @Override
244: public Iterator<Object> iterator(final Iterator<Object> upstream) {
245: return new Iterator0() {
246: Iterator<Object> iter = null;
247:
248: @Override
249: public boolean hasNext() {
250: while (true) {
251: if (iter == null) {
252: if (!upstream.hasNext()) {
253: return false;
254: }
255: Object mapped = mapper.invoke(upstream.next());
256: if (!(mapped instanceof Stream)) {
257: throw new ELException("Expecting a Stream " + "from flatMap's mapper function.");
258: }
259: iter = ((Stream) mapped).iterator();
260: } else {
261: if (iter.hasNext()) {
262: return true;
263: }
264: iter = null;
265: }
266: }
267: }
268:
269: @Override
270: public Object next() {
271: if (iter == null) {
272: return null;
273: }
274: return iter.next();
275: }
276: };
277: }
278: });
279: }
280:
281: public Object reduce(Object base, LambdaExpression op) {
282: Iterator<Object> iter = iterator();
283: while (iter.hasNext()) {
284: base = op.invoke(base, iter.next());
285: }
286: return base;
287: }
288:
289: public Optional reduce(LambdaExpression op) {
290: Iterator<Object> iter = iterator();
291: if (iter.hasNext()) {
292: Object base = iter.next();
293: while (iter.hasNext()) {
294: base = op.invoke(base, iter.next());
295: }
296: return new Optional(base);
297: }
298: return new Optional();
299: }
300:
301: /*
302: * public Map<Object,Object> reduceBy(LambdaExpression classifier, LambdaExpression seed, LambdaExpression reducer) {
303: * Map<Object,Object> map = new HashMap<Object,Object>(); Iterator<Object> iter = iterator(); while (iter.hasNext()) {
304: * Object item = iter.next(); Object key = classifier.invoke(item); Object value = map.get(key); if (value == null) {
305: * value = seed.invoke(); } map.put(key, reducer.invoke(value, item)); } return map; }
306: */
307:
308: public void forEach(LambdaExpression comsumer) {
309: Iterator<Object> iter = iterator();
310: while (iter.hasNext()) {
311: comsumer.invoke(iter.next());
312: }
313: }
314:
315: /*
316: * public Map<Object,Collection<Object>> groupBy(LambdaExpression classifier) { Map<Object, Collection<Object>> map =
317: * new HashMap<Object, Collection<Object>>(); Iterator<Object> iter = iterator(); while (iter.hasNext()) { Object item =
318: * iter.next(); Object key = classifier.invoke(item); if (key == null) { throw new ELException("null key"); }
319: * Collection<Object> c = map.get(key); if (c == null) { c = new ArrayList<Object>(); map.put(key, c); } c.add(item); }
320: * return map; }
321: */
322: public boolean anyMatch(LambdaExpression predicate) {
323: Iterator<Object> iter = iterator();
324: while (iter.hasNext()) {
325: if ((Boolean) predicate.invoke(iter.next())) {
326: return true;
327: }
328: }
329: return false;
330: }
331:
332: public boolean allMatch(LambdaExpression predicate) {
333: Iterator<Object> iter = iterator();
334: while (iter.hasNext()) {
335: if (!(Boolean) predicate.invoke(iter.next())) {
336: return false;
337: }
338: }
339: return true;
340: }
341:
342: public boolean noneMatch(LambdaExpression predicate) {
343: Iterator<Object> iter = iterator();
344: while (iter.hasNext()) {
345: if ((Boolean) predicate.invoke(iter.next())) {
346: return false;
347: }
348: }
349: return true;
350: }
351:
352: public Object[] toArray() {
353: Iterator<Object> iter = iterator();
354: ArrayList<Object> al = new ArrayList<Object>();
355: while (iter.hasNext()) {
356: al.add(iter.next());
357: }
358: return al.toArray();
359: }
360:
361: public Object toList() {
362: Iterator<Object> iter = iterator();
363: ArrayList<Object> al = new ArrayList<Object>();
364: while (iter.hasNext()) {
365: al.add(iter.next());
366: }
367: return al;
368: }
369:
370: /*
371: * public Object into(Object target) { if (! (target instanceof Collection)) { throw new
372: * ELException("The argument type for into operation mush be a Collection"); } Collection<Object> c =
373: * (Collection<Object>) target; Iterator<Object> iter = iterator(); while (iter.hasNext()) { c.add(iter.next()); }
374: * return c; }
375: */
376:
377: public Optional findFirst() {
378: Iterator<Object> iter = iterator();
379: if (iter.hasNext()) {
380: return new Optional(iter.next());
381: } else {
382: return new Optional();
383: }
384: }
385:
386: public Object sum() {
387: Number sum = Long.valueOf(0);
388: Iterator<Object> iter = iterator();
389: while (iter.hasNext()) {
390: sum = ELArithmetic.add(sum, iter.next());
391: }
392: return sum;
393: }
394:
395: public Object count() {
396: long count = 0;
397: Iterator<Object> iter = iterator();
398: while (iter.hasNext()) {
399: count++;
400: iter.next();
401: }
402: return Long.valueOf(count);
403: }
404:
405: public Optional min() {
406: Object min = null;
407: Iterator<Object> iter = iterator();
408: while (iter.hasNext()) {
409: Object item = iter.next();
410: if (min == null || ELSupport.compare(min, item) > 0) {
411: min = item;
412: }
413: }
414: if (min == null) {
415: return new Optional();
416: }
417: return new Optional(min);
418: }
419:
420: public Optional max() {
421: Object max = null;
422: Iterator<Object> iter = iterator();
423: while (iter.hasNext()) {
424: Object item = iter.next();
425: if (max == null || ELSupport.compare(max, item) < 0) {
426: max = item;
427: }
428: }
429: if (max == null) {
430: return new Optional();
431: }
432: return new Optional(max);
433: }
434:
435: public Optional min(final LambdaExpression comparator) {
436: Object min = null;
437: Iterator<Object> iter = iterator();
438: while (iter.hasNext()) {
439: Object item = iter.next();
440: if (min == null || ELSupport.compare(comparator.invoke(item, min), Long.valueOf(0)) < 0) {
441: min = item;
442: }
443: }
444: if (min == null) {
445: return new Optional();
446: }
447: return new Optional(min);
448: }
449:
450: public Optional max(final LambdaExpression comparator) {
451: Object max = null;
452: Iterator<Object> iter = iterator();
453: while (iter.hasNext()) {
454: Object item = iter.next();
455: if (max == null || ELSupport.compare(comparator.invoke(max, item), Long.valueOf(0)) < 0) {
456: max = item;
457: }
458: }
459: if (max == null) {
460: return new Optional();
461: }
462: return new Optional(max);
463: }
464:
465: public Optional average() {
466: Number sum = Long.valueOf(0);
467: long count = 0;
468: Iterator<Object> iter = iterator();
469: while (iter.hasNext()) {
470: count++;
471: sum = ELArithmetic.add(sum, iter.next());
472: }
473: if (count == 0) {
474: return new Optional();
475: }
476: return new Optional(ELArithmetic.divide(sum, count));
477: }
478:
479: abstract class Iterator0 implements Iterator<Object> {
480: @Override
481: public void remove() {
482: throw new UnsupportedOperationException();
483: }
484: }
485:
486: abstract class Iterator1 extends Iterator0 {
487:
488: Iterator iter;
489:
490: Iterator1(Iterator iter) {
491: this.iter = iter;
492: }
493:
494: @Override
495: public boolean hasNext() {
496: return iter.hasNext();
497: }
498: }
499:
500: abstract class Iterator2 extends Iterator1 {
501: private Object current;
502: private boolean yielded;
503:
504: Iterator2(Iterator upstream) {
505: super(upstream);
506: }
507:
508: @Override
509: public Object next() {
510: yielded = false;
511: return current;
512: }
513:
514: @Override
515: public boolean hasNext() {
516: while ((!yielded) && iter.hasNext()) {
517: doItem(iter.next());
518: }
519: return yielded;
520: }
521:
522: void yield(Object current) {
523: this.current = current;
524: yielded = true;
525: }
526:
527: abstract void doItem(Object item);
528: }
529: }