### 1.
**Introduction to Streams:**
- **Definition:** A Stream is a sequence of elements supporting sequential and
parallel aggregate operations.
- **Key Characteristics:**
- **Functional Programming:** Streams enable functional-style programming.
- **Pipelining:** Operations can be pipelined to form a sequence of
transformations.
- **Immutable:** Streams do not modify the underlying data source.
- **Laziness:** Operations are performed only when needed.
- **Creating Streams:**
- From a Collection: `List.stream()`, `Set.stream()`, `Map.entrySet().stream()`.
- From an Array: `Arrays.stream(array)`.
### 2. **Intermediate and Terminal Operations:**
- **Intermediate Operations:**
- Transform the elements in the stream.
- Examples: `filter`, `map`, `flatMap`, `distinct`, `sorted`.
- **Terminal Operations:**
- Produce a result or a side-effect.
- Examples: `forEach`, `collect`, `reduce`, `count`, `anyMatch`, `allMatch`,
`noneMatch`.
### 3. **Filtering and Mapping:**
- **Filtering:**
- Use `filter` to select elements based on a given condition.
- Example: `stream.filter(x -> x > 5)`.
- **Mapping:**
- Use `map` to transform each element of the stream.
- Example: `stream.map(x -> x * 2)`.
### 4. **FlatMap:**
- **Definition:** `flatMap` is used to flatten a stream of collections into a single
stream.
- **Example:**
```java
List<List<Integer>> listOfLists = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3,
4));
List<Integer> flatList = listOfLists.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
```
### 5. **Sorting:**
- Use `sorted` to order the elements of a stream.
- Example: `stream.sorted()`, `stream.sorted(Comparator.reverseOrder())`.
### 6. **Reducing:**
- **Definition:** The `reduce` operation performs a reduction on the elements
of the stream.
- **Example:**
```java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
```
### 7. **Collectors:**
- **Definition:** The `Collectors` utility class provides various predefined
collectors for common use cases.
- **Examples:**
```java
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
String result = stream.collect(Collectors.joining(", "));
```
### 8. **Grouping and Partitioning:**
- **GroupingBy:**
- Use `Collectors.groupingBy` to group elements by a classifier.
- Example: `Map<Type, List<Element>> result =
stream.collect(Collectors.groupingBy(element -> element.getType()));`
- **PartitioningBy:**
- Use `Collectors.partitioningBy` to partition elements into two groups based on
a predicate.
- Example: `Map<Boolean, List<Element>> result =
stream.collect(Collectors.partitioningBy(element -> element.isSpecial()));`
### 9. **Parallel Streams:**
- Use `parallelStream()` to convert a sequential stream into a parallel stream.
- Be cautious with stateful operations and shared mutable data.
### 10. **Optional:**
- Use `Optional` to represent an optional value or the absence of a value.
- Helps in avoiding null checks and NullPointerExceptions.
- Example: `Optional<String> result = stream.findFirst();`
### 11. **Performance Considerations:**
- Streams may not always improve performance.
- Parallel streams introduce overhead and may not be suitable for all scenarios.
- Measure performance and choose the right approach.
### 12. **Integration with Lambda Expressions:**
- Streams work seamlessly with lambda expressions, allowing concise and
expressive code.
- Enables a functional programming style for collection manipulation.
### 13. **Example:**
- Consider a simple example of filtering, mapping, and collecting:
```java
List<String> languages = Arrays.asList("Java", "Python", "JavaScript", "C#",
"Ruby");
List<String> result = languages.stream()
.filter(lang -> lang.length() > 4)
.map(String::toUpperCase)
.collect(Collectors.toList());
```
These notes cover the fundamental concepts and operations of Java 8 Streams.
They provide a foundation for leveraging the powerful capabilities of the Streams
API to write cleaner, more expressive, and often more efficient code when
working with collections in Java.