feat: Stream 结束

This commit is contained in:
Bunny 2025-01-21 13:44:35 +08:00
parent ba47472c5c
commit 71e05346af
32 changed files with 2194 additions and 21 deletions

967
README/Java Stream详解.md Normal file
View File

@ -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个参数keyvalue
- 3个参数keyvalue处理key冲突问题
- 4个参数keyvalue处理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;
}
}
}
```

View File

@ -70,3 +70,198 @@ LinkedBlockingQueue<Integer> integers1 = new LinkedBlockingQueue<>();
boolean b1 = integers1.remainingCapacity() == Integer.MAX_VALUE;
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>
> ```

View File

@ -1,4 +1,65 @@
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 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;
}
}
}

View File

@ -1,4 +1,95 @@
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 {
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

View File

@ -1,4 +0,0 @@
package cn.bunny.atomic;
public class AtomicExample10 {
}

View File

@ -1,4 +0,0 @@
package cn.bunny.atomic;
public class AtomicExample11 {
}

View File

@ -1,4 +0,0 @@
package cn.bunny.atomic;
public class AtomicExample12 {
}

View File

@ -1,4 +0,0 @@
package cn.bunny.atomic;
public class AtomicExample13 {
}

View File

@ -1,4 +0,0 @@
package cn.bunny.atomic;
public class AtomicExample14 {
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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
}
}

View File

@ -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;
}
}
}

View File

@ -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 + ")";
}
}
}

View File

@ -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);
}
}

View File

@ -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 + ")";
}
}
}

View File

@ -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 + ")";
}
}
}

View File

@ -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 + ")";
}
}
}

View File

@ -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;
}
}
}

View File

@ -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 + ")";
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,7 @@
package cn.bunny.stream;
public class StreamExample23 {
public static void main(String[] args) {
}
}