All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.groovy.runtime.StreamGroovyMethods Maven / Gradle / Ivy

There is a newer version: 5.0.0-alpha-11
Show newest version
/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.codehaus.groovy.runtime;

import groovy.lang.EmptyRange;
import groovy.lang.IntRange;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.BaseStream;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class StreamGroovyMethods {

    private StreamGroovyMethods() {
    }

    /**
     * Returns element at {@code index} or {@code null}.
     * 

* This is a short-circuiting terminal operation. * *

     * import java.util.stream.Stream
     * import static groovy.test.GroovyAssert.shouldFail
     *
     * Stream stream = ['foo','bar','baz'].stream()
     * shouldFail(IllegalArgumentException) { stream[-1] }
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[0] == 'foo'
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[1] == 'bar'
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[2] == 'baz'
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[3] === null
     * 
* * @throws IllegalArgumentException if {@code index} is negative * * @since 5.0.0 */ public static T getAt(final Stream self, final int index) { return self.skip(index).findFirst().orElse(null); } /** * Returns element(s) in {@code range} or an empty list. *

* This is a short-circuiting terminal operation. * *

     * import java.util.stream.Stream
     * import static groovy.test.GroovyAssert.shouldFail
     *
     * Stream<String> stream = ['foo','bar','baz'].stream()
     * shouldFail(IllegalArgumentException) { stream[-1..0] }
     *
     * stream = ['foo','bar','baz'].stream()
     * shouldFail(IllegalArgumentException) { stream[0..-1] }
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[0..<1] == ['foo']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[1..<2] == ['bar']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[2..<3] == ['baz']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[3..<4] == []
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[0<..2] == ['bar','baz']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream[0..99] == ['foo','bar','baz']
     * 
* * @throws IllegalArgumentException for negative index or reverse range * * @since 5.0.0 */ public static List getAt(final Stream self, final IntRange range) { if (range.isReverse()) throw new IllegalArgumentException("reverse range"); return self.skip(range.getFromInt()).limit(range.size()).collect(Collectors.toList()); } /** * Returns an empty list. *

*

     * import java.util.stream.Stream
     * Stream<String> stream = ['foo','bar','baz'].stream()
     * assert stream[1..<1].isEmpty()
     * 
* * @since 5.0.0 */ public static List getAt(final Stream self, final EmptyRange range) { return new ArrayList<>(); } /** * Returns a (possibly empty) stream. *

* This is a short-circuiting intermediate operation. * *

     * import java.util.stream.Stream
     * import static groovy.test.GroovyAssert.shouldFail
     *
     * Stream<String> stream = ['foo','bar','baz'].stream()
     * shouldFail(IllegalArgumentException) { stream.from(-1..0) }
     *
     * stream = ['foo','bar','baz'].stream()
     * shouldFail(IllegalArgumentException) { stream.from(0..-1) }
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream.from(0..<1).toList() == ['foo']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream.from(1..<2).toList() == ['bar']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream.from(2..<3).toList() == ['baz']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream.from(3..<4).toList() == []
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream.from(0<..2).toList() == ['bar','baz']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream.from(0<..<2).toList() == ['bar']
     *
     * stream = ['foo','bar','baz'].stream()
     * assert stream.from(0..99).toList() == ['foo','bar','baz']
     * 
* * @throws IllegalArgumentException for negative index or reverse range * * @since 5.0.0 */ public static Stream from(final Stream self, final IntRange range) { if (range.isReverse()) throw new IllegalArgumentException("reverse range"); return self.skip(range.getFromInt()).limit(range.size()); } /** * Returns an empty stream. *

*

     * import java.util.stream.Stream
     * Stream<String> stream = ['foo','bar','baz'].stream()
     * assert !stream.from(1..<1).findAny().isPresent()
     * 
* * @since 5.0.0 */ public static Stream from(final Stream self, final EmptyRange range) { return Stream.empty(); } //-------------------------------------------------------------------------- /** * Returns a lazily concatenated stream whose elements are all the elements of this stream followed by all the elements of the {@link Collection} object. * *
     * import java.util.stream.Stream
     * assert (Stream.of(1) + [2]).toList() == [1,2]
     * assert (Stream.of(1) + []).toList() == [1]
     * 
* * @since 4.0.0 */ public static Stream plus(final Stream lhs, final Collection rhs) { return Stream.concat(lhs, rhs.stream()); } /** * Returns a lazily concatenated stream whose elements are all the elements of this stream followed by all the elements of the {@link Iterable} object. * *
     * import java.util.stream.Stream
     * assert (Stream.of(1) + [2]).toList() == [1,2]
     * assert (Stream.of(1) + []).toList() == [1]
     * 
* * @since 4.0.0 */ public static Stream plus(final Stream lhs, final Iterable rhs) { return Stream.concat(lhs, stream(rhs)); } /** * Returns a lazily concatenated stream whose elements are all the elements of this stream followed by all the elements of the second stream. * *
     * import java.util.stream.Stream
     * assert (Stream.of(1) + Stream.<Integer>empty()).toList() == [1]
     * assert (Stream.of(1) + Stream.of(2)).toList() == [1,2]
     * assert (Stream.of(1) + [2].stream()).toList() == [1,2]
     * 
* * @since 4.0.0 */ public static Stream plus(final Stream lhs, final Stream rhs) { return Stream.concat(lhs, rhs); } //-------------------------------------------------------------------------- /** * Returns a sequential {@link Stream} containing a single element. * *
     * def item = 'string'
     * assert item.stream().toList() == ['string']
     * assert item.stream().findFirst().isPresent()
     * 
* * @since 3.0.0 */ public static Stream stream(final T self) { return Stream.of(self); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param The type of the array elements * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final T[] self) { return Arrays.stream(self); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final int[] self) { return Arrays.stream(self).boxed(); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final long[] self) { return Arrays.stream(self).boxed(); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final double[] self) { return Arrays.stream(self).boxed(); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final char[] self) { return IntStream.range(0, self.length).mapToObj(i -> self[i]); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final byte[] self) { return IntStream.range(0, self.length).mapToObj(i -> self[i]); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final short[] self) { return IntStream.range(0, self.length).mapToObj(i -> self[i]); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final boolean[] self) { return IntStream.range(0, self.length).mapToObj(i -> self[i]); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 2.5.0 */ public static Stream stream(final float[] self) { return IntStream.range(0, self.length).mapToObj(i -> self[i]); } /** * Returns a sequential {@link Stream} with the specified element(s) as its * source. *
     * def tokens = new StringTokenizer('one two')
     * assert tokens.stream().toList() == ['one', 'two']
     * 
* * @since 3.0.0 */ public static Stream stream(final Enumeration self) { return stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE, Spliterator.ORDERED) { @Override public void forEachRemaining(final Consumer action) { while (self.hasMoreElements()) { action.accept(self.nextElement()); } } @Override public boolean tryAdvance(final Consumer action) { if (self.hasMoreElements()) { action.accept(self.nextElement()); return true; } return false; } }); } /** * Returns a sequential {@link Stream} with the specified element(s) as its * source. * *
     * class Items implements Iterable {
     *   Iterator<String> iterator() {
     *     ['one', 'two'].iterator()
     *   }
     * }
     * def items = new Items()
     * assert items.stream().toList() == ['one', 'two']
     * 
* * @since 3.0.0 */ public static Stream stream(final Iterable self) { return StreamSupport.stream(self.spliterator(), false); } /** * Returns a sequential {@link Stream} with the specified element(s) as its * source. * *
     * [].iterator().stream().toList().isEmpty()
     * ['one', 'two'].iterator().stream().toList() == ['one', 'two']
     * 
* * @since 3.0.0 */ public static Stream stream(final Iterator self) { return stream(Spliterators.spliteratorUnknownSize(self, Spliterator.ORDERED)); } /** * Returns a sequential {@link Stream} with the specified element(s) as its * source. * *
     * assert [].spliterator().stream().toList().isEmpty()
     * assert ['one', 'two'].spliterator().stream().toList() == ['one', 'two']
     * 
* * @since 3.0.0 */ public static Stream stream(final Spliterator self) { return StreamSupport.stream(self, false); } /** * Returns an empty sequential {@link Stream}. * *
     * def item = null
     * assert item.stream().toList() == []
     * assert !item.stream().findFirst().isPresent()
     * 
* * @since 3.0.0 */ public static Stream stream(final NullObject self) { return Stream.empty(); } /** * If a value is present in the {@link Optional}, returns a {@link Stream} * with the value as its source or else an empty stream. * * @since 3.0.0 */ public static Stream stream(final Optional self) { return self.map(Stream::of).orElseGet(Stream::empty); } // /** * If a value is present in the {@link OptionalInt}, returns an {@link IntStream} * with the value as its source or else an empty stream. * * @since 3.0.0 */ public static IntStream stream(final OptionalInt self) { if (!self.isPresent()) { return IntStream.empty(); } return IntStream.of(self.getAsInt()); } /** * If a value is present in the {@link OptionalLong}, returns a {@link LongStream} * with the value as its source or else an empty stream. * * @since 3.0.0 */ public static LongStream stream(final OptionalLong self) { if (!self.isPresent()) { return LongStream.empty(); } return LongStream.of(self.getAsLong()); } /** * If a value is present in the {@link OptionalDouble}, returns a {@link DoubleStream} * with the value as its source or else an empty stream. * * @since 3.0.0 */ public static DoubleStream stream(final OptionalDouble self) { if (!self.isPresent()) { return DoubleStream.empty(); } return DoubleStream.of(self.getAsDouble()); } /** * Returns a sequential {@link IntStream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 3.0.8 */ public static IntStream intStream(final int[] self) { return Arrays.stream(self); } /** * Returns a sequential {@link LongStream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 3.0.8 */ public static LongStream longStream(final long[] self) { return Arrays.stream(self); } /** * Returns a sequential {@link DoubleStream} with the specified array as its * source. * * @param self The array, assumed to be unmodified during use * @return a {@code Stream} for the array * * @since 3.0.8 */ public static DoubleStream doubleStream(final double[] self) { return Arrays.stream(self); } //-------------------------------------------------------------------------- /** * Returns an array containing the elements of the stream. *
     * import static groovy.test.GroovyAssert.shouldFail
     *
     * assert Arrays.equals([].stream().toArray(Object), new Object[0])
     * assert Arrays.equals([].stream().toArray(String), new String[0])
     * assert Arrays.equals([].stream().toArray(String[]), new String[0][])
     * assert Arrays.equals(['x'].stream().toArray(Object), ['x'].toArray())
     * assert Arrays.equals(['x'].stream().toArray(String), ['x'] as String[])
     * assert Arrays.deepEquals([['x'] as String[]].stream().toArray(String[]), [['x'] as String[]] as String[][])
     * assert Arrays.equals(['x'].stream().toArray(CharSequence), ['x'] as CharSequence[])
     *
     * shouldFail(ArrayStoreException) {
     *     ['x'].stream().toArray(Thread)
     * }
     *
     * shouldFail(IllegalArgumentException) {
     *     ['x'].stream().toArray((Class) null)
     * }
     *
     * // Stream#toArray(IntFunction) should still be used for closure literal:
     * assert Arrays.equals(['x'].stream().toArray { n -> new String[n] }, ['x'] as String[])
     *
     * // Stream#toArray(IntFunction) should still be used for method reference:
     * assert Arrays.equals(['x'].stream().toArray(String[]::new), ['x'] as String[])
     * 
* * @param self the stream * @param type the array element type * * @since 3.0.4 */ public static T[] toArray(final Stream self, final Class type) { if (type == null) throw new IllegalArgumentException("type cannot be null"); return self.toArray(length -> (T[]) Array.newInstance(type, length)); } /** * Accumulates the elements of stream into a new List. * * @param self the stream * @param the type of element * @return a new {@code java.util.List} instance * * @since 2.5.0 */ public static List toList(final Stream self) { return self.collect(Collectors.toList()); } /** * Accumulates the elements of stream into a new List. * * @param self the {@code java.util.stream.BaseStream} * @param the type of element * @return a new {@code java.util.List} instance * * @since 2.5.0 */ public static List toList(final BaseStream self) { return stream(self.iterator()).collect(Collectors.toList()); } /** * Accumulates the elements of stream into a new Set. * * @param self the stream * @param the type of element * @return a new {@code java.util.Set} instance * * @since 2.5.0 */ public static Set toSet(final Stream self) { return self.collect(Collectors.toSet()); } /** * Accumulates the elements of stream into a new Set. * * @param self the {@code java.util.stream.BaseStream} * @param the type of element * @return a new {@code java.util.Set} instance * * @since 2.5.0 */ public static Set toSet(final BaseStream self) { return stream(self.iterator()).collect(Collectors.toSet()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy