From 71e05346af28a58f9065245cab0886041b6eb4a7 Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Tue, 21 Jan 2025 13:44:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Stream=20=E7=BB=93=E6=9D=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README/Java Stream详解.md | 967 ++++++++++++++++++ README/Java并发容器使用.md | 197 +++- .../java/cn/bunny/atomic/AtomicExample08.java | 61 ++ .../java/cn/bunny/atomic/AtomicExample09.java | 91 ++ .../java/cn/bunny/atomic/AtomicExample10.java | 4 - .../java/cn/bunny/atomic/AtomicExample11.java | 4 - .../java/cn/bunny/atomic/AtomicExample12.java | 4 - .../java/cn/bunny/atomic/AtomicExample13.java | 4 - .../java/cn/bunny/atomic/AtomicExample14.java | 4 - .../java/cn/bunny/stream/StreamExample01.java | 59 ++ .../java/cn/bunny/stream/StreamExample02.java | 111 ++ .../java/cn/bunny/stream/StreamExample03.java | 22 + .../java/cn/bunny/stream/StreamExample04.java | 18 + .../java/cn/bunny/stream/StreamExample05.java | 30 + .../java/cn/bunny/stream/StreamExample06.java | 21 + .../java/cn/bunny/stream/StreamExample07.java | 31 + .../java/cn/bunny/stream/StreamExample08.java | 51 + .../java/cn/bunny/stream/StreamExample09.java | 27 + .../java/cn/bunny/stream/StreamExample10.java | 42 + .../java/cn/bunny/stream/StreamExample11.java | 39 + .../java/cn/bunny/stream/StreamExample12.java | 42 + .../java/cn/bunny/stream/StreamExample13.java | 38 + .../java/cn/bunny/stream/StreamExample14.java | 39 + .../java/cn/bunny/stream/StreamExample15.java | 36 + .../java/cn/bunny/stream/StreamExample16.java | 34 + .../java/cn/bunny/stream/StreamExample17.java | 37 + .../java/cn/bunny/stream/StreamExample18.java | 37 + .../java/cn/bunny/stream/StreamExample19.java | 39 + .../java/cn/bunny/stream/StreamExample20.java | 38 + .../java/cn/bunny/stream/StreamExample21.java | 40 + .../java/cn/bunny/stream/StreamExample22.java | 41 + .../java/cn/bunny/stream/StreamExample23.java | 7 + 32 files changed, 2194 insertions(+), 21 deletions(-) create mode 100644 README/Java Stream详解.md delete mode 100644 multithreading1/src/main/java/cn/bunny/atomic/AtomicExample10.java delete mode 100644 multithreading1/src/main/java/cn/bunny/atomic/AtomicExample11.java delete mode 100644 multithreading1/src/main/java/cn/bunny/atomic/AtomicExample12.java delete mode 100644 multithreading1/src/main/java/cn/bunny/atomic/AtomicExample13.java delete mode 100644 multithreading1/src/main/java/cn/bunny/atomic/AtomicExample14.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample01.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample02.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample03.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample04.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample05.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample06.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample07.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample08.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample09.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample10.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample11.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample12.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample13.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample14.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample15.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample16.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample17.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample18.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample19.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample20.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample21.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample22.java create mode 100644 multithreading1/src/main/java/cn/bunny/stream/StreamExample23.java diff --git a/README/Java Stream详解.md b/README/Java Stream详解.md new file mode 100644 index 0000000..56fe0ee --- /dev/null +++ b/README/Java Stream详解.md @@ -0,0 +1,967 @@ +# Java Stream详解 + +## 创建Stream + +### Stream.builder()创建 + +```java +Stream build = Stream.builder() + .add(1) + .add(12) + .add(3) + .add(34) + .build(); +``` + +### Stream.of创建 + +```java +Stream integerStream = Stream.of(1, 2, 34, 5); +``` + +### 空Stream创建 + +```java +Stream objectStream = Stream.empty(); +``` + +### Stream.generate创建 + +如果不加限制运行时会一直创建像死循环一样 + +```java +// Stream.generate创建 +Stream 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> + +```java +// 创建Stream> +Stream> stream = new HashMap() {{ + put("a", "b"); + put("c", "d"); +}}.entrySet().stream(); +``` + +### Files中的Stream + +```java +// Files中的Stream +Stream lines = Files.lines(Paths.get("xxx.md"), StandardCharsets.UTF_8); +``` + +## Stream的操作 + +### distinct操作 + +```java +Stream 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 list = new ArrayList<>() {{ + add(1); + add(2); + add(2); + add(3); + add(3); + add(4); +}}; +List> 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 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 names = Arrays.asList("Alice", "Bob", "Charlie"); +List upperCaseNames = names.stream() + .map(String::toUpperCase) + .collect(Collectors.toList()); +``` + +### toSet + +将元素输出到 Set + +```java +List names = Arrays.asList("Alice", "Bob", "Charlie"); +Set uniqueNames = names.stream() + .collect(Collectors.toSet()); +``` + +### toMap + +将元素输出到 Map + +- 2个参数:key,value +- 3个参数:key,value,处理key冲突问题 +- 4个参数:key,value,处理key冲突问题,转换map类型 + +```java +List names = Arrays.asList("Alice", "Bob", "Charlie"); +Map nameLengthMap = names.stream() + .collect(Collectors.toMap(name -> name, String::length)); +``` + +### reduce + +语法 + +```java +Optional reduce(BinaryOperator accumulator) +Optional reduce(T identity, BinaryOperator accumulator) +``` + +使用 + +```java +List numbers = Arrays.asList(1, 2, 3, 4, 5); + +// 使用 reduce 求和 +Optional 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 summingDouble(ToDoubleFunction mapper) +``` + +使用 + +```java +public class StreamExample07 { + public static void main(String[] args) { + List 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 people = Arrays.asList( + new Person("Alice", 30), + new Person("Bob", 25), + new Person("Charlie", 30), + new Person("David", 25) + ); + + // 根据年龄将一组人分组 + Map> groupedByAge = people.stream() + .collect(Collectors.groupingBy(Person::getAge)); + + // 自定义收集器:可以传递第二个参数来指定下游收集器。 + Map groupedByAgeCount = people.stream() + .collect(Collectors.groupingBy(Person::getAge, Collectors.counting())); + + // 多级分组:可以嵌套使用 groupingBy 进行多级分组。 + Map>> 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 numbers = Arrays.asList(1L, 2L, 3L, 4L, 5L); +double averagingLongNumbers = numbers.stream() + .collect(Collectors.averagingLong(Long::longValue)); +System.out.println("Average: " + averagingLongNumbers); + +// averagingDouble +List 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 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 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 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 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 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 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 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 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 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 people = Arrays.asList( + new Person("Alice", 30), + new Person("Bob", 25), + new Person("Charlie", 35) + ); + + // 使用 Collectors.minBy 找到年龄最小的人 + Optional 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 people = Arrays.asList( + new Person("Alice", 30), + new Person("Bob", 25), + new Person("Charlie", 35) + ); + + // 使用 Collectors.maxBy 找到年龄最大的人 + Optional 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 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 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 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 people = Arrays.asList( + new Person("Alice", 30), + new Person("Bob", 17), + new Person("Charlie", 25), + new Person("David", 15) + ); + + // 使用 Collectors.partitioningBy 按年龄分组 + Map> 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; + } + } +} +``` \ No newline at end of file diff --git a/README/Java并发容器使用.md b/README/Java并发容器使用.md index 727fcc2..8d84b76 100644 --- a/README/Java并发容器使用.md +++ b/README/Java并发容器使用.md @@ -69,4 +69,199 @@ System.out.println(b); LinkedBlockingQueue integers1 = new LinkedBlockingQueue<>(); boolean b1 = integers1.remainingCapacity() == Integer.MAX_VALUE; System.out.println(b1); -``` \ No newline at end of file +``` + +## InterruptedException使用 + +```java +public class AtomicExample08 { + public static void main(String[] args) throws InterruptedException { + DelayQueue 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 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 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 +> +> +> org.projectlombok +> lombok +> 1.18.36 +> +> +> +> org.slf4j +> slf4j-api +> 2.0.16 +> +> +> org.slf4j +> slf4j-simple +> 2.0.16 +> +> +> +> org.openjdk.jmh +> jmh-core +> 1.19 +> +> +> org.openjdk.jmh +> jmh-generator-annprocess +> 1.19 +> +> +> ``` \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample08.java b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample08.java index 55c0668..f67b748 100644 --- a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample08.java +++ b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample08.java @@ -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 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; + } + } } diff --git a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample09.java b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample09.java index baf43f0..abf4ce3 100644 --- a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample09.java +++ b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample09.java @@ -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 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 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 \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample10.java b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample10.java deleted file mode 100644 index 17036e8..0000000 --- a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample10.java +++ /dev/null @@ -1,4 +0,0 @@ -package cn.bunny.atomic; - -public class AtomicExample10 { -} diff --git a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample11.java b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample11.java deleted file mode 100644 index 13e2347..0000000 --- a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample11.java +++ /dev/null @@ -1,4 +0,0 @@ -package cn.bunny.atomic; - -public class AtomicExample11 { -} diff --git a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample12.java b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample12.java deleted file mode 100644 index 400d627..0000000 --- a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample12.java +++ /dev/null @@ -1,4 +0,0 @@ -package cn.bunny.atomic; - -public class AtomicExample12 { -} diff --git a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample13.java b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample13.java deleted file mode 100644 index 38ec430..0000000 --- a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample13.java +++ /dev/null @@ -1,4 +0,0 @@ -package cn.bunny.atomic; - -public class AtomicExample13 { -} diff --git a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample14.java b/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample14.java deleted file mode 100644 index 27d4485..0000000 --- a/multithreading1/src/main/java/cn/bunny/atomic/AtomicExample14.java +++ /dev/null @@ -1,4 +0,0 @@ -package cn.bunny.atomic; - -public class AtomicExample14 { -} diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample01.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample01.java new file mode 100644 index 0000000..cfa5cec --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample01.java @@ -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 build = Stream.builder() + .add(1) + .add(12) + .add(3) + .add(34) + .build(); + + Stream integerStream = Stream.of(1, 2, 34, 5); + + // 空Stream + Stream 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> + Stream> stream = new HashMap() {{ + put("a", "b"); + put("c", "d"); + }}.entrySet().stream(); + + // Files中的Stream + Stream lines = Files.lines(Paths.get("xxx.md"), StandardCharsets.UTF_8); + } +} diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample02.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample02.java new file mode 100644 index 0000000..8166816 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample02.java @@ -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 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 list = new ArrayList<>() {{ + add(1); + add(2); + add(2); + add(3); + add(3); + add(4); + }}; + List> arrayListList = List.of(list); + + // 扁平化数组 + arrayListList.stream().flatMap(Collection::stream).forEach(System.out::println); + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample03.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample03.java new file mode 100644 index 0000000..df9c8bf --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample03.java @@ -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 + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample04.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample04.java new file mode 100644 index 0000000..6d294d4 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample04.java @@ -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); + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample05.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample05.java new file mode 100644 index 0000000..a81de2e --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample05.java @@ -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 max = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9) + .max(Comparator.comparing(i -> i)); + System.out.println(max.get()); + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample06.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample06.java new file mode 100644 index 0000000..9166f93 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample06.java @@ -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 numbers = Arrays.asList(1, 2, 3, 4, 5); + + // 使用 reduce 求和 + Optional 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 + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample07.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample07.java new file mode 100644 index 0000000..ca18eea --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample07.java @@ -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 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; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample08.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample08.java new file mode 100644 index 0000000..0e6f772 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample08.java @@ -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 people = Arrays.asList( + new Person("Alice", 30), + new Person("Bob", 25), + new Person("Charlie", 30), + new Person("David", 25) + ); + + // 根据年龄将一组人分组 + Map> groupedByAge = people.stream() + .collect(Collectors.groupingBy(Person::getAge)); + System.out.println(groupedByAge); + + // 自定义收集器:可以传递第二个参数来指定下游收集器。 + Map groupedByAgeCount = people.stream() + .collect(Collectors.groupingBy(Person::getAge, Collectors.counting())); + System.out.println(groupedByAgeCount); + + // 多级分组:可以嵌套使用 groupingBy 进行多级分组。 + Map>> 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 + ")"; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample09.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample09.java new file mode 100644 index 0000000..08464f5 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample09.java @@ -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 numbers = Arrays.asList(1L, 2L, 3L, 4L, 5L); + double averagingLongNumbers = numbers.stream() + .collect(Collectors.averagingLong(Long::longValue)); + System.out.println("Average: " + averagingLongNumbers); + + // averagingDouble + List 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 averagingIntNumbers = Arrays.asList(1, 2, 3, 4, 5); + double averagingInt = averagingIntNumbers.stream() + .collect(Collectors.averagingInt(Integer::intValue)); + System.out.println("Average: " + averagingInt); + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample10.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample10.java new file mode 100644 index 0000000..13f48b2 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample10.java @@ -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 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 + ")"; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample11.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample11.java new file mode 100644 index 0000000..460cb91 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample11.java @@ -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 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 + ")"; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample12.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample12.java new file mode 100644 index 0000000..5de9623 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample12.java @@ -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 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 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 + ")"; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample13.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample13.java new file mode 100644 index 0000000..6025985 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample13.java @@ -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 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; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample14.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample14.java new file mode 100644 index 0000000..d29a8f9 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample14.java @@ -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 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 + ")"; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample15.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample15.java new file mode 100644 index 0000000..a71ef13 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample15.java @@ -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 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; + } + } +} diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample16.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample16.java new file mode 100644 index 0000000..8cd162f --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample16.java @@ -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 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; + } + } +} + + diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample17.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample17.java new file mode 100644 index 0000000..81369bb --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample17.java @@ -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 people = Arrays.asList( + new Person("Alice", 30), + new Person("Bob", 25), + new Person("Charlie", 35) + ); + + // 使用 Collectors.minBy 找到年龄最小的人 + Optional 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; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample18.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample18.java new file mode 100644 index 0000000..e9cec93 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample18.java @@ -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 people = Arrays.asList( + new Person("Alice", 30), + new Person("Bob", 25), + new Person("Charlie", 35) + ); + + // 使用 Collectors.maxBy 找到年龄最大的人 + Optional 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; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample19.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample19.java new file mode 100644 index 0000000..75adaa4 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample19.java @@ -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 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; + } + } +} diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample20.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample20.java new file mode 100644 index 0000000..fd8fb65 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample20.java @@ -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 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; + } + } +} \ No newline at end of file diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample21.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample21.java new file mode 100644 index 0000000..d34f271 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample21.java @@ -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 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; + } + } +} diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample22.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample22.java new file mode 100644 index 0000000..5c61406 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample22.java @@ -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 people = Arrays.asList( + new Person("Alice", 30), + new Person("Bob", 17), + new Person("Charlie", 25), + new Person("David", 15) + ); + + // 使用 Collectors.partitioningBy 按年龄分组 + Map> 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; + } + } +} diff --git a/multithreading1/src/main/java/cn/bunny/stream/StreamExample23.java b/multithreading1/src/main/java/cn/bunny/stream/StreamExample23.java new file mode 100644 index 0000000..21b1f55 --- /dev/null +++ b/multithreading1/src/main/java/cn/bunny/stream/StreamExample23.java @@ -0,0 +1,7 @@ +package cn.bunny.stream; + +public class StreamExample23 { + public static void main(String[] args) { + + } +} \ No newline at end of file