feat: Stream 结束
This commit is contained in:
parent
ba47472c5c
commit
71e05346af
|
@ -0,0 +1,967 @@
|
||||||
|
# Java Stream详解
|
||||||
|
|
||||||
|
## 创建Stream
|
||||||
|
|
||||||
|
### Stream.builder()创建
|
||||||
|
|
||||||
|
```java
|
||||||
|
Stream<Integer> build = Stream.<Integer>builder()
|
||||||
|
.add(1)
|
||||||
|
.add(12)
|
||||||
|
.add(3)
|
||||||
|
.add(34)
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stream.of创建
|
||||||
|
|
||||||
|
```java
|
||||||
|
Stream<Integer> integerStream = Stream.of(1, 2, 34, 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 空Stream创建
|
||||||
|
|
||||||
|
```java
|
||||||
|
Stream<Object> objectStream = Stream.empty();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stream.generate创建
|
||||||
|
|
||||||
|
如果不加限制运行时会一直创建像死循环一样
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Stream.generate创建
|
||||||
|
Stream<Integer> generate = Stream.generate(() -> ThreadLocalRandom.current().nextInt(10))
|
||||||
|
.limit(10);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stream.iterate创建
|
||||||
|
|
||||||
|
```
|
||||||
|
// 不加限制会一直创建
|
||||||
|
Stream.iterate(100, seed -> seed + 1)
|
||||||
|
.limit(10)
|
||||||
|
.forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### IntStream创建创建
|
||||||
|
|
||||||
|
```java
|
||||||
|
// IntStream创建[1,10)
|
||||||
|
IntStream.range(1, 10)
|
||||||
|
.forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### IntStream.rangeClosed创建闭区间
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 创建闭区间[1,10]
|
||||||
|
IntStream.rangeClosed(1,10)
|
||||||
|
.forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arrays.asList创建
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Arrays.asList创建
|
||||||
|
Arrays.asList("a","b","c","d","e","f")
|
||||||
|
.forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 创建Stream<Map.Entry<String, String>>
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 创建Stream<Map.Entry<String, String>>
|
||||||
|
Stream<Map.Entry<String, String>> stream = new HashMap<String, String>() {{
|
||||||
|
put("a", "b");
|
||||||
|
put("c", "d");
|
||||||
|
}}.entrySet().stream();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Files中的Stream
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Files中的Stream
|
||||||
|
Stream<String> lines = Files.lines(Paths.get("xxx.md"), StandardCharsets.UTF_8);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Stream的操作
|
||||||
|
|
||||||
|
### distinct操作
|
||||||
|
|
||||||
|
```java
|
||||||
|
Stream<Object> stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 去重操作
|
||||||
|
stream.distinct().forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
> 输出:
|
||||||
|
>
|
||||||
|
> ```
|
||||||
|
> 1
|
||||||
|
> 2
|
||||||
|
> 3
|
||||||
|
> 4
|
||||||
|
> ```
|
||||||
|
|
||||||
|
### filter操作
|
||||||
|
|
||||||
|
```java
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 过滤器,满足值为2的筛选
|
||||||
|
stream.filter(x -> x.equals(2)).forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### limit操作
|
||||||
|
|
||||||
|
```java
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 选择序列个数为3
|
||||||
|
stream.limit(3).forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### map操作
|
||||||
|
|
||||||
|
```java
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 映射,可以修改原本的类型
|
||||||
|
stream.map(Object::toString).forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### skip操作
|
||||||
|
|
||||||
|
```java
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 跳过前两个数
|
||||||
|
stream.skip(2).forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### peek操作
|
||||||
|
|
||||||
|
如果对一个对象进行操作,比如Person中有姓名和年龄,这时候通过peek修改了其中的年龄,那么这个值会被改变
|
||||||
|
|
||||||
|
```java
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 不会使元素数据、类型产生改变
|
||||||
|
stream.peek(x -> ThreadLocalRandom.current().nextInt(100)).limit(10).forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### sorted操作
|
||||||
|
|
||||||
|
排序操作,也可以指定内容进行排序
|
||||||
|
|
||||||
|
```java
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 从小到大排序
|
||||||
|
stream.sorted().forEach(System.out::println);
|
||||||
|
|
||||||
|
// 提供重载方法
|
||||||
|
stream.sorted(Comparator.comparing(Object::toString)).forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### flatMap操作
|
||||||
|
|
||||||
|
扁平化数据,JavaScript中也有这个
|
||||||
|
|
||||||
|
```java
|
||||||
|
ArrayList<Integer> list = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}};
|
||||||
|
List<ArrayList<Integer>> arrayListList = List.of(list);
|
||||||
|
|
||||||
|
// 扁平化数组
|
||||||
|
arrayListList.stream().flatMap(Collection::stream).forEach(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### match操作
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 需要满足所有元素都匹配条件
|
||||||
|
boolean allMatch = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.allMatch(i -> i > 4);
|
||||||
|
System.out.println(allMatch);// false
|
||||||
|
|
||||||
|
// 只要有一个元素满足匹配条件
|
||||||
|
boolean anyMatch = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.anyMatch(x -> x > 4);
|
||||||
|
System.out.println(anyMatch);// true
|
||||||
|
|
||||||
|
// 所有元素都不满足条件
|
||||||
|
boolean noneMatch = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.noneMatch(x -> x > 4);
|
||||||
|
System.out.println(noneMatch);// false
|
||||||
|
```
|
||||||
|
|
||||||
|
### find操作
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 找到第一个数字
|
||||||
|
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(System.out::println);
|
||||||
|
|
||||||
|
// 获取任意一个数字
|
||||||
|
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.findAny()
|
||||||
|
.ifPresent(System.out::println);
|
||||||
|
```
|
||||||
|
|
||||||
|
### forEach操作
|
||||||
|
|
||||||
|
不解释,放在最后,如果使用了forEach那么后面就无法再跟其它流函数
|
||||||
|
|
||||||
|
### 计数、求和、最小值、最大值
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 计数
|
||||||
|
long count = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.count();
|
||||||
|
System.out.println(count);// 9
|
||||||
|
|
||||||
|
// 求和
|
||||||
|
long sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.mapToLong(Integer::longValue)
|
||||||
|
.sum();
|
||||||
|
System.out.println(sum);
|
||||||
|
|
||||||
|
// 查找最小值
|
||||||
|
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.min(Comparator.comparing(i -> i))
|
||||||
|
.ifPresent(System.out::println);
|
||||||
|
|
||||||
|
// 查找最大值
|
||||||
|
Optional<Integer> max = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.max(Comparator.comparing(i -> i));
|
||||||
|
System.out.println(max.get());
|
||||||
|
```
|
||||||
|
|
||||||
|
## Collectors使用
|
||||||
|
|
||||||
|
收集器
|
||||||
|
|
||||||
|
### toList
|
||||||
|
|
||||||
|
将元素输出到 list
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
|
||||||
|
List<String> upperCaseNames = names.stream()
|
||||||
|
.map(String::toUpperCase)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
```
|
||||||
|
|
||||||
|
### toSet
|
||||||
|
|
||||||
|
将元素输出到 Set
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
|
||||||
|
Set<String> uniqueNames = names.stream()
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
```
|
||||||
|
|
||||||
|
### toMap
|
||||||
|
|
||||||
|
将元素输出到 Map
|
||||||
|
|
||||||
|
- 2个参数:key,value
|
||||||
|
- 3个参数:key,value,处理key冲突问题
|
||||||
|
- 4个参数:key,value,处理key冲突问题,转换map类型
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
|
||||||
|
Map<String, Integer> nameLengthMap = names.stream()
|
||||||
|
.collect(Collectors.toMap(name -> name, String::length));
|
||||||
|
```
|
||||||
|
|
||||||
|
### reduce
|
||||||
|
|
||||||
|
语法
|
||||||
|
|
||||||
|
```java
|
||||||
|
Optional<T> reduce(BinaryOperator<T> accumulator)
|
||||||
|
Optional<T> reduce(T identity, BinaryOperator<T> accumulator)
|
||||||
|
```
|
||||||
|
|
||||||
|
使用
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
|
||||||
|
|
||||||
|
// 使用 reduce 求和
|
||||||
|
Optional<Integer> sum = numbers.stream()
|
||||||
|
.reduce(Integer::sum);
|
||||||
|
sum.ifPresent(System.out::println); // 输出: 15
|
||||||
|
|
||||||
|
// 使用带初始值的 reduce
|
||||||
|
int sumWithIdentity = numbers.stream()
|
||||||
|
.reduce(0, Integer::sum);
|
||||||
|
System.out.println(sumWithIdentity); // 输出: 15
|
||||||
|
```
|
||||||
|
|
||||||
|
### summingDouble
|
||||||
|
|
||||||
|
将求和后的结果转成Double
|
||||||
|
|
||||||
|
语法
|
||||||
|
|
||||||
|
```java
|
||||||
|
static Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper)
|
||||||
|
```
|
||||||
|
|
||||||
|
使用
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample07 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Product> products = Arrays.asList(
|
||||||
|
new Product("Apple", 1.20),
|
||||||
|
new Product("Banana", 0.80),
|
||||||
|
new Product("Orange", 1.00)
|
||||||
|
);
|
||||||
|
|
||||||
|
double totalCost = products.stream().mapToDouble(Product::getPrice).sum();
|
||||||
|
|
||||||
|
System.out.println("Total Cost: " + totalCost); // 输出: Total Cost: 3.0
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static class Product {
|
||||||
|
private final String name;
|
||||||
|
private final double price;
|
||||||
|
|
||||||
|
public Product(String name, double price) {
|
||||||
|
this.name = name;
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### groupingBy
|
||||||
|
|
||||||
|
- 1个参数:指定key是什么
|
||||||
|
- 2个参数:指定key和value
|
||||||
|
- 3个参数:key,value,value类型
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample08 {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 30),
|
||||||
|
new Person("David", 25)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 根据年龄将一组人分组
|
||||||
|
Map<Integer, List<Person>> groupedByAge = people.stream()
|
||||||
|
.collect(Collectors.groupingBy(Person::getAge));
|
||||||
|
|
||||||
|
// 自定义收集器:可以传递第二个参数来指定下游收集器。
|
||||||
|
Map<Integer, Long> groupedByAgeCount = people.stream()
|
||||||
|
.collect(Collectors.groupingBy(Person::getAge, Collectors.counting()));
|
||||||
|
|
||||||
|
// 多级分组:可以嵌套使用 groupingBy 进行多级分组。
|
||||||
|
Map<Integer, Map<String, List<Person>>> groupedByAgeAndName = people.stream()
|
||||||
|
.collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getName)));
|
||||||
|
|
||||||
|
System.out.println(groupedByAge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> 输出:
|
||||||
|
>
|
||||||
|
> ```java
|
||||||
|
> {25=[Bob (25), David (25)], 30=[Alice (30), Charlie (30)]}
|
||||||
|
> {25=2, 30=2}
|
||||||
|
> {25={Bob=[Bob (25)], David=[David (25)]}, 30={Alice=[Alice (30)], Charlie=[Charlie (30)]}}
|
||||||
|
> ```
|
||||||
|
|
||||||
|
### Collectors.averaging
|
||||||
|
|
||||||
|
求平均值
|
||||||
|
|
||||||
|
```java
|
||||||
|
// averagingLong
|
||||||
|
List<Long> numbers = Arrays.asList(1L, 2L, 3L, 4L, 5L);
|
||||||
|
double averagingLongNumbers = numbers.stream()
|
||||||
|
.collect(Collectors.averagingLong(Long::longValue));
|
||||||
|
System.out.println("Average: " + averagingLongNumbers);
|
||||||
|
|
||||||
|
// averagingDouble
|
||||||
|
List<Double> averagingDoubleNumbers = Arrays.asList(1.5, 2.5, 3.5, 4.5, 5.5);
|
||||||
|
double averagingDouble = averagingDoubleNumbers.stream()
|
||||||
|
.collect(Collectors.averagingDouble(Double::doubleValue));
|
||||||
|
System.out.println("Average: " + averagingDouble);
|
||||||
|
|
||||||
|
// averagingInt
|
||||||
|
List<Integer> averagingIntNumbers = Arrays.asList(1, 2, 3, 4, 5);
|
||||||
|
double averagingInt = averagingIntNumbers.stream()
|
||||||
|
.collect(Collectors.averagingInt(Integer::intValue));
|
||||||
|
System.out.println("Average: " + averagingInt);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collectors.collectingAndThen
|
||||||
|
|
||||||
|
先计算平均年龄,之后将计算结果转为整数,可以理解为:先收集之后再干嘛
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample10 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.collectingAndThen 计算平均年龄并转换为整数
|
||||||
|
int averageAge = people.stream()
|
||||||
|
.collect(Collectors.collectingAndThen(
|
||||||
|
Collectors.averagingInt(Person::getAge),// 先计算平均年龄
|
||||||
|
Double::intValue // 之后将结果转换为整数
|
||||||
|
));
|
||||||
|
|
||||||
|
System.out.println("Average Age: " + averageAge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collectors.counting使用
|
||||||
|
|
||||||
|
求总数,和SQL中count类似
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample11 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.counting 统计人数
|
||||||
|
long count = people.stream()
|
||||||
|
.collect(Collectors.counting());
|
||||||
|
|
||||||
|
System.out.println("Total number of people: " + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collectors.mapping
|
||||||
|
|
||||||
|
类似Stream中的map,先操作(此操作会可以改变其类似),之后在做处理
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample12 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35),
|
||||||
|
new Person("David", 40)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.mapping 和 Collectors.toSet 只收集大于 30 岁的人的年龄
|
||||||
|
Set<Integer> agesAbove30 = people.stream()
|
||||||
|
.filter(person -> person.getAge() > 30)
|
||||||
|
.collect(Collectors.mapping(Person::getAge, Collectors.toSet()));
|
||||||
|
|
||||||
|
System.out.println("Ages above 30: " + agesAbove30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collectors.joining
|
||||||
|
|
||||||
|
- 无参数:将元素连接在一起,中间没有内容分隔
|
||||||
|
- 1个参数:将元素连接,使用传入的符号进行分割
|
||||||
|
- 3个参数:将元素连接,传入第一个参数进行分割,第二个参数是整个处理完成元素的前缀,第三个参数是整个处理完成的后缀
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample13 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice"),
|
||||||
|
new Person("Bob"),
|
||||||
|
new Person("Charlie")
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.joining 连接名字,添加前缀和后缀
|
||||||
|
String result = people.stream()
|
||||||
|
.map(Person::getName) // 提取名字
|
||||||
|
.collect(Collectors.joining(", ", "[", "]")); // 使用逗号和空格作为分隔符,添加前缀和后缀
|
||||||
|
|
||||||
|
System.out.println("Names: " + result);// Names: [Alice, Bob, Charlie]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Person(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collectors.summing使用
|
||||||
|
|
||||||
|
#### summingInt
|
||||||
|
|
||||||
|
求和转成int
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample14 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summingInt 计算年龄总和
|
||||||
|
int totalAge = people.stream()
|
||||||
|
.collect(Collectors.summingInt(Person::getAge));
|
||||||
|
|
||||||
|
System.out.println("Total Age: " + totalAge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### summingDouble
|
||||||
|
|
||||||
|
求和转成double
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample15 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Product> products = Arrays.asList(
|
||||||
|
new Product("Laptop", 999.99),
|
||||||
|
new Product("Smartphone", 499.99),
|
||||||
|
new Product("Tablet", 299.99)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summingDouble 计算价格总和
|
||||||
|
double totalPrice = products.stream()
|
||||||
|
.collect(Collectors.summingDouble(Product::getPrice));
|
||||||
|
|
||||||
|
System.out.println("Total Price: " + totalPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static
|
||||||
|
class Product {
|
||||||
|
private final String name;
|
||||||
|
@Getter
|
||||||
|
private final double price;
|
||||||
|
|
||||||
|
public Product(String name, double price) {
|
||||||
|
this.name = name;
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### summingLong
|
||||||
|
|
||||||
|
求和转成long
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample16 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Transaction> transactions = Arrays.asList(
|
||||||
|
new Transaction(1000L),
|
||||||
|
new Transaction(2500L),
|
||||||
|
new Transaction(1500L)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summingLong 计算总金额
|
||||||
|
long totalAmount = transactions.stream()
|
||||||
|
.collect(Collectors.summingLong(Transaction::getAmount));
|
||||||
|
|
||||||
|
System.out.println("Total Amount: " + totalAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Transaction {
|
||||||
|
private final long amount;
|
||||||
|
|
||||||
|
public Transaction(long l) {
|
||||||
|
this.amount = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collectors.minBy和Collectors.maxBy
|
||||||
|
|
||||||
|
#### minBy
|
||||||
|
|
||||||
|
求最小值
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample17 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.minBy 找到年龄最小的人
|
||||||
|
Optional<Person> youngest = people.stream()
|
||||||
|
.collect(Collectors.minBy(Comparator.comparingInt(Person::getAge)));
|
||||||
|
|
||||||
|
youngest.ifPresent(person ->
|
||||||
|
System.out.println("Youngest Person: " + person.getName() + ", Age: " + person.getAge()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### maxBy
|
||||||
|
|
||||||
|
求最大值
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample18 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.maxBy 找到年龄最大的人
|
||||||
|
Optional<Person> oldest = people.stream()
|
||||||
|
.collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge)));
|
||||||
|
|
||||||
|
oldest.ifPresent(person ->
|
||||||
|
System.out.println("Oldest Person: " + person.getName() + ", Age: " + person.getAge()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collectors.summarizing
|
||||||
|
|
||||||
|
#### Collectors.summarizingInt
|
||||||
|
|
||||||
|
求和转成类型
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample19 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summarizingInt 统计年龄信息
|
||||||
|
IntSummaryStatistics ageStats = people.stream()
|
||||||
|
.collect(Collectors.summarizingInt(Person::getAge));
|
||||||
|
|
||||||
|
System.out.println("Count: " + ageStats.getCount());
|
||||||
|
System.out.println("Sum: " + ageStats.getSum());
|
||||||
|
System.out.println("Min: " + ageStats.getMin());
|
||||||
|
System.out.println("Max: " + ageStats.getMax());
|
||||||
|
System.out.println("Average: " + ageStats.getAverage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Collectors.summarizingLong
|
||||||
|
|
||||||
|
求和转成类型
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample20 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Transaction> transactions = Arrays.asList(
|
||||||
|
new Transaction(1000L),
|
||||||
|
new Transaction(2500L),
|
||||||
|
new Transaction(1500L)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summarizingLong 统计金额信息
|
||||||
|
LongSummaryStatistics amountStats = transactions.stream()
|
||||||
|
.collect(Collectors.summarizingLong(Transaction::getAmount));
|
||||||
|
|
||||||
|
System.out.println("Count: " + amountStats.getCount());
|
||||||
|
System.out.println("Sum: " + amountStats.getSum());
|
||||||
|
System.out.println("Min: " + amountStats.getMin());
|
||||||
|
System.out.println("Max: " + amountStats.getMax());
|
||||||
|
System.out.println("Average: " + amountStats.getAverage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Transaction {
|
||||||
|
private final long amount;
|
||||||
|
|
||||||
|
public Transaction(long amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Collectors.summarizingDouble
|
||||||
|
|
||||||
|
求和转成类型
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample21 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Product> products = Arrays.asList(
|
||||||
|
new Product("Laptop", 1200.50),
|
||||||
|
new Product("Phone", 800.75),
|
||||||
|
new Product("Tablet", 300.00)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summarizingDouble 统计价格信息
|
||||||
|
DoubleSummaryStatistics priceStats = products.stream()
|
||||||
|
.collect(Collectors.summarizingDouble(Product::getPrice));
|
||||||
|
|
||||||
|
System.out.println("Count: " + priceStats.getCount());
|
||||||
|
System.out.println("Sum: " + priceStats.getSum());
|
||||||
|
System.out.println("Min: " + priceStats.getMin());
|
||||||
|
System.out.println("Max: " + priceStats.getMax());
|
||||||
|
System.out.println("Average: " + priceStats.getAverage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static
|
||||||
|
class Product {
|
||||||
|
private final String name;
|
||||||
|
private final double price;
|
||||||
|
|
||||||
|
public Product(String name, double price) {
|
||||||
|
this.name = name;
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collectors.partitioningBy
|
||||||
|
|
||||||
|
以Boolean为 key的分组,key为Boolean值,后面是value值,属于Map集合
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StreamExample22 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 17),
|
||||||
|
new Person("Charlie", 25),
|
||||||
|
new Person("David", 15)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.partitioningBy 按年龄分组
|
||||||
|
Map<Boolean, List<Person>> partitionedByAge = people.stream()
|
||||||
|
.collect(Collectors.partitioningBy(person -> person.getAge() >= 18));
|
||||||
|
|
||||||
|
// 输出结果
|
||||||
|
System.out.println("成年人:");
|
||||||
|
partitionedByAge.get(true).forEach(person -> System.out.println(person.getName()));
|
||||||
|
|
||||||
|
System.out.println("未成年人:");
|
||||||
|
partitionedByAge.get(false).forEach(person -> System.out.println(person.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -69,4 +69,199 @@ System.out.println(b);
|
||||||
LinkedBlockingQueue<Integer> integers1 = new LinkedBlockingQueue<>();
|
LinkedBlockingQueue<Integer> integers1 = new LinkedBlockingQueue<>();
|
||||||
boolean b1 = integers1.remainingCapacity() == Integer.MAX_VALUE;
|
boolean b1 = integers1.remainingCapacity() == Integer.MAX_VALUE;
|
||||||
System.out.println(b1);
|
System.out.println(b1);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## InterruptedException使用
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class AtomicExample08 {
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
DelayQueue<DelayedEntry> queue = new DelayQueue<>();
|
||||||
|
queue.add(new DelayedEntry("A", 1000L));
|
||||||
|
queue.add(new DelayedEntry("B", 1000L));
|
||||||
|
queue.add(new DelayedEntry("C", 1000L));
|
||||||
|
queue.add(new DelayedEntry("D", 1000L));
|
||||||
|
queue.add(new DelayedEntry("E", 1000L));
|
||||||
|
queue.add(new DelayedEntry("F", 1000L));
|
||||||
|
queue.add(new DelayedEntry("G", 1000L));
|
||||||
|
queue.add(new DelayedEntry("H", 1000L));
|
||||||
|
queue.add(new DelayedEntry("I", 1000L));
|
||||||
|
|
||||||
|
// 非阻塞读取,立即返回但不移除头部元素,队列为空返回null
|
||||||
|
assert queue.peek() != null;
|
||||||
|
System.out.println(queue.peek().value);
|
||||||
|
|
||||||
|
// 非阻塞读取,当队列为空或者头部元素未达到过期时间返回值为null
|
||||||
|
System.out.println(Objects.requireNonNull(queue.poll()).value);
|
||||||
|
|
||||||
|
// 最大阻塞单位时间,到达阻塞单位时间后,此刻为空或者头部元素未达到过期时间返回值为null,否则立即移出头部元素
|
||||||
|
System.out.println(Objects.requireNonNull(queue.poll(3, TimeUnit.SECONDS)).value);
|
||||||
|
|
||||||
|
// 会一直阻塞到队列中有元素,并且队列头部元素达到过期时间,之后从队列中移除并返回
|
||||||
|
System.out.println(queue.take().value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首先要实现Delayed接口
|
||||||
|
@Getter
|
||||||
|
static class DelayedEntry implements Delayed {
|
||||||
|
private final String value;
|
||||||
|
private final long time;
|
||||||
|
|
||||||
|
private DelayedEntry(String value, long time) {
|
||||||
|
this.time = time;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDelay(TimeUnit unit) {
|
||||||
|
long delta = time - System.currentTimeMillis();
|
||||||
|
return unit.convert(delta, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Delayed o) {
|
||||||
|
if (this.time < ((DelayedEntry) o).time) {
|
||||||
|
return -1;
|
||||||
|
} else if (this.time > ((DelayedEntry) o).time) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ConcurrentLinkedQueue(并发队列)性能
|
||||||
|
|
||||||
|
ConcurrentLinkedQueue要优秀很多
|
||||||
|
|
||||||
|
```java
|
||||||
|
import org.openjdk.jmh.annotations.*;
|
||||||
|
import org.openjdk.jmh.runner.Runner;
|
||||||
|
import org.openjdk.jmh.runner.RunnerException;
|
||||||
|
import org.openjdk.jmh.runner.options.Options;
|
||||||
|
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Measurement(iterations = 10)
|
||||||
|
@Warmup(iterations = 10)
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@State(Scope.Thread)
|
||||||
|
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||||
|
public class AtomicExample09 {
|
||||||
|
private final static String DATA = "TEST";
|
||||||
|
private final static Object LOCK = new Object();
|
||||||
|
private SynchronizedLinkedList synchronizedLinkedList;
|
||||||
|
private ConcurrentLinkedQueue<String> concurrentLinkedQueue;
|
||||||
|
|
||||||
|
// 如果使用不当反而会降低性能
|
||||||
|
public static void main(String[] args) throws RunnerException {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(AtomicExample09.class.getSimpleName())
|
||||||
|
.forks(1)
|
||||||
|
.build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Setup(Level.Iteration)
|
||||||
|
public void setUp() {
|
||||||
|
synchronizedLinkedList = new SynchronizedLinkedList();
|
||||||
|
concurrentLinkedQueue = new ConcurrentLinkedQueue<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 SynchronizedLinkedList
|
||||||
|
@Group("sync")
|
||||||
|
@Benchmark
|
||||||
|
@GroupThreads(5)
|
||||||
|
public void synchronizedListAdd() {
|
||||||
|
synchronizedLinkedList.addLast(DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Group("sync")
|
||||||
|
@Benchmark
|
||||||
|
@GroupThreads(5)
|
||||||
|
public String synchronizedListGet() {
|
||||||
|
return synchronizedLinkedList.removeFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 ConcurrentLinkedQueue
|
||||||
|
@Group("concurrent")
|
||||||
|
@Benchmark
|
||||||
|
@GroupThreads(5)
|
||||||
|
public void concurrentLinkedQueueAdd() {
|
||||||
|
concurrentLinkedQueue.offer(DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Group("concurrent")
|
||||||
|
@Benchmark
|
||||||
|
@GroupThreads(5)
|
||||||
|
public String concurrentLinkedQueueGet() {
|
||||||
|
return concurrentLinkedQueue.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SynchronizedLinkedList {
|
||||||
|
private final LinkedList<String> list = new LinkedList<>();
|
||||||
|
|
||||||
|
void addLast(String element) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
list.addLast(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String removeFirst() {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return list.removeLast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 测试结果
|
||||||
|
// Benchmark Mode Cnt Score Error Units
|
||||||
|
// AtomicExample09.concurrent avgt 10 0.221 ± 0.649 us/op
|
||||||
|
// AtomicExample09.concurrent:concurrentLinkedQueueAdd avgt 10 0.407 ± 1.296 us/op
|
||||||
|
// AtomicExample09.concurrent:concurrentLinkedQueueGet avgt 10 0.034 ± 0.048 us/op
|
||||||
|
// AtomicExample09.sync avgt 10 0.240 ± 0.039 us/op
|
||||||
|
// AtomicExample09.sync:synchronizedListAdd avgt 10 0.232 ± 0.034 us/op
|
||||||
|
// AtomicExample09.sync:synchronizedListGet avgt 10 0.248 ± 0.044 us/op
|
||||||
|
```
|
||||||
|
|
||||||
|
> 测试需要下载 pom 包
|
||||||
|
>
|
||||||
|
> ```xml
|
||||||
|
> <dependencies>
|
||||||
|
> <dependency>
|
||||||
|
> <groupId>org.projectlombok</groupId>
|
||||||
|
> <artifactId>lombok</artifactId>
|
||||||
|
> <version>1.18.36</version>
|
||||||
|
> </dependency>
|
||||||
|
> <!-- slf4j -->
|
||||||
|
> <dependency>
|
||||||
|
> <groupId>org.slf4j</groupId>
|
||||||
|
> <artifactId>slf4j-api</artifactId>
|
||||||
|
> <version>2.0.16</version>
|
||||||
|
> </dependency>
|
||||||
|
> <dependency>
|
||||||
|
> <groupId>org.slf4j</groupId>
|
||||||
|
> <artifactId>slf4j-simple</artifactId>
|
||||||
|
> <version>2.0.16</version>
|
||||||
|
> </dependency>
|
||||||
|
> <!-- jmh -->
|
||||||
|
> <dependency>
|
||||||
|
> <groupId>org.openjdk.jmh</groupId>
|
||||||
|
> <artifactId>jmh-core</artifactId>
|
||||||
|
> <version>1.19</version>
|
||||||
|
> </dependency>
|
||||||
|
> <dependency>
|
||||||
|
> <groupId>org.openjdk.jmh</groupId>
|
||||||
|
> <artifactId>jmh-generator-annprocess</artifactId>
|
||||||
|
> <version>1.19</version>
|
||||||
|
> </dependency>
|
||||||
|
> </dependencies>
|
||||||
|
> ```
|
|
@ -1,4 +1,65 @@
|
||||||
package cn.bunny.atomic;
|
package cn.bunny.atomic;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.DelayQueue;
|
||||||
|
import java.util.concurrent.Delayed;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class AtomicExample08 {
|
public class AtomicExample08 {
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
DelayQueue<DelayedEntry> queue = new DelayQueue<>();
|
||||||
|
queue.add(new DelayedEntry("A", 1000L));
|
||||||
|
queue.add(new DelayedEntry("B", 1000L));
|
||||||
|
queue.add(new DelayedEntry("C", 1000L));
|
||||||
|
queue.add(new DelayedEntry("D", 1000L));
|
||||||
|
queue.add(new DelayedEntry("E", 1000L));
|
||||||
|
queue.add(new DelayedEntry("F", 1000L));
|
||||||
|
queue.add(new DelayedEntry("G", 1000L));
|
||||||
|
queue.add(new DelayedEntry("H", 1000L));
|
||||||
|
queue.add(new DelayedEntry("I", 1000L));
|
||||||
|
|
||||||
|
// 非阻塞读取,立即返回但不移除头部元素,队列为空返回null
|
||||||
|
assert queue.peek() != null;
|
||||||
|
System.out.println(queue.peek().value);
|
||||||
|
|
||||||
|
// 非阻塞读取,当队列为空或者头部元素未达到过期时间返回值为null
|
||||||
|
System.out.println(Objects.requireNonNull(queue.poll()).value);
|
||||||
|
|
||||||
|
// 最大阻塞单位时间,到达阻塞单位时间后,此刻为空或者头部元素未达到过期时间返回值为null,否则立即移出头部元素
|
||||||
|
System.out.println(Objects.requireNonNull(queue.poll(3, TimeUnit.SECONDS)).value);
|
||||||
|
|
||||||
|
// 会一直阻塞到队列中有元素,并且队列头部元素达到过期时间,之后从队列中移除并返回
|
||||||
|
System.out.println(queue.take().value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首先要实现Delayed接口
|
||||||
|
@Getter
|
||||||
|
static class DelayedEntry implements Delayed {
|
||||||
|
private final String value;
|
||||||
|
private final long time;
|
||||||
|
|
||||||
|
private DelayedEntry(String value, long time) {
|
||||||
|
this.time = time;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDelay(TimeUnit unit) {
|
||||||
|
long delta = time - System.currentTimeMillis();
|
||||||
|
return unit.convert(delta, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Delayed o) {
|
||||||
|
if (this.time < ((DelayedEntry) o).time) {
|
||||||
|
return -1;
|
||||||
|
} else if (this.time > ((DelayedEntry) o).time) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,95 @@
|
||||||
package cn.bunny.atomic;
|
package cn.bunny.atomic;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.*;
|
||||||
|
import org.openjdk.jmh.runner.Runner;
|
||||||
|
import org.openjdk.jmh.runner.RunnerException;
|
||||||
|
import org.openjdk.jmh.runner.options.Options;
|
||||||
|
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Measurement(iterations = 10)
|
||||||
|
@Warmup(iterations = 10)
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@State(Scope.Thread)
|
||||||
|
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||||
public class AtomicExample09 {
|
public class AtomicExample09 {
|
||||||
|
private final static String DATA = "TEST";
|
||||||
|
private final static Object LOCK = new Object();
|
||||||
|
private SynchronizedLinkedList synchronizedLinkedList;
|
||||||
|
private ConcurrentLinkedQueue<String> concurrentLinkedQueue;
|
||||||
|
|
||||||
|
// 如果使用不当反而会降低性能
|
||||||
|
public static void main(String[] args) throws RunnerException {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(AtomicExample09.class.getSimpleName())
|
||||||
|
.forks(1)
|
||||||
|
.build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Setup(Level.Iteration)
|
||||||
|
public void setUp() {
|
||||||
|
synchronizedLinkedList = new SynchronizedLinkedList();
|
||||||
|
concurrentLinkedQueue = new ConcurrentLinkedQueue<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 SynchronizedLinkedList
|
||||||
|
@Group("sync")
|
||||||
|
@Benchmark
|
||||||
|
@GroupThreads(5)
|
||||||
|
public void synchronizedListAdd() {
|
||||||
|
synchronizedLinkedList.addLast(DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Group("sync")
|
||||||
|
@Benchmark
|
||||||
|
@GroupThreads(5)
|
||||||
|
public String synchronizedListGet() {
|
||||||
|
return synchronizedLinkedList.removeFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 ConcurrentLinkedQueue
|
||||||
|
@Group("concurrent")
|
||||||
|
@Benchmark
|
||||||
|
@GroupThreads(5)
|
||||||
|
public void concurrentLinkedQueueAdd() {
|
||||||
|
concurrentLinkedQueue.offer(DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Group("concurrent")
|
||||||
|
@Benchmark
|
||||||
|
@GroupThreads(5)
|
||||||
|
public String concurrentLinkedQueueGet() {
|
||||||
|
return concurrentLinkedQueue.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SynchronizedLinkedList {
|
||||||
|
private final LinkedList<String> list = new LinkedList<>();
|
||||||
|
|
||||||
|
void addLast(String element) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
list.addLast(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String removeFirst() {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return list.removeLast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// 测试结果
|
||||||
|
// Benchmark Mode Cnt Score Error Units
|
||||||
|
// AtomicExample09.concurrent avgt 10 0.221 ± 0.649 us/op
|
||||||
|
// AtomicExample09.concurrent:concurrentLinkedQueueAdd avgt 10 0.407 ± 1.296 us/op
|
||||||
|
// AtomicExample09.concurrent:concurrentLinkedQueueGet avgt 10 0.034 ± 0.048 us/op
|
||||||
|
// AtomicExample09.sync avgt 10 0.240 ± 0.039 us/op
|
||||||
|
// AtomicExample09.sync:synchronizedListAdd avgt 10 0.232 ± 0.034 us/op
|
||||||
|
// AtomicExample09.sync:synchronizedListGet avgt 10 0.248 ± 0.044 us/op
|
|
@ -1,4 +0,0 @@
|
||||||
package cn.bunny.atomic;
|
|
||||||
|
|
||||||
public class AtomicExample10 {
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
package cn.bunny.atomic;
|
|
||||||
|
|
||||||
public class AtomicExample11 {
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
package cn.bunny.atomic;
|
|
||||||
|
|
||||||
public class AtomicExample12 {
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
package cn.bunny.atomic;
|
|
||||||
|
|
||||||
public class AtomicExample13 {
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
package cn.bunny.atomic;
|
|
||||||
|
|
||||||
public class AtomicExample14 {
|
|
||||||
}
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class StreamExample01 {
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
Stream<Integer> build = Stream.<Integer>builder()
|
||||||
|
.add(1)
|
||||||
|
.add(12)
|
||||||
|
.add(3)
|
||||||
|
.add(34)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Stream<Integer> integerStream = Stream.of(1, 2, 34, 5);
|
||||||
|
|
||||||
|
// 空Stream
|
||||||
|
Stream<Object> objectStream = Stream.empty();
|
||||||
|
|
||||||
|
// Stream.generate创建
|
||||||
|
Stream.generate(() -> ThreadLocalRandom.current().nextInt(10))
|
||||||
|
.limit(10)
|
||||||
|
.forEach(System.out::println);
|
||||||
|
|
||||||
|
// 不加限制会一直创建
|
||||||
|
Stream.iterate(100, seed -> seed + 1)
|
||||||
|
.limit(10)
|
||||||
|
.forEach(System.out::println);
|
||||||
|
|
||||||
|
// IntStream创建[1,10)
|
||||||
|
IntStream.range(1, 10)
|
||||||
|
.forEach(System.out::println);
|
||||||
|
|
||||||
|
// 创建闭区间[1,10]
|
||||||
|
IntStream.rangeClosed(1, 10)
|
||||||
|
.forEach(System.out::println);
|
||||||
|
|
||||||
|
// Arrays.asList创建
|
||||||
|
Arrays.asList("a", "b", "c", "d", "e", "f")
|
||||||
|
.forEach(System.out::println);
|
||||||
|
|
||||||
|
// 创建Stream<Map.Entry<String, String>>
|
||||||
|
Stream<Map.Entry<String, String>> stream = new HashMap<String, String>() {{
|
||||||
|
put("a", "b");
|
||||||
|
put("c", "d");
|
||||||
|
}}.entrySet().stream();
|
||||||
|
|
||||||
|
// Files中的Stream
|
||||||
|
Stream<String> lines = Files.lines(Paths.get("xxx.md"), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class StreamExample02 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Stream<Object> stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 去重操作
|
||||||
|
stream.distinct().forEach(System.out::println);
|
||||||
|
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 过滤器,满足值为2的筛选
|
||||||
|
stream.filter(x -> x.equals(2)).forEach(System.out::println);
|
||||||
|
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 选择序列个数为3
|
||||||
|
stream.limit(3).forEach(System.out::println);
|
||||||
|
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 映射,可以修改原本的类型
|
||||||
|
stream.map(Object::toString).forEach(System.out::println);
|
||||||
|
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 跳过前两个数
|
||||||
|
stream.skip(2).forEach(System.out::println);
|
||||||
|
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 不会使元素数据、类型产生改变
|
||||||
|
stream.peek(x -> ThreadLocalRandom.current().nextInt(100)).limit(10).forEach(System.out::println);
|
||||||
|
|
||||||
|
stream = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}}.stream();
|
||||||
|
|
||||||
|
// 从小到大排序
|
||||||
|
stream.sorted().forEach(System.out::println);
|
||||||
|
|
||||||
|
// 提供重载方法
|
||||||
|
// stream.sorted(Comparator.comparing(Object::toString)).forEach(System.out::println);
|
||||||
|
|
||||||
|
ArrayList<Integer> list = new ArrayList<>() {{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
add(3);
|
||||||
|
add(4);
|
||||||
|
}};
|
||||||
|
List<ArrayList<Integer>> arrayListList = List.of(list);
|
||||||
|
|
||||||
|
// 扁平化数组
|
||||||
|
arrayListList.stream().flatMap(Collection::stream).forEach(System.out::println);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class StreamExample03 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 需要满足所有元素都匹配条件
|
||||||
|
boolean allMatch = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.allMatch(i -> i > 4);
|
||||||
|
System.out.println(allMatch);// false
|
||||||
|
|
||||||
|
// 只要有一个元素满足匹配条件
|
||||||
|
boolean anyMatch = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.anyMatch(x -> x > 4);
|
||||||
|
System.out.println(anyMatch);// true
|
||||||
|
|
||||||
|
// 所有元素都不满足条件
|
||||||
|
boolean noneMatch = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.noneMatch(x -> x > 4);
|
||||||
|
System.out.println(noneMatch);// false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class StreamExample04 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
// 找到第一个数字
|
||||||
|
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(System.out::println);
|
||||||
|
|
||||||
|
// 获取任意一个数字
|
||||||
|
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.findAny()
|
||||||
|
.ifPresent(System.out::println);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class StreamExample05 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 计数
|
||||||
|
long count = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.count();
|
||||||
|
System.out.println(count);// 9
|
||||||
|
|
||||||
|
// 求和
|
||||||
|
long sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.mapToLong(Integer::longValue)
|
||||||
|
.sum();
|
||||||
|
System.out.println(sum);
|
||||||
|
|
||||||
|
// 查找最小值
|
||||||
|
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.min(Comparator.comparing(i -> i))
|
||||||
|
.ifPresent(System.out::println);
|
||||||
|
|
||||||
|
// 查找最大值
|
||||||
|
Optional<Integer> max = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||||
|
.max(Comparator.comparing(i -> i));
|
||||||
|
System.out.println(max.get());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class StreamExample06 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
|
||||||
|
|
||||||
|
// 使用 reduce 求和
|
||||||
|
Optional<Integer> sum = numbers.stream()
|
||||||
|
.reduce(Integer::sum);
|
||||||
|
sum.ifPresent(System.out::println); // 输出: 15
|
||||||
|
|
||||||
|
// 使用带初始值的 reduce
|
||||||
|
int sumWithIdentity = numbers.stream()
|
||||||
|
.reduce(0, Integer::sum);
|
||||||
|
System.out.println(sumWithIdentity); // 输出: 15
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class StreamExample07 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Product> products = Arrays.asList(
|
||||||
|
new Product("Apple", 1.20),
|
||||||
|
new Product("Banana", 0.80),
|
||||||
|
new Product("Orange", 1.00)
|
||||||
|
);
|
||||||
|
|
||||||
|
double totalCost = products.stream().mapToDouble(Product::getPrice).sum();
|
||||||
|
|
||||||
|
System.out.println("Total Cost: " + totalCost); // 输出: Total Cost: 3.0
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static class Product {
|
||||||
|
private final String name;
|
||||||
|
private final double price;
|
||||||
|
|
||||||
|
public Product(String name, double price) {
|
||||||
|
this.name = name;
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample08 {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 30),
|
||||||
|
new Person("David", 25)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 根据年龄将一组人分组
|
||||||
|
Map<Integer, List<Person>> groupedByAge = people.stream()
|
||||||
|
.collect(Collectors.groupingBy(Person::getAge));
|
||||||
|
System.out.println(groupedByAge);
|
||||||
|
|
||||||
|
// 自定义收集器:可以传递第二个参数来指定下游收集器。
|
||||||
|
Map<Integer, Long> groupedByAgeCount = people.stream()
|
||||||
|
.collect(Collectors.groupingBy(Person::getAge, Collectors.counting()));
|
||||||
|
System.out.println(groupedByAgeCount);
|
||||||
|
|
||||||
|
// 多级分组:可以嵌套使用 groupingBy 进行多级分组。
|
||||||
|
Map<Integer, Map<String, List<Person>>> groupedByAgeAndName = people.stream()
|
||||||
|
.collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getName)));
|
||||||
|
System.out.println(groupedByAgeAndName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample09 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// averagingLong
|
||||||
|
List<Long> numbers = Arrays.asList(1L, 2L, 3L, 4L, 5L);
|
||||||
|
double averagingLongNumbers = numbers.stream()
|
||||||
|
.collect(Collectors.averagingLong(Long::longValue));
|
||||||
|
System.out.println("Average: " + averagingLongNumbers);
|
||||||
|
|
||||||
|
// averagingDouble
|
||||||
|
List<Double> averagingDoubleNumbers = Arrays.asList(1.5, 2.5, 3.5, 4.5, 5.5);
|
||||||
|
double averagingDouble = averagingDoubleNumbers.stream()
|
||||||
|
.collect(Collectors.averagingDouble(Double::doubleValue));
|
||||||
|
System.out.println("Average: " + averagingDouble);
|
||||||
|
|
||||||
|
// averagingInt
|
||||||
|
List<Integer> averagingIntNumbers = Arrays.asList(1, 2, 3, 4, 5);
|
||||||
|
double averagingInt = averagingIntNumbers.stream()
|
||||||
|
.collect(Collectors.averagingInt(Integer::intValue));
|
||||||
|
System.out.println("Average: " + averagingInt);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample10 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.collectingAndThen 计算平均年龄并转换为整数
|
||||||
|
int averageAge = people.stream()
|
||||||
|
.collect(Collectors.collectingAndThen(
|
||||||
|
Collectors.averagingInt(Person::getAge),// 先计算平均年龄
|
||||||
|
Double::intValue // 之后将结果转换为整数
|
||||||
|
));
|
||||||
|
|
||||||
|
System.out.println("Average Age: " + averageAge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample11 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.counting 统计人数
|
||||||
|
long count = people.stream()
|
||||||
|
.collect(Collectors.counting());
|
||||||
|
|
||||||
|
System.out.println("Total number of people: " + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample12 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35),
|
||||||
|
new Person("David", 40)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.mapping 和 Collectors.toSet 只收集大于 30 岁的人的年龄
|
||||||
|
Set<Integer> agesAbove30 = people.stream()
|
||||||
|
.filter(person -> person.getAge() > 30)
|
||||||
|
.collect(Collectors.mapping(Person::getAge, Collectors.toSet()));
|
||||||
|
|
||||||
|
System.out.println("Ages above 30: " + agesAbove30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample13 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice"),
|
||||||
|
new Person("Bob"),
|
||||||
|
new Person("Charlie")
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.joining 连接名字,添加前缀和后缀
|
||||||
|
String result = people.stream()
|
||||||
|
.map(Person::getName) // 提取名字
|
||||||
|
.collect(Collectors.joining(", ", "[", "]")); // 使用逗号和空格作为分隔符,添加前缀和后缀
|
||||||
|
|
||||||
|
System.out.println("Names: " + result);// Names: [Alice, Bob, Charlie]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Person(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample14 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summingInt 计算年龄总和
|
||||||
|
int totalAge = people.stream()
|
||||||
|
.collect(Collectors.summingInt(Person::getAge));
|
||||||
|
|
||||||
|
System.out.println("Total Age: " + totalAge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + age + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample15 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Product> products = Arrays.asList(
|
||||||
|
new Product("Laptop", 999.99),
|
||||||
|
new Product("Smartphone", 499.99),
|
||||||
|
new Product("Tablet", 299.99)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summingDouble 计算价格总和
|
||||||
|
double totalPrice = products.stream()
|
||||||
|
.collect(Collectors.summingDouble(Product::getPrice));
|
||||||
|
|
||||||
|
System.out.println("Total Price: " + totalPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static
|
||||||
|
class Product {
|
||||||
|
private final String name;
|
||||||
|
@Getter
|
||||||
|
private final double price;
|
||||||
|
|
||||||
|
public Product(String name, double price) {
|
||||||
|
this.name = name;
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample16 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Transaction> transactions = Arrays.asList(
|
||||||
|
new Transaction(1000L),
|
||||||
|
new Transaction(2500L),
|
||||||
|
new Transaction(1500L)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summingLong 计算总金额
|
||||||
|
long totalAmount = transactions.stream()
|
||||||
|
.collect(Collectors.summingLong(Transaction::getAmount));
|
||||||
|
|
||||||
|
System.out.println("Total Amount: " + totalAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Transaction {
|
||||||
|
private final long amount;
|
||||||
|
|
||||||
|
public Transaction(long l) {
|
||||||
|
this.amount = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample17 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.minBy 找到年龄最小的人
|
||||||
|
Optional<Person> youngest = people.stream()
|
||||||
|
.collect(Collectors.minBy(Comparator.comparingInt(Person::getAge)));
|
||||||
|
|
||||||
|
youngest.ifPresent(person ->
|
||||||
|
System.out.println("Youngest Person: " + person.getName() + ", Age: " + person.getAge()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample18 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.maxBy 找到年龄最大的人
|
||||||
|
Optional<Person> oldest = people.stream()
|
||||||
|
.collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge)));
|
||||||
|
|
||||||
|
oldest.ifPresent(person ->
|
||||||
|
System.out.println("Oldest Person: " + person.getName() + ", Age: " + person.getAge()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.IntSummaryStatistics;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample19 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 25),
|
||||||
|
new Person("Charlie", 35)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summarizingInt 统计年龄信息
|
||||||
|
IntSummaryStatistics ageStats = people.stream()
|
||||||
|
.collect(Collectors.summarizingInt(Person::getAge));
|
||||||
|
|
||||||
|
System.out.println("Count: " + ageStats.getCount());
|
||||||
|
System.out.println("Sum: " + ageStats.getSum());
|
||||||
|
System.out.println("Min: " + ageStats.getMin());
|
||||||
|
System.out.println("Max: " + ageStats.getMax());
|
||||||
|
System.out.println("Average: " + ageStats.getAverage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.LongSummaryStatistics;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample20 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Transaction> transactions = Arrays.asList(
|
||||||
|
new Transaction(1000L),
|
||||||
|
new Transaction(2500L),
|
||||||
|
new Transaction(1500L)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summarizingLong 统计金额信息
|
||||||
|
LongSummaryStatistics amountStats = transactions.stream()
|
||||||
|
.collect(Collectors.summarizingLong(Transaction::getAmount));
|
||||||
|
|
||||||
|
System.out.println("Count: " + amountStats.getCount());
|
||||||
|
System.out.println("Sum: " + amountStats.getSum());
|
||||||
|
System.out.println("Min: " + amountStats.getMin());
|
||||||
|
System.out.println("Max: " + amountStats.getMax());
|
||||||
|
System.out.println("Average: " + amountStats.getAverage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Transaction {
|
||||||
|
private final long amount;
|
||||||
|
|
||||||
|
public Transaction(long amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.DoubleSummaryStatistics;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample21 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Product> products = Arrays.asList(
|
||||||
|
new Product("Laptop", 1200.50),
|
||||||
|
new Product("Phone", 800.75),
|
||||||
|
new Product("Tablet", 300.00)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.summarizingDouble 统计价格信息
|
||||||
|
DoubleSummaryStatistics priceStats = products.stream()
|
||||||
|
.collect(Collectors.summarizingDouble(Product::getPrice));
|
||||||
|
|
||||||
|
System.out.println("Count: " + priceStats.getCount());
|
||||||
|
System.out.println("Sum: " + priceStats.getSum());
|
||||||
|
System.out.println("Min: " + priceStats.getMin());
|
||||||
|
System.out.println("Max: " + priceStats.getMax());
|
||||||
|
System.out.println("Average: " + priceStats.getAverage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static
|
||||||
|
class Product {
|
||||||
|
private final String name;
|
||||||
|
private final double price;
|
||||||
|
|
||||||
|
public Product(String name, double price) {
|
||||||
|
this.name = name;
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class StreamExample22 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Person> people = Arrays.asList(
|
||||||
|
new Person("Alice", 30),
|
||||||
|
new Person("Bob", 17),
|
||||||
|
new Person("Charlie", 25),
|
||||||
|
new Person("David", 15)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Collectors.partitioningBy 按年龄分组
|
||||||
|
Map<Boolean, List<Person>> partitionedByAge = people.stream()
|
||||||
|
.collect(Collectors.partitioningBy(person -> person.getAge() >= 18));
|
||||||
|
|
||||||
|
// 输出结果
|
||||||
|
System.out.println("成年人:");
|
||||||
|
partitionedByAge.get(true).forEach(person -> System.out.println(person.getName()));
|
||||||
|
|
||||||
|
System.out.println("未成年人:");
|
||||||
|
partitionedByAge.get(false).forEach(person -> System.out.println(person.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
static class Person {
|
||||||
|
private final String name;
|
||||||
|
private final int age;
|
||||||
|
|
||||||
|
public Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package cn.bunny.stream;
|
||||||
|
|
||||||
|
public class StreamExample23 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue