### [Stream Group By](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html)
```java
// Group employees by department
Map<Department, List<Employee>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
// Compute sum of salaries by department
Map<Department, Integer> totalByDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.summingInt(Employee::getSalary)));
// 使用 Stream API 將物件分類並保持排序
Map<String, List<Item>> categorizedItems = items.stream()
.collect(Collectors.groupingBy(
Item::getCategory,
LinkedHashMap::new, // 使用 LinkedHashMap 保持排序
Collectors.toList() // 將子串列收集為 List
));
```
### groupingBy 之後的內容再做轉換
```java
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public static void main(String[] args) {
List<Person> people = List.of(
new Person("Alice", 25),
new Person("Bob", 30),
new Person("Charlie", 25),
new Person("David", 30)
);
// 使用 groupingBy 分組,然後對每個分組的人名轉換為大寫
Map<Integer, List<String>> groupedNames = people.stream()
.collect(Collectors.groupingBy(
Person::getAge,
Collectors.mapping(
person -> person.getName().toUpperCase(),
Collectors.toList()
)
));
System.out.println(groupedNames);
}
}
```
### N 個一組
```java
import java.util.stream.Collectors;
import java.util.*;
public class Main {
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J");
int n = 3; // n 個一組
Map<Integer, List<String>> groupedMap = list.stream()
.collect(Collectors.groupingBy(str -> list.indexOf(str) / n));
groupedMap.forEach((key, value) -> {
System.out.println("Group " + key + ": " + value);
});
}
}
```
### 依照原串列順序做出 Map
```java
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice2", "Alice1", "Charlie", "Bob1", "Bob2", "Alice3");
Map<String, List<String>> groupedNames = names.stream()
.collect(Collectors.groupingBy(name -> name.substring(0, 1), LinkedHashMap::new, Collectors.toList()));
// 印出分組後的結果,保持原始順序
groupedNames.forEach((key, value) -> System.out.println(key + ": " + value));
}
}
```
### groupingBy 將 null 值作為單獨的分組
```java
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", null, "David", null);
Map<String, List<String>> groupedNames = names.stream()
.collect(Collectors.groupingBy(
name -> name == null ? "NULL" : name,Collectors.toList()
));
System.out.println(groupedNames);
// {NULL=[null, null], Bob=[Bob], Alice=[Alice], Charlie=[Charlie], David=[David]}
}
}
```
### Collectors.toMap
```java
List<Person> persons = Arrays.asList(
new Person("John", 20),
new Person("Mary", 30),
new Person("Peter", 25)
);
Map<String, Integer> ageByName = persons.stream()
.collect(Collectors.toMap(
Person::getName, // 定義鍵
Person::getAge // 定義值
));
```
```java
List<Person> persons = Arrays.asList(
new Person("John", 20),
new Person("Mary", 30),
new Person("Peter", 25),
new Person("John", 40)
);
Map<String, Integer> ageByName = persons.stream()
.collect(Collectors.toMap(
Person::getName,
Person::getAge,
(age1, age2) -> age1 // 合併函數:選擇年齡較小的值
));
```
```java
Map<String, Person> personMap = personList.stream()
.collect(Collectors.toMap(Person::getName, Function.identity()));
// Function.identity() 表示物件本身
```
### [Java 中的 Stream 的 reduce 操作](https://www.delftstack.com/zh-tw/howto/java/stream-reduce-in-java/#%e5%9c%a8-java-%e4%b8%ad%e4%bd%bf%e7%94%a8-reduce-%e9%81%8b%e7%ae%97%e6%b1%82%e5%92%8c)
```java
import java.util.Arrays;
public class SimpleTesting {
public static void main(String args[]) {
int[] numbers = {45, 56, 87, 323, 47, 20, 658, 985, 78, 123};
int sum = Arrays.stream(numbers).reduce(0, (a, b) -> a + b);
System.out.print("sum: " +sum);
// finding the min element
int min = Arrays.stream(numbers).reduce(Integer.MAX_VALUE, (a, b) -> a < b ? a : b);
// finding the max element
int max = Arrays.stream(numbers).reduce(Integer.MIN_VALUE, (a, b) -> a > b ? a : b);
}
}
```
#### 將 List 轉換成 String,設定間隔符號、起始符號、結束符號
```java
import java.util.Arrays;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
String result = Arrays.asList("Apple", "Banana", "Cheery", "Orange", "WaterMelone").stream()
.collect(Collectors.joining(",", "(", ")"));
System.out.println(result);
// (Apple,Banana,Cheery,Orange,WaterMelone)
}
}
```
#### [陣列中任一組符合](https://stackoverflow.com/questions/1128723/how-do-i-determine-whether-an-array-contains-a-particular-value-in-java)
```java
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals); // flase
```
```
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEvenNumber = numbers.stream()
.anyMatch(num -> num % 2 == 0);
if(hasEvenNumber) {
System.out.println("List contains at least one even number.");
} else {
System.out.println("List does not contain any even number.");
}
}
}
```
#### map 轉換並收集成 List
```java
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<String> names = Stream.of("tony", "tom", "john")
.map(name -> name.toUpperCase())
.collect(Collectors.toList());
System.out.println(names.toString());
// [TONY, TOM, JOHN]
}
}
```
#### 過濾內容
```java
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<String> names2 = Stream.of("Tony", "Tom", "John", "Andy")
.filter(name -> name.startsWith("T"))
.collect(Collectors.toList());
System.out.println(names2.toString());
// [Tony, Tom]
}
}
```
#### flatMap 的應用
```java
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<String> allNames = Stream.of(Arrays.asList("Tony", "Tom", "John"),
Arrays.asList("Amy", "Emma", "Iris"))
.flatMap(names -> names.stream().map(a -> a.toUpperCase()))
.collect(Collectors.toList());
System.out.println(allNames.toString());
// [TONY, TOM, JOHN, AMY, EMMA, IRIS]
}
}
```
#### 計數
```java
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
long count = Stream.of("Tony", "Tom", "John", "Amy", "Emma", "Iris").count();
System.out.println("count: " + count);
// count: 6
}
}
```
#### 最大值
```java
import java.util.Comparator;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
int max = Stream.of(120,24,59,63,11,74)
.max(Comparator.comparing(n -> n))
.get();
System.out.println("max: " + max);
// max: 120
}
}
```
#### 最小值
```java
import java.util.Comparator;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
int min = Stream.of(120,24,59,63,11,74)
.min(Comparator.comparing(n -> n))
.get();
System.out.println("min: " + min);
// min: 11
}
}
```
#### [flatMap](https://openhome.cc/zh-tw/java/functional-api/flatmap/)
```java
var itemNames = new ArrayList<String>();
for(var order : orders) {
for(var lineItem : order.lineItems()) {
itemNames.add(lineItem.name());
}
}
```
```java
List<String> itemNames = orders.stream()
.flatMap(order -> order.lineItems().stream())
.map(LineItem::name)
.collect(toList());
```
#### 遞增排序 ASC
```java
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> sortedAsc = Stream.of(120,24,59,63,11,74)
.sorted()
.collect(Collectors.toList());
System.out.println("sorted asc: " + sortedAsc);
// sorted asc: [11, 24, 59, 63, 74, 120]
}
}
```
#### 遞減排序 DESC
```java
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> sortedDesc = Stream.of(120,24,59,63,11,74)
.sorted((n1, n2) -> n2 - n1)
.collect(Collectors.toList());
System.out.println("sorted desc: " + sortedDesc);
//sorted desc: [120, 74, 63, 59, 24, 11]
}
}
```
#### 依 String 類型排序
在使用 Java Stream 進行排序時,可以使用 `sorted()` 方法並傳入 `Comparator` 物件來進行比較。比較 String 類型的話,可以使用 `Comparator.comparing()` 方法,並指定要比較的屬性。
以下是一個排序字串列表的範例程式碼:
```java
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<String> strings = Arrays.asList("apple", "banana", "cherry", "date", "fig");
List<String> sortedStrings = strings.stream()
.sorted(Comparator.comparing(String::toString))
.collect(Collectors.toList());
sortedStrings.forEach(System.out::println);
}
}
```
這段程式碼會將 `strings` 列表中的字串按照字母順序進行排序,並輸出排序後的結果。在`Comparator.comparing()` 中,我們使用 `String::toString` 來表示要比較的屬性為字串本身。如果要根據其他條件進行排序,只需要更改 `Comparator.comparing()` 中的函數即可。
#### 根據特定字串順序排序
```java
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
String order = "5, 9, 1, 2";
List<String> result = Stream.of("9", "6", "5", "3", "1", "7", "2", "4", "8")
.sorted((a, b) -> order.indexOf(a) - order.indexOf(b)).collect(Collectors.toList());
System.out.println(result);
// 注意 indexOf 未包含的項目取得的值為 -1,因為未包含的項目會在前方
// [6, 3, 7, 4, 8, 5, 9, 1, 2]
}
}
```
將包含的項目移至前方的作法
```java
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
String order = "5, 9, 1, 2";
List<String> result = Stream.of("9", "6", "5", "3", "1", "7", "2", "4", "8")
.sorted(Comparator.comparing((String a) -> (order.contains(a) ? 0 : 1))
.thenComparing((String a) -> order.indexOf(a)))
.collect(Collectors.toList());
System.out.println(result);
// [5, 9, 1, 2, 6, 3, 7, 4, 8]
}
}
```
### [Removing all duplicates from a List in Java](https://www.baeldung.com/java-remove-duplicates-from-list)
```java
public void
givenListContainsDuplicates_whenRemovingDuplicatesWithJava8_thenCorrect() {
List<Integer> listWithDuplicates = Lists.newArrayList(5, 0, 3, 1, 2, 3, 0, 0);
List<Integer> listWithoutDuplicates = listWithDuplicates.stream()
.distinct()
.collect(Collectors.toList());
assertThat(listWithoutDuplicates, hasSize(5));
assertThat(listWithoutDuplicates, containsInAnyOrder(5, 0, 3, 1, 2));
}
```
### Java stream List to Array
```java
List<String> list = Arrays.asList("apple", "banana", "orange");
String[] array = list.stream().toArray(String[]::new);
```
### IntStream
```java
IntStream.range(0, 10).forEach(i -> System.out.print(i)); // 0123456789
IntStream.range(0, 10).forEach(System.out::print); // 0123456789
// boxed 方法是 IntStream 的一個方法,它將 IntStream 中的每個元素從基本類型 int 轉換為對象類型 Integer,並返回一個 Stream<Integer>
IntStream intStream = IntStream.rangeClosed(1, 5);
List<Integer> integerList = intStream.boxed().collect(Collectors.toList());
```
### 計算標準差 (Standard Deviation)
```java
import java.util.List;
public class StandardDeviationCalculator {
public static void main(String[] args) {
List<Double> data = List.of(2.0, 4.0, 6.0, 8.0, 10.0); // 這裡是你的數據集
// 計算平均值
double mean = data.stream()
.mapToDouble(Double::doubleValue)
.average()
.orElse(0.0);
// 計算每個數值與平均值的差的平方,然後計算它們的平均值
double variance = data.stream()
.mapToDouble(Double::doubleValue)
.map(x -> Math.pow(x - mean, 2))
.average()
.orElse(0.0);
// 計算標準差,即將方差的平方根
double standardDeviation = Math.sqrt(variance);
System.out.println("平均值: " + mean);
System.out.println("標準差: " + standardDeviation);
}
}
```