Java 8 Stream
Published: 2023-01-12 11:55:55

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
https://cheatography.com/carlmig/cheat-sheets/java-8-streams/

concat(Stream<? extends T> a, Stream<? extends T> b)
Creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.

```
@Test
public void whenMergingStreams_thenResultStreamContainsElementsFromBoth() {
    Stream<Integer> stream1 = Stream.of(1, 3, 5);
    Stream<Integer> stream2 = Stream.of(2, 4, 6);

    Stream<Integer> resultingStream = Stream.concat(stream1, stream2);

    assertEquals(
      Arrays.asList(1, 3, 5, 2, 4, 6),
      resultingStream.collect(Collectors.toList()));
}
```


count()
Returns the count of elements in this stream.

distinct()
Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.

filter(Predicate<? super T> predicate)
Returns a stream consisting of the elements of this stream that match the given predicate.

flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.

```
public class FlatMapExample1 {

    public static void main(String[] args) {

        Developer o1 = new Developer();
        o1.setName("mkyong");
        o1.addBook("Java 8 in Action");
        o1.addBook("Spring Boot in Action");
        o1.addBook("Effective Java (3nd Edition)");

        Developer o2 = new Developer();
        o2.setName("zilap");
        o2.addBook("Learning Python, 5th Edition");
        o2.addBook("Effective Java (3nd Edition)");

        List<Developer> list = new ArrayList<>();
        list.add(o1);
        list.add(o2);

        // hmm....Set of Set...how to process?
        /*Set<Set<String>> collect = list.stream()
                .map(x -> x.getBook())
                .collect(Collectors.toSet());*/

        Set<String> collect =
                list.stream()
                        .map(x -> x.getBook())                              //  Stream<Set<String>>
                        .flatMap(x -> x.stream())                           //  Stream<String>
                        .filter(x -> !x.toLowerCase().contains("python"))   //  filter python book
                        .collect(Collectors.toSet());                       //  remove duplicated

        collect.forEach(System.out::println);

    }

}
```

flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)
flatMapToInt(Function<? super T,? extends IntStream> mapper)
flatMapToLong(Function<? super T,? extends LongStream> mapper)
mapToDouble(ToDoubleFunction<? super T> mapper)
mapToInt(ToIntFunction<? super T> mapper)
mapToLong(ToLongFunction<? super T> mapper)

```
        // Creating a List of Strings
        List<String> list = Arrays.asList("Geeks", "GFG",
                                          "GeeksforGeeks", "gfg");
  
        // Using Stream flatMapToInt(Function mapper)
        // to get length of all strings present in list
        list.stream().flatMapToInt(str -> IntStream.of(str.length())).
        forEach(System.out::println);
        // result: 5 3 13 3
        list.stream().mapToInt(str -> 
        str.length()).forEach(System.out::println);
        // result: 5 3 13 3
```

forEach(Consumer<? super T> action)
Performs an action for each element of this stream.

forEachOrdered(Consumer<? super T> action)
Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order.

generate(Supplier<T> s)
Returns an infinite sequential unordered stream where each element is generated by the provided Supplier.
```
Stream.generate(new Random()::nextInt)
    .limit(5).forEach(System.out::println); 
//result: 697197501, 50139200, 321540264, 1042847655, -770409472
```

iterate(T seed, UnaryOperator<T> f)
Returns an infinite sequential ordered Stream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc.

```
	//Stream.iterate(initial value, next value)
	Stream.iterate(0, n -> n + 1)
                .limit(10)
                .forEach(x -> System.out.println(x));
       //0 1 2 3 4 5 6 7 8 9
```

limit(long maxSize)
Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
skip(long n)
Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.

```
	Stream.of(-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
              .skip(2)
              .forEach(i -> System.out.print(i + " "));
        // 1 2 3 4 5 6 7 8 9 10
	    
	Stream.of(-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
              .limit(2)
              .forEach(i -> System.out.print(i + " "));
       // -1 0
```

peek(Consumer<? super T> action)
This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline:

```
     Stream.of("one", "two", "three", "four")
         .filter(e -> e.length() > 3)
         .peek(e -> System.out.println("Filtered value: " + e))
         .map(String::toUpperCase)
         .peek(e -> System.out.println("Mapped value: " + e))
         .collect(Collectors.toList());
```

reduce(BinaryOperator<T> accumulator)
Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.

```
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int result = numbers
  .stream()
  .reduce(0, (subtotal, element) -> subtotal + element);
assertThat(result).isEqualTo(21);
```

sorted(Comparator<? super T> comparator)
Returns a stream consisting of the elements of this stream, sorted according to the provided Comparator.

```
// sorted accept integer with negative and positive number. But if the stream is not integer, better use Compartor instead
Stream.of(6,9,3,0,1)
.sorted((x,y)->x-y)
.forEach(i -> System.out.print(i + " "));
// result: 0 1 3 6 9

List<User> users = Arrays.asList(
            new User("C", 30),
            new User("D", 40),
            new User("A", 10),
            new User("B", 20),
            new User("E", 50));

List<User> sortedList = users.stream()			.sorted(Comparator.comparingInt(User::getAge))
			.collect(Collectors.toList());

```

Comparator

```
	    String str = "welcome to code decode and code decode welcome you";
	    Map <String, Long> map = Arrays.asList(str.split(" "))
	    	    .stream()
	    	    .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
	    System.out.println(map);
// result: {code=2, and=1, to=1, decode=2, welcome=2, you=1}

// Convert String to uppercase and join them with coma
list.stream().map(x->x.toUpperCase()).collect(Collectors.joining(","));

// Statistics 
IntSummaryStatistics statistics stat = list.stream().mapToInt(x->x) // IntStream
.summaryStatistics()

int min = statistics.getMin();
int max = statistics.getMax();
```

IntStream
range(int startInclusive, int endExclusive)
Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive) by an incremental step of 1.
rangeClosed(int startInclusive, int endInclusive)
Returns a sequential ordered IntStream from startInclusive (inclusive) to endInclusive (inclusive) by an incremental step of 1.
`IntStream.range(0,count)` = `Stream.iterate(2, n -> n+1).limit(count)`