Java Streams

Streams come instead of Iterators and iterations.
From You can create streams from collections, arrays, generators, or iterators.
To You can collect stream results in collections, arrays, strings, or maps.
Operations Specify intermediate operations for transforming the initial stream into others, possibly in multiple steps. Intermediate - return Streams objects.
Apply a terminal (reduction) operation to produce a result. This operation forces the execution of the lazy operations that precede it. Afterwards, the stream can no longer be used.
Collection -> Stream
Use method .stream()
List<String> words = List.of("I", "am", "a", "list", "of", "Strings"); // OR
List<String> words = List.of(contents.split("\\PL+")); // Split into words; nonletters are delimiters
Stream<String> stream = strings.stream();
Array -> Stream
Use method Stream.of()
Stream<String> words = Stream.of(contents.split("\\PL+"));  // split returns a String[] array
Stream<String> song = Stream.of("gently", "down", "the", "stream");
Empty Stream
Stream<String> silence = Stream.empty(); // Generic type <String> is inferred; same as Stream.<String>empty()
Infinite Stream
.generate, .iterate
Stream<String> echos = Stream.generate(() -> "Echo");  // constant values
Stream<Double> randoms = Stream.generate(Math::random);		// random
Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));  // 1 2 3 ...

// To produce a finite stream instead, add a predicate that specifies when the iteration should finish:
BigInteger limit = new BigInteger("10000000");
Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.compareTo(limit) < 0, n -> n.add(BigInteger.ONE));
filter, map, and flatMap
every transformation yelds a new stream
To filter
List words = List.of(contents.split("\\PL+"));
Stream longWords = words.stream().filter(w -> w.length() > 12);
To transform use the map method and pass the function that carries out the transformation.
Stream lowercaseWords = words.stream().map(String::toLowerCase); // OR
Stream firstLetters = words.stream().map(s -> s.substring(0, 1));

a function is applied to each element, and the result is a new stream with the results. If Input of the function is a nested structure (List of Lists, Stream of Streams) the result would be stream of streams. With .flatMap() - the result would be flat Stream
Examples
List<String> myList = Stream.of("a", "b").map(String::toUpperCase).collect(Collectors.toList());
// Result is List "A","B"
List<List<String>> list = Arrays.asList( Arrays.asList("a"), Arrays.asList("b"));

List<Stream<String>> myList2 = list.stream().map(Collection::stream).collect(Collectors.toList());
// The type would be List<Stream<String>> not List of Lists or Strings

List<String> myList2 = list.stream().flatMap(Collection::stream).collect(Collectors.toList());
// flatMap - eliminate nested Streams

List<String> myList3 = list.stream().flatMap(Collection::stream).map(String::toUpperCase).collect(Collectors.toList());
// The right way to uppercase and flatten

// flatMap can be applied to Optional also to avoid nested Optionals
assertEquals(Optional.of("STRING"), Optional.of("string").flatMap(s -> Optional.of("STRING")));
Extracting Substreams and Combining Streams

.limit(n)
.skip(n)
.takeWhile()
.dropWhile()
concat
stream.limit(n) returns a new stream that ends after n elements. Can cut infinite stream to a size
Stream<Double> randoms = Stream.generate(Math::random).limit(100);

stream.skip(n) does the exact opposite. It discards the first n elements.
Stream<String> words = Stream.of(contents.split("\\PL+")).skip(1);

stream.takeWhile(predicate) call takes all elements from the stream while the predicate is true, and then stops.
List<String> lista= Arrays.asList("   ","hola","que","tal","estas","hoy","aqui");
lista.stream().takeWhile((s)->s.length()<5).forEach(System.out::println);
dropWhile method does the opposite, dropping elements while a condition is true and yielding a stream of all elements starting with the first one for which the condition was false.
lista.stream().dropWhile(s -< s.trim().length() == 0).forEach(System.out::println);
You can concatenate two streams with the static concat method of the Stream class
Stream.concat(Stream.of("hola","que"), Stream.of("tal","estas")).forEach(System.out::println);
Of course, the first stream should not be infinite - otherwise the second wouldn’t ever get a chance.
.distinct()
.sorted()
.peek()
Stream<String> uniqueWords = Stream.of("merrily", "merrily", "merrily", "gently").distinct();
Different sorted method: for streams of Comparable elements, or with a Comparator. Here, we sort strings so that the longest ones come first:
Stream<String> longestFirst = words.stream().sorted(Comparator.comparing(String::length).reversed());
peek method yields another stream with the same elements as the original, but a function is invoked every time an element is retrieved. That is handy for debugging
Object[] powers = Stream.iterate(1.0, p -> p * 2).peek(e -> System.out.println("Fetching " + e)).limit(20).toArray();
Simple Reductions
.max()
.min() .count() .findFirst() .findAny() .anyMatch()
No, singleton beans are not thread-safe, as thread safety is about execution, whereas the singleton is a design pattern focusing on creation. Thread safety depends only on the bean implementation itself.
What are the autowiring modes?
Autowiring enables the programmer to inject the bean automatically. We don't need to write explicit injection logic.
1)nothis is the default mode, it means autowiring is not enabled.
2)byNameinjects the bean based on the property name. It uses setter method.
3)byTypeinjects the bean based on the property type. It uses setter method.
4)constructorIt injects the bean using constructor
Spring Bean Life Cycle