Java函数式编程(中)

article/2025/6/29 10:13:45

三、Stream API

(1)创建操作

构建
Arrays.stream(数组)根据数组构建
Collection.stream()根据集合构建
Stream.of(对象1, 对象2, ...)根据对象构建
生成
IntStream.range(a, b)根据范围生成(含a 不含b)
IntStream.rangeClosed(a, b)根据范围生成(含a 也含b)
IntStream.iterate(s, p -> c)s初始值,p前值,c当前值
IntStream.generate(() -> c)c当期值
合并
Stream.concat(流1, 流2)合并两个流

(2)中间操作

截取
stream.skip(n)舍弃n个,保留剩余
stream.limit(n)从当前保留n个
stream.dropWhile(x -> boolean)舍弃,直到不满足条件,保留剩余
stream.takewhile(x -> boolean)保留,直到不满足条件,舍弃剩余
过滤
stream.filter(x -> boolean)满足条件的保留
转换
stream.map(x -> y)将x转换为y
stream.flatMap(x -> substream)将x转换为substream
stream.mapMulti((x, consumer) -> void)consumer消费的x会进入结果
stream.mapToInt(x -> int)将x转换为int
stream.mapToLong(x -> long)将x转换为long
stream.mapToDouble(x -> double)将x转换为double
排序与去重
stream.distinct()去重
stream.sort((a, b) -> int)a与b比较,返回负 a小,返回零相等,返回正 b小

(3)终结操作

查找
stream.findFirst()找到第一个,返回Optional
stream.findAny()随便找一个,返回Optional
判断
stream.anyMatch(x -> boolean)随便一个满足条件,返回true
stream.allMatch(x -> boolean)所有都满足条件,才返回true
stream.noneMatch(x -> boolean)所有都不满足条件,才返回true
消费
stream.forEach(x -> void)消费
stream.forEachOrdered(x -> void)按序消费
化简
stream.reduce(init, (p, x) -> r)init初始值,用上次结果p和当前元素x生成本次结果r
stream.reduce(init, (p, x) -> r, (r1, r2) -> r)最后是表示结果之间进行合并
stream.reduce((p, x) -> r)用第一个值作为初始值,返回Optional
stream.min((a, b) -> int)求最小值
stream.max((a, b) -> int)求最大值
stream.count()求个数
收集
stream.toArray()收集为数组
stream.toArray(size -> new A[size])收集为数组
stream.collect(() -> c, (c, x) -> void, (c1, c2) -> c)收集到容器:首先创建容器c,其次将x放入c,最后合并所有容器

(4)调试

调试
stream.peek(x -> void)调试

(5)收集器

收集器
joinint(delimiter)拼接字符串,delimiter分隔符
toList()用ArrayList收集
toSet()用HashSet收集
toMap(x -> k, x -> v)从x提取出k, v
toUnmodifiableList()用不可变List收集
toUnmodifiableSet()用不可变Set收集
toUnmodifiableMap(x -> k, x -> v)用不可变Map收集
partitioningBy(x -> boolean, dc)按条件分区,用下游收集器dc收集
groupingBy(x -> k, dc)从x提取出k,用下游收集器dc收集
mapping(x -> y, dc)将x转换为y,用下游收集器dc收集
flatMapping(x -> substream, dc)将x转换为substream,用下游收集器dc收集
filtering(x -> boolean, dc)过滤后,用下游收集器dc收集
counting()求个数
minBy((a, b) -> int)求最小
maxBy((a, b) -> int)求最大
summingInt(x -> int)转int后求和
averagingInt(x -> int)转int后求平均
reducing(init, (p, x) -> r)init初始值,用上次结果p和当前元素x生成本次结果r

(6)int流

int流
intstream.mapToObj(int -> obj)转换为obj流
intstream.boxed()转换为Integer流
instream.sum()求和
intstream.min()求最小值,返回Optional
intstream.max()求最大值,返回Optional
intstream.average()求平均值,返回Optional
intstream.summaryStatistics()综合count sum min max average

1. 过滤 - filter

需求:找到所有的浆果

关键:Predicate

实现代码:

package com.itheima.day3.stream;import java.util.stream.Stream;public class C01FilterTest {public static void main(String[] args) {Stream.of(new Fruit("草莓", "Strawberry", "浆果", "红色"),new Fruit("桑葚", "Mulberry", "浆果", "紫色"),new Fruit("杨梅", "Waxberry", "浆果", "红色"),new Fruit("核桃", "Walnut", "坚果", "棕色"),new Fruit("花生", "Peanut", "坚果", "棕色"),new Fruit("蓝莓", "Blueberry", "浆果", "蓝色"))
//                .filter(f->f.category().equals("浆果") && f.color().equals("蓝色")).filter(f->f.category().equals("浆果")).filter(f->f.color().equals("蓝色")).forEach(System.out::println);}record Fruit(String cname, String name, String category, String color) {}
}

2. 映射 - map

需求:把所有果实打成酱

实现:Function

实现代码:

package com.itheima.day3.stream;import java.util.stream.Stream;public class C02MapTest {public static void main(String[] args) {Stream.of(new Fruit("草莓", "Strawberry", "浆果", "红色"),new Fruit("桑葚", "Mulberry", "浆果", "紫色"),new Fruit("杨梅", "Waxberry", "浆果", "红色"),new Fruit("核桃", "Walnut", "坚果", "棕色"),new Fruit("草莓", "Peanut", "坚果", "棕色"),new Fruit("蓝莓", "Blueberry", "浆果", "蓝色")).map(f->f.cname()+"酱").forEach(System.out::println);}record Fruit(String cname, String name, String category, String color) {}
}

3. 降维(扁平化)- flatMap

需求:二维数据 变成 一维数据

关键:Function

实现代码:

package com.itheima.day3.stream;import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;public class C03FlatMapTest {public static void main(String[] args) {Stream.of(List.of(new Fruit("草莓", "Strawberry", "浆果", "红色"),new Fruit("桑葚", "Mulberry", "浆果", "紫色"),new Fruit("杨梅", "Waxberry", "浆果", "红色"),new Fruit("蓝莓", "Blueberry", "浆果", "蓝色")),List.of(new Fruit("核桃", "Walnut", "坚果", "棕色"),new Fruit("草莓", "Peanut", "坚果", "棕色")))
//                .flatMap(list -> list.stream()).flatMap(Collection::stream).forEach(System.out::println);Integer[][] array2D = {{1, 2, 3},{4, 5, 6},{7, 8, 9},};Arrays.stream(array2D)
//                .flatMap(array -> Arrays.stream(array)).flatMap(Arrays::stream).forEach(System.out::println);}record Fruit(String cname, String name, String category, String color) {}}
  • 降维前:

  • 降维后:

4. 构建 

已有数据 构建出 Stream流

示例代码:

package com.itheima.day3.stream;import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;public class C04BuildTest {public static void main(String[] args) {// 1. 从集合构建Set.of(1, 2, 3).stream().forEach(System.out::println);List.of(1, 2, 3).stream().forEach(System.out::println);Map.of("a", 1, "b", 2).entrySet().stream().forEach(System.out::println);// 2. 从数组构建int[] array = {1, 2, 3};Arrays.stream(array).forEach(System.out::println);// 3. 从对象构建Stream.of(1, 2, 3, 4, 5).forEach(System.out::println);}
}

5. 拼接 - concat

将两个流合并成一个

Stream.concat(流1, 流2)

示例代码:

package com.itheima.day3.stream;import java.util.stream.Stream;public class C05ConcatSplitTest {public static void main(String[] args) {// 1. 合并Stream<Integer> s1 = Stream.of(1, 2, 3);Stream<Integer> s2 = Stream.of(4, 5, 1, 2);Stream<Integer> concat = Stream.concat(s1, s2);concat.forEach(System.out::println);}
}

6. 截取 - skip、limit、takeWhile、dropWhile

  • 截取 - 直接给出截取位置
    • skip(long n)            跳过 n 个数据,保留剩下的
    • limit(long n)           保留 n 个数据,剩下的不要
  • 截取 - 根据条件确定截取位置
    • takeWhile(Predicate p)      条件成立保留, 一旦条件不成立,剩下的不要
    • dropWhile(Predicate p)      条件成立舍弃, 一旦条件不成立,剩下的保留

示例代码:

package com.itheima.day3.stream;import java.util.stream.Stream;public class C05ConcatSplitTest {public static void main(String[] args) {// 1. 合并Stream<Integer> s1 = Stream.of(1, 2, 3);Stream<Integer> s2 = Stream.of(4, 5, 1, 2);Stream<Integer> concat = Stream.concat(s1, s2);  // 1 2 3 4 5 1 2/*2. 截取 - 直接给出截取位置skip(long n)            跳过 n 个数据,保留剩下的limit(long n)           保留 n 个数据,剩下的不要*/concat.skip(2).forEach(System.out::print);  // 3 4 5 1 2concat.limit(2).forEach(System.out::print);  // 1 2concat.skip(2).limit(2).forEach(System.out::print);  // 3 4/*3. 截取 - 根据条件确定截取位置takeWhile(Predicate p)      条件成立保留, 一旦条件不成立,剩下的不要dropWhile(Predicate p)      条件成立舍弃, 一旦条件不成立,剩下的保留*/concat.takeWhile(x -> x < 3).forEach(System.out::print);  // 1 2concat.dropWhile(x -> x < 3).forEach(System.out::print);  // 3 4 5 1 2}
}

7. 生成 - range、iterate、generate

不用现有数据 生成 Stream 对象

示例代码:

package com.itheima.day3.stream;import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;public class C06GenerateTest {public static void main(String[] args) {// 1. IntStream.rangeIntStream.range(1, 10).forEach(System.out::println);  // 含头不含尾 [)IntStream.rangeClosed(1, 9).forEach(System.out::println);  // 含头也含尾 []// 2. IntStream.iterate  生成 1 3 5 7 9 ... 奇数序列    可以根据上一个元素值来生成当前元素IntStream.iterate(1, x -> x + 2).limit(10).forEach(System.out::println);  // 前10个奇数IntStream.iterate(1, x -> x <= 9, x -> x + 2).forEach(System.out::println);  // 10以内的奇数// 3. IntStream.generate  生成5个0~100内的随机整数(包含0,不包含100 -> [0, 100) )IntStream.generate(()-> ThreadLocalRandom.current().nextInt(100)).limit(5).forEach(System.out::println);ThreadLocalRandom.current().ints(5, 0, 100).forEach(System.out::println);}
}

8. 查找与判断 - findAny、findFirst、anyMatch、allMatch、noneMatch

查找

  • filter(Predict p).findAny()
  • filter(Predict p).findFirst()

判断

  • anyMatch(Predict p)
  • allMatch(Predict p)
  • noneMatch(Predict p)

示例1:查找

package com.itheima.day3.stream;import java.util.stream.IntStream;public class C07FindTest {public static void main(String[] args) {// 1. findFirst 找到第一个元素IntStream stream = IntStream.of(1, 2, 3, 4, 5, 6);// 查找第一个偶数(找不到则返回-1)System.out.println(stream.filter(x -> (x & 1) == 0).findFirst().orElse(-1));  // OptionalInt[2]// 查找第一个偶数,找到才打印,找不到不打印stream.filter(x -> (x & 1) == 0).findFirst().ifPresent(System.out::println);  // 2// 2. findAny 找到任意一个偶数元素stream.filter(x -> (x & 1) == 0).findAny().ifPresent(System.out::println);  // 串行流: 2(与findFirst一致); 并行流: 2 或 4 或 6}
}

示例2:判断

package com.itheima.day3.stream;import java.util.stream.IntStream;public class C08MatchTest {public static void main(String[] args) {IntStream stream = IntStream.of(1, 2, 3, 4, 5, 6);// 检查是否有偶数System.out.println(stream.anyMatch(x -> (x & 1) == 0));  // true// 检查是否所有元素都是偶数System.out.println(stream.allMatch(x -> (x & 1) == 0));  // false// 检查是否所有元素都不是偶数System.out.println(stream.noneMatch(x -> (x & 1) == 0));  // false}
}

9. 排序与去重 - distinct、sorted

示例代码

package com.itheima.day3.stream;import java.util.Comparator;
import java.util.stream.IntStream;
import java.util.stream.Stream;public class C09SortTest {public static void main(String[] args) {// 去重IntStream.of(1, 2, 3, 1, 2, 3, 3, 4, 5).distinct().forEach(System.out::println);  // 1, 2, 3, 4, 5// 排序Stream.of(new Hero("令狐冲", 90),new Hero("风清扬", 98),new Hero("独孤求败", 100),new Hero("方证", 92),new Hero("东方不败", 98),new Hero("冲虚", 90),new Hero("向问天", 88),new Hero("任我行", 92),new Hero("不戒", 88))
//                .sorted((a, b) -> a.strength() < b.strength() ? -1 : a.strength() == b.strength() ? 0 : 1)  // 按武力值升序排序
//                .sorted((a, b) -> Integer.compare(a.strength(), b.strength()))
//                .sorted(Comparator.comparingInt(h -> h.strength()))
//                .sorted(Comparator.comparingInt(Hero::strength).reversed()) // 按武力降序.sorted(Comparator.comparingInt(Hero::strength).reversed().thenComparingInt(h -> h.name().length())) // 按武力降序,武力相等的按名字长度升序.forEach(System.out::println);}record Hero(String name, int strength) {}
}

10. 化简 - reduce

适用场景:求最大值、最小值、平均值、和、个数

示例代码:

package com.itheima.day3.stream;import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;/*化简:两两合并,只剩一个适合:最大值、最小值、求和、求个数....reduce((p, x) -> r)        p 上次的合并结果, x 当前元素, r 本次合并结果.reduce(init, (p, x) -> r).reduce(init, (p, x) -> r, (r1, r2) -> r)*/
public class C10ReduceTest {record Hero(String name, int strength) {}public static void main(String[] args) {Stream<Hero> stream = Stream.of(new Hero("令狐冲", 90),new Hero("风清扬", 98),new Hero("独孤求败", 100),new Hero("方证", 92),new Hero("东方不败", 98),new Hero("冲虚", 90),new Hero("向问天", 88),new Hero("任我行", 92),new Hero("不戒", 88));// 1) 求武力最高的 heroOptional<Hero> result = stream.reduce((h1, h2) -> h1.strength() > h2.strength() ? h1 : h2);Hero result2 = stream.reduce(new Hero("-", -1), (h1, h2) -> h1.strength() > h2.strength() ? h1 : h2);System.out.println(result2);// 2) 求高手总数System.out.println(stream.map(h -> 1).reduce(0, Integer::sum));System.out.println(stream.count());// 3) 求武力值最高的heroSystem.out.println(stream.max(Comparator.comparingInt(Hero::strength)));// 4) 求武力值最低的heroSystem.out.println(stream.min(Comparator.comparingInt(Hero::strength)));// 5) 求所有hero的武力值的和System.out.println(stream.mapToInt(Hero::strength).sum());// 6) 求hero的武力值的平均值System.out.println(stream.mapToInt(Hero::strength).average());}
}

11. 收集 - collect

作用:将元素收集入容器

示例代码:

package com.itheima.day3.stream;import java.util.*;
import java.util.stream.Stream;public class C11CollectTest {record Hero(String name, int strength) {}/*收集:将元素收集入容器.collect(() -> c, (c, x) -> void, ?)() -> c             创建容器 c(c, x) -> void      将元素 x 加入 容器 c*/public static void main(String[] args) {Stream<String> stream = Stream.of("令狐冲", "风清扬", "独孤求败", "方证","东方不败", "冲虚", "向问天", "任我行", "不戒", "不戒", "不戒", "不戒");// ------------------收集到集合容器---------------// 1) 收集到 ListList<String> result = stream.collect(() -> new ArrayList<>(), (list, x) -> list.add(x), (a, b) -> {});// ArrayList::new   () -> new ArrayList()// ArrayList::add   (list, x) -> list.add(x)List<String> result2 = stream.collect(ArrayList::new, ArrayList::add, (a, b) -> {});// 2) 收集到 SetSet<String> result3 = stream.collect(LinkedHashSet::new, Set::add, (a, b) -> {});// 3)收集到 Map (key、value)Map<String, Integer> result4 = stream.collect(HashMap::new, (map, x) -> map.put(x, 1), (a, b) -> {});for (Map.Entry<String, Integer> entry : result4.entrySet()) {System.out.println(entry);}// ---------------收集到字符串容器-----------------// 4) 收集到StringBuilderStringBuilder sb = stream.collect(StringBuilder::new, StringBuilder::append, (a, b) -> {});System.out.println(sb);// 5) 收集到StringJoiner 添加分隔符StringJoiner sj = stream.collect(() -> new StringJoiner(","), StringJoiner::add, (a, b) -> {});System.out.println(sj);}
}

12. 收集器 - Collectors

示例代码:

package com.itheima.day3.stream;import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;// Collector 收集器
public class C12CollectorTest {record Hero(String name, int strength) {}public static void main(String[] args) {Stream<String> stream = Stream.of("令狐冲", "风清扬", "独孤求败", "方证","东方不败", "冲虚", "向问天", "任我行", "不戒");// 1) 收集到 ListList<String> result = stream.collect(() -> new ArrayList<>(), (list, x) -> list.add(x), (a, b) -> {});List<String> result2 = stream.collect(ArrayList::new, ArrayList::add, (a, b) -> {});List<String> result3 = stream.collect(Collectors.toList());List<String> result4 = stream.toList();// 2) 收集到 SetSet<String> result5 = stream.collect(LinkedHashSet::new, Set::add, (a, b) -> {});Set<String> result6 = stream.collect(Collectors.toSet());// 3)收集到 StringBuilderStringBuilder sb = stream.collect(StringBuilder::new, StringBuilder::append, (a, b) -> {});String result7 = stream.collect(Collectors.joining());// 4) 收集到 StringJoinerStringJoiner sj = stream.collect(() -> new StringJoiner(","), StringJoiner::add, (a, b) -> {});String result8 = stream.collect(Collectors.joining(","));// 5) 收集到 Map (key、value)Map<String, Integer> result9 = stream.collect(HashMap::new, (map, x) -> map.put(x, 1), (a, b) -> {});Map<String, Integer> map = stream.collect(Collectors.toMap(x -> x, x -> 1));/*Map2: new ArrayList(["方证","冲虚","不戒"])3: new ArrayList(["令狐冲","风清扬","向问天","任我行"])4: new ArrayList(["独孤求败","东方不败"])下游收集器*/// 按元素长度分组收集Map<Integer, List<String>> result10 = stream.collect(Collectors.groupingBy(String::length, Collectors.toList()));// 按元素长度分组收集,并将元素使用逗号分隔Map<Integer, String> result11 = stream.collect(Collectors.groupingBy(String::length, Collectors.joining(",")));for (Map.Entry<Integer, String> e : result11.entrySet()) {System.out.println(e);}}
}

13. 下游收集器

与groupingBy()配合使用的下游收集器:

收集器含义
mapping(x -> y, dc)将 x 转换为 y,用下游收集器 dc 收集
flatMapping(x -> substream, dc)将 x 转换为 substream,用下游收集器dc收集 
filtering(x -> boolean, dc)过滤后,用下游收集器 dc 收集
counting()求个数
minBy((a, b) -> int)求最小
maxBy((a, b) -> int)求最大
summingInt(x -> int)转 int 后求和
averagingInt(x -> int)转 int 后求平均
reducing(init, (p, x) -> r)init 初始值,用上次结果 p 和当前元素 x 生成本次结果r

示例代码:

package com.itheima.day3.stream;import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;// 静态导入
import static java.util.stream.Collectors.*;public class C13GroupingByTest {record Hero(String name, int strength) {}public static void main(String[] args) {Stream<Hero> stream = Stream.of(new Hero("令狐冲", 90),new Hero("风清扬", 98),new Hero("独孤求败", 100),new Hero("方证", 92),new Hero("东方不败", 98),new Hero("冲虚", 90),new Hero("向问天", 88),new Hero("任我行", 92),new Hero("不戒", 88));// 1. mapping(x -> y, dc)  需求:根据名字长度分组,分组后组内只保留他们的武力值// new Hero("令狐冲", 90) -> 90// dc 下游收集器 down collectorMap<Integer, List<Integer>> collect1 = stream.collect(groupingBy(h -> h.name().length(), mapping(Hero::strength, toList())));// 2. filtering(x -> boolean, dc)  需求:根据名字长度分组,分组后组内过滤掉武力小于 90 的// 在分组收集的过程中,执行过滤Map<Integer, List<Hero>> collect2 = stream.collect(groupingBy(h -> h.name().length(), filtering(h -> h.strength() >= 90, toList())));// 或 先过滤,再来分组收集Map<Integer, List<Hero>> collect3 = stream.filter(h -> h.strength() >= 90).collect(groupingBy(h -> h.name().length(), toList()));// 3. flatMapping(x -> substream, dc)     需求:根据名字长度分组,分组后组内保留人名,并且人名切分成单个字符// "令狐冲".chars().mapToObj(Character::toString).forEach(System.out::println);Map<Integer, List<String>> collect4 = stream.collect(groupingBy(h -> h.name().length(),flatMapping(h -> h.name().chars().mapToObj(Character::toString), toList())));// 4. counting() 需求:根据名字长度分组,分组后求每组个数stream.collect(groupingBy(h -> h.name().length(), counting()));//5. minBy((a, b) -> int) 需求:根据名字长度分组,分组后求每组武功最低的人// 6. maxBy((a, b) -> int) 需求:根据名字长度分组,分组后求每组武功最高的人Map<Integer, Optional<Hero>> collect5 = stream.collect(groupingBy(h -> h.name().length(), minBy(Comparator.comparingInt(Hero::strength))));Map<Integer, Optional<Hero>> collect6 = stream.collect(groupingBy(h -> h.name().length(), maxBy(Comparator.comparingInt(Hero::strength))));// 7. summingInt(x -> int)            需求:根据名字长度分组,分组后求每组武力和// 8. averagingDouble(x -> double)    需求:根据名字长度分组,分组后求每组武力平均值Map<Integer, Integer> collect7 = stream.collect(groupingBy(h -> h.name().length(), summingInt(h -> h.strength)));Map<Integer, Double> collect8 = stream.collect(groupingBy(h -> h.name().length(), averagingDouble(Hero::strength)));// 9. reducing(init, (p, x) -> r)// 求和Map<Integer, Integer> collect9 = stream.collect(groupingBy(h -> h.name().length(), mapping(Hero::strength, reducing(0, Integer::sum))));// 求个数Map<Integer, Integer> collect10 = stream.collect(groupingBy(h -> h.name().length(), mapping(h -> 1, reducing(0, Integer::sum))));// 求平均,缺少 finisherMap<Integer, double[]> collect = stream.collect(groupingBy(h -> h.name().length(),mapping(h -> new double[]{h.strength(), 1},reducing(new double[]{0, 0}, (p, x) -> new double[]{p[0] + x[0], p[1] + x[1]}))));for (Map.Entry<Integer, double[]> e : collect.entrySet()) {System.out.println(e.getKey() + ":" + Arrays.toString(e.getValue()));}}
}

14. 基本流

基本类型是指 IntStream、LongStream 和 DoubleStream,它们在做数值计算时有更好的性能。

int 流含义
intStream.mapToObj(int -> obj)转换为obj流 (对象流)
intStream.boxed()转换为Integer流(对象流)
intStream.sum()求和
intStream.min()求最小值,返回Optional
intStream.max()求最大值,返回Optional
intStream.average()求平均值,返回Optional
intStream.summaryStatistics()综合count sum min max average

示例代码:

package com.itheima.day3.stream;import java.util.IntSummaryStatistics;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;public class C14Effective {record Hero(String name, int strength) {}/*三种基本流*/public static void main(String[] args) {IntStream a = IntStream.of(97, 98, 99);LongStream b = LongStream.of(1L, 2L, 3L);DoubleStream c = DoubleStream.of(1.0, 2.0, 3.0);Stream<Integer> d = Stream.of(1, 2, 3);// 转换为字符串a.mapToObj(Character::toString).forEach(System.out::println);  // a b c// count sum min max averageIntSummaryStatistics stat = a.summaryStatistics();System.out.println(stat.getSum());  // 294System.out.println(stat.getCount());  // 3System.out.println(stat.getMax());  // 99System.out.println(stat.getMin());  // 97System.out.println(stat.getAverage());  // 98.0}
}

转换成基本流:

转换含义
stream.map(x -> y)将流中的每个元素x通过mapper函数转换为另一种类型y,形成新的stream
stream.flatMap(x -> substream)将每个元素x映射为一个子流substream,然后将所有子流扁平化合并为一个新的stream
stream.mapMulti(x, consumer) -> void)类似flatMap,但通过Consumer动态决定输出多个或零个元素到结果流
stream.mapToInt(x -> int)将流元素x转换为int,返回一个IntStream(原始类型流,避免装箱开销)
stream.mapToLong(x -> long)将流元素x转为long,返回LongStream
stream.mapToDouble(x -> double)将流元素x转换为double,返回DoubleStream

示例代码:

package com.itheima.day3.stream;import java.util.stream.Stream;public class C14Effective {record Hero(String name, int strength) {}/*三种基本流*/public static void main(String[] args) {Stream<Hero> stream = Stream.of(new Hero("令狐冲", 90),new Hero("风清扬", 98));stream.mapToInt(Hero::strength).forEach(System.out::println);  // 90 98}
}

15. 特性

(1)不可变性

  • 描述:Stream操作(如filter、map)不会修改原始数据源,而是生成一个新的Stream
  • 优势:避免副作用,适合并发编程。

(2)惰性求值(Lazy Evaluation)

  • 描述:中间操作(如filter、map)不会立即执行,只有在终端操作(如collect、forEach)触发时才会实际计算。
  • 优势:优化性能(如短路操作limit()、findFirst()。
  • 示例:
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
numbers.stream().filter(n -> {System.out.println("Filtering: " + n); // 只有终端操作触发时才会执行return n % 2 == 0;}).map(n -> {System.out.println("Mapping: " + n);return n * 2;}).findFirst(); // 触发计算,可能只处理前几个元素

(3)一次性消费(Single Use)

  • 描述:Stream只能被消费一次,终端操作调用后流即关闭,再次使用会抛出IllegalStateException
  • 示例:
Stream<Integer> stream = Stream.of(1, 2, 3);
stream.forEach(System.out::println); // 正常
stream.forEach(System.out::println); // 抛出异常

(4)并行处理(Parallel Processing)

  • 描述:通过parallel() 方法将流转换为并行流,自动利用多核CPU加速处理。
  • 注意:需确保操作是线程安全的,无共享可变状态。
  • 示例:
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
int sum = numbers.parallelStream() // 并行流.mapToInt(n -> n * 2).sum();

示例代码:

package com.itheima.day3.stream;import java.util.stream.Stream;public class C15Summary {public static void main(String[] args) {/*掌握 Stream 流的特性1. 一次使用2. 两类操作(中间操作 lazy 懒惰, 终结操作 eager 迫切)*/Stream<Integer> s1 = Stream.of(1, 3, 5); // 水滴// 一次特性// s1.forEach(System.out::println);  // 1, 3, 5// s1.forEach(System.out::println);  // java.lang.IllegalStateException: stream has already been operated upon or closed// -----------------------------------    -------------------------  阀门// 在终结操作被调用时才执行前面的中间操作s1.map(x -> x + 1)                        // 水管 2 4 6.filter(x -> x <= 5)                    // 水管 2 4.forEach(System.out::println);          // 水管 总阀门 2 4}
}

16. 并行

示例代码:

package com.itheima.day3.stream;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collector;
import java.util.stream.Stream;// 并行流
public class C16Parallel {public static void main(String[] args) {// 单线程List<Integer> collect = Stream.of(1, 2, 3, 4).collect(Collector.of(// 如何创建容器() -> {System.out.printf("%-12s %s%n",simple(),"create");return new ArrayList<Integer>();},// 如何向容器添加数据(list, x) -> {List<Integer> old = new ArrayList<>(list);list.add(x);System.out.printf("%-12s %s.add(%d)=>%s%n",simple(), old, x, list);},// 如何合并两个容器的数据(list1, list2) -> {List<Integer> old = new ArrayList<>(list1);list1.addAll(list2);System.out.printf("%-12s %s.add(%s)=>%s%n", simple(),old, list2, list1);return list1;},// 收尾list -> null,// 特性:并发、收尾、顺序Collector.Characteristics.IDENTITY_FINISH));/*1) 数据量问题: 数据量大时才建议用并行流2) 线程会无限增加吗: 跟 cpu 能处理的线程数相关3) 收尾的意义: 转不可变集合、StringBuilder 转 String ...4) 是否线程安全: 不会有线程安全问题(访问的不是同一个ArrayList,互不干扰)5) 特性:是否需要收尾(默认收尾)是否需要保证顺序(默认保证)容器是否支持并发(默认不需要支持)到达选择哪一种?A. Characteristics.CONCURRENT + Characteristics.UNORDERED + 线程安全容器 -> 并发量大性能可能会受影响B. 默认 + 线程不安全容器                                                  -> 占用内存多,合并多也会影响性能*/List<Integer> collect2 = Stream.of(1, 2, 3, 4).parallel().collect(Collector.of(// 如何创建容器() -> {System.out.printf("%-12s %s%n", simple(), "create");return new Vector<Integer>();  // 支持并发的容器,线程安全},// 如何向容器添加数据(list, x) -> {List<Integer> old = new ArrayList<>(list);list.add(x);System.out.printf("%-12s %s.add(%d)=>%s%n", simple(), old, x, list);},// 如何合并两个容器的数据(list1, list2) -> {List<Integer> old = new ArrayList<>(list1);list1.addAll(list2);System.out.printf("%-12s %s.add(%s)=>%s%n", simple(), old, list2, list1);return list1;},// 收尾list -> {System.out.printf("%-12s finish: %s=>%s%n", simple(), list, list);return Collections.unmodifiableList(list);  // 转不可变List}// 特性:并发、是否需要收尾,是否要保证收集顺序, Collector.Characteristics.IDENTITY_FINISH     // 不需要收尾, Collector.Characteristics.UNORDERED           // 不需要保证收集顺序, Collector.Characteristics.CONCURRENT          // 支持并发));System.out.println(collect2);// java.lang.UnsupportedOperationException(如果没添加: Collector.Characteristics.IDENTITY_FINISH )collect2.add(100);System.out.println(collect2);}private static String simple() {String name = Thread.currentThread().getName();int idx = name.indexOf("worker");if (idx > 0) {return name.substring(idx);}return name;}
}

17. 效率

示例1:求和

package com.itheima.day3.performance;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.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;// 性能:求和
public class T01Sum {@State(Scope.Benchmark)public static class MyState {public static final int COUNT = 10000;public int[] numbers = new int[COUNT];public List<Integer> numberList = new ArrayList<>(COUNT);public MyState() {for (int i = 0; i < COUNT; i++) {int x = i + 1;numbers[i] = x;numberList.add(i, x);}}}// 基本类型 -> 用loop循环对int求和@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public int primitive(MyState state) {int sum = 0;for (int number : state.numbers) {sum += number;}return sum;}// 包装类型 - 用loop循环对Integer求和@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public int boxed(MyState state) {int sum = 0;for (Integer i : state.numberList) {sum += i;}return sum;}// 普通Stream流 -> 用Stream对Integer求和@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public int stream(MyState state) {return state.numberList.stream().reduce(0, (a, b) -> a + b);}// 基本流 -> 用IntStream对int求和@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public int intStream(MyState state) {return IntStream.of(state.numbers).sum();}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(T01Sum.class.getSimpleName())  // 指定要运行的测试类.forks(1)  // 使用一个独立JVM进程.build();new Runner(opt).run();//        MyState state = new MyState();
//        T01Sum test = new T01Sum();
//        System.out.println(test.primitive(state));
//        System.out.println(test.boxed(state));
//        System.out.println(test.stream(state));
//        System.out.println(test.intStream(state));}
}

测试结果对比:Score的单位为ms

  • 元素个数为100时:
BenchmarkModeCntScore (ns/op)Error (ns/op)Units
T01Sum.primitiveavgt525.424± 0.782ns/op
T01Sum.intStreamavgt547.482± 1.145ns/op
T01Sum.boxedavgt572.457± 4.136ns/op
T01Sum.streamavgt5465.141± 4.891ns/op

  • 元素个数为1000时:
BenchmarkModeCntScore (ns/op) Error (ns/op)Units
T01Sum.primitiveavgt5270.556± 1.277ns/op
T01Sum.intStreamavgt5292.467± 10.987ns/op
T01Sum.boxedavgt5583.929± 57.338ns/op
T01Sum.streamavgt55948.294± 2209.211ns/op
  • 元素个数为10000时:
BenchmarkModeCntScore (ns/op)Error (ns/op)Units
T01Sum.primitiveavgt52681.651± 12.614ns/op
T01Sum.intStreamavgt52718.408± 52.418ns/op
T01Sum.boxedavgt56391.285± 358.154ns/op
T01Sum.streamavgt544414.884± 3213.055ns/op

结论:

  • 做数值计算,优先挑选基本流(IntStream等),在数据量较大时,它的性能已经非常接近普通for循环;
  • 做数值计算,应当避免普通流(Stream),性能与其它几种相比,慢一个数量级。

示例2:求最大值

package com.itheima.day3.performance;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.ArrayList;
import java.util.concurrent.*;
import java.util.stream.IntStream;// 性能:求最大值
public class T02Parallel {static final int n = 1000000;@State(Scope.Benchmark)public static class MyState {int[] numbers = new int[n];{for (int i = 0; i < n; i++) {numbers[i] = ThreadLocalRandom.current().nextInt(10000000);}}}/*** loop循环求最大值* @param state* @return*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public int primitive(MyState state) {int max = 0;for (int number : state.numbers) {if (number > max) {max = number;}}return max;}/*** 串行流求最大值* @param state* @return*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public int sequence(MyState state) {return IntStream.of(state.numbers).max().orElse(0);}/*** 并行流求最大值* @param state* @return*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public int parallel(MyState state) {return IntStream.of(state.numbers).parallel().max().orElse(0);}/*** 分而治之 - 自定义多线程并行求最大值*  - 将数据分成10份,从每份里找到最大的,最后从每份的最大值中再挑选出整体的最大值* @param state* @return* @throws ExecutionException* @throws InterruptedException*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public int custom(MyState state) throws ExecutionException, InterruptedException {int[] numbers = state.numbers;// 将数据分成10份int step = n / 10;ArrayList<Future<Integer>> result = new ArrayList<>();try (ExecutorService service = Executors.newVirtualThreadPerTaskExecutor()) {// 从每份里找打最大值添加到resultfor (int j = 0; j < n; j += step) {int k = j;result.add(service.submit(() -> {int max = 0;for (int i = k; i < k + step; i++) {if (numbers[i] > max) {max = numbers[i];}}return max;}));}}System.out.println(result.size());int max = 0;// 从result里找到最大的,即为整体数据中最大值for (Future<Integer> future : result) {if (future.get() > max) {max = future.get();}}return max;}public static void main(String[] args) throws RunnerException, ExecutionException, InterruptedException {Options opt = new OptionsBuilder().include(T02Parallel.class.getSimpleName()).forks(1).build();new Runner(opt).run();
//        MyState state = new MyState();
//        T02Parallel test = new T02Parallel();
//        System.out.println(test.primitive(state));
//        System.out.println(test.sequence(state));
//        System.out.println(test.parallel(state));
//        System.out.println(test.custom(state));}
}

测试结果对比:

  • 元素个数为100时:
BenchmarkModeCntScore (ns/op)Error (ns/op)Units
T02Parallel.customavgt539619.796± 1263.036ns/op
T02Parallel.parallelavgt56754.239± 79.894ns/op
T02Parallel.primitiveavgt529.538± 3.056ns/op
T02Parallel.sequenceavgt580.170± 1.940ns/op
  • 元素个数为10000时:
BenchmarkModeCntScore (ns/op)Error (ns/op)Units
T02Parallel.customavgt541656.093± 1537.237ns/op
T02Parallel.parallelavgt511218.573± 1994.863ns/op
T02Parallel.primitiveavgt52217.562± 80.981ns/op
T02Parallel.sequenceavgt55682.482± 264.645ns/op
  • 元素个数为1000000时:
BenchmarkModeCntScore (ns/op)Error (ns/op)Units
T02Parallel.customavgt5194984.564± 25794.484ns/op
T02Parallel.parallelavgt5298940.794± 31944.959ns/op
T02Parallel.primitiveavgt5325178.873± 81314.981ns/op
T02Parallel.sequenceavgt5618274.062± 5867.812ns/op

结论:

  • 并行流相对自定义多线程实现分而治之代码更为简洁;
  • 并行流只有在数据量非常大时,才能充分发力;数据量少时,还不如用串行流

示例3:并行(发)收集

package com.itheima.day3.performance;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.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;import static java.util.stream.Collectors.*;// 性能:并行(发)收集
// ConcurrentHashMap
// HashMap
public class T03Concurrent {static final int n = 1000000;@State(Scope.Benchmark)public static class MyState {int[] numbers = new int[n];{for (int i = 0; i < n; i++) {numbers[i] = ThreadLocalRandom.current().nextInt(n / 10);}}}/*** 不可变 - 新的计数值* @param state* @return*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public Map<Integer, Integer> loop1(MyState state) {Map<Integer, Integer> map = new HashMap<>();for (int number : state.numbers) {map.merge(number, 1, Integer::sum);}return map;}/*** AtomicInteger对象* @param state* @return*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public Map<Integer, AtomicInteger> loop2(MyState state) {Map<Integer, AtomicInteger> map = new HashMap<>();for (int number : state.numbers) {map.computeIfAbsent(number, k -> new AtomicInteger()).getAndIncrement();}return map;}/*** 单线程* @param state* @return*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public Map<Integer, Long> sequence(MyState state) {return Arrays.stream(state.numbers).boxed().collect(groupingBy(Function.identity(), counting()));  // 数字相同的分到一组,值为出现次数}/*** 并行流 - 用hashMap收集* @param state* @return*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public Map<Integer, Long> parallelNoConcurrent(MyState state) {return Arrays.stream(state.numbers).boxed().parallel().collect(groupingBy(Function.identity(), counting()));}/*** 并行流 - 内部用支持并发的容器concurrentHashMap(容器数量为1)* @param state* @return*/@Benchmark@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public ConcurrentMap<Integer, Long> parallelConcurrent(MyState state) {return Arrays.stream(state.numbers).boxed().parallel().collect(groupingByConcurrent(Function.identity(), counting()));}public static void main(String[] args) throws RunnerException, ExecutionException, InterruptedException {Options opt = new OptionsBuilder().include(T03Concurrent.class.getSimpleName()).forks(1).build();new Runner(opt).run();
//        MyState state = new MyState();
//        T03Concurrent test = new T03Concurrent();
//        System.out.println(test.loop1(state));
//        System.out.println(test.loop2(state));
//        System.out.println(test.sequence(state));
//        System.out.println(test.parallelNoConcurrent(state));
//        System.out.println(test.parallelConcurrent(state));}
}

测试结果对比:

  • 元素个数为100时:
BenchmarkModeCntScore (ns/op)Error (ns/op)Units
loop1avgt51312.389± 90.683ns/op
loop2avgt51776.391± 255.271ns/op
sequenceavgt51727.739± 28.821ns/op
parallelNoConcurrentavgt527654.004± 496.970ns/op
parallelConcurrentavgt516320.113± 344.766ns/op
  • 元素个数为10000时:
BenchmarkModeCntScore (ns/op)Error (ns/op)Units
loop1avgt5211526.546± 13549.703ns/op
loop2avgt5203794.146± 3525.972ns/op
sequenceavgt5237688.651± 7593.483ns/op
parallelNoConcurrentavgt5527203.976± 3496.107ns/op
parallelConcurrentavgt5369630.728± 20549.731ns/op
  • 元素个数为1000000时:
BenchmarkModeCntScore (ms/op)Error (ms/op)Units
loop1avgt569.154± 3.456ms/op
loop2avgt583.815± 2.307ms/op
sequenceavgt5103.585± 0.834ns/op
parallelNoConcurrentavgt5167.032± 15.406ms/op
parallelConcurrentavgt552.326± 1.501ms/op

结论:

  • sequence是一个容器单线程收集,数据量少时性能占优;
  • parallelNoConcurrent是多个容器多线程并行收集,时间应该花费在合并容器上,性能最差;
  • parallelConcurrent是一个容器多线程并发收集,在数据量大时性能较优。

示例4:MethodHandle性能

package jmh;import org.openjdk.jmh.annotations.Benchmark;
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.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.BinaryOperator;public class Sample2 {/*** 普通方法调用* @return*/@Benchmarkpublic int origin() {return add(1, 2);}static int add(int a, int b) {return a + b;}// ----------------------------static Method method;static MethodHandle methodHandle;static {try {method = Sample2.class.getDeclaredMethod("add", int.class, int.class);methodHandle = MethodHandles.lookup().unreflect(method);} catch (NoSuchMethodException | IllegalAccessException e) {throw new RuntimeException(e);}}/*** 反射* @return* @throws InvocationTargetException* @throws IllegalAccessException*/@Benchmarkpublic Object reflection() throws InvocationTargetException, IllegalAccessException {// 动态调用add方法return method.invoke(null, 1, 2);}/*** MethodHandle* @return* @throws Throwable*/@Benchmarkpublic Object method() throws Throwable {// 使用MethodHandle调用add方法,比反射更轻量级,更接近JVM底层调用机制return methodHandle.invoke(1, 2);}// ----------------------------------/*** Lambda* @return*/@Benchmarkpublic int lambda() {return test(Integer::sum, 1, 2);}@FunctionalInterfaceinterface Add {int add(int a, int b);}static int test(Add add, int a, int b) {return add.add(a, b);}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(Sample2.class.getSimpleName()).forks(1).build();new Runner(opt).run();}
}

测试结果对比:

BenchmarkModeCntScoreErrorUnits
Sample2.lambdathrpt5389307532.881± 332213073.039ops/s
Sample2.methodthrpt5157556577.611± 4048306.620ops/s
Sample2.originthrpt5413287866.949± 65182730.966ops/s
Sample2.reflectionthrpt591640751.456± 37969233.369ops/s

结论:

  • 普通方法调用最快,Lambda性能接近普通方法,MethodHandle性能约为普通方法的38%,反射Reflection最慢,仅为普通方法的22%。
  • 尽量使用普通方法或Lambda,避免使用反射


http://www.hkcw.cn/article/RUxYGcONAQ.shtml

相关文章

16.FreeRTOS

目录 第1章 FreeRTOS 实时操作系统 1.1 认识实时操作系统 1.1.1 裸机的概念 1.1.2 操作系统的概念 1.2 操作系统的分类 1.3 常见的操作系统 1.4 认识实时操作系统 1.4.1 可剥夺型内核与不可剥夺型内核 1.4.2 嵌入式操作系统的作用 1.4.3 嵌入式操作系统的发展 1.4.4…

windows11安装scoop 20250602

详细的 Scoop 安装步骤&#xff1a; 使用国内镜像安装 Scoop 首先&#xff0c;打开 PowerShell&#xff08;右键点击 win按钮&#xff0c;–>终端&#xff0c;Scoop官方不建议用管理员权限安装)&#xff0c;然后执行以下命令&#xff1a; # 设置 Scoop 安装路径 $env:SCOO…

类和对象(一)

一、面向对象 &#xff08;OOP是面向对象的语言的简称&#xff09; Java是⼀⻔纯⾯向对象的语⾔&#xff0c;在⾯向对象的世界⾥&#xff0c;⼀切皆 为对象。⾯向对象是解决问题的⼀种思想&#xff0c;主要依靠对象之间的交互完成⼀件事情。 面向对象——>不关注过程&…

OpenCV4.4.0下载及初步配置(Win11)

目录 OpenCV4.4.0工具下载安装环境变量系统配置 OpenCV4.4.0 工具 系统&#xff1a;Windows 11 下载 OpenCV全版本百度网盘链接&#xff1a;: https://pan.baidu.com/s/15qTzucC6ela3bErdZ285oA?pwdjxuy 提取码: jxuy找到 opencv-4.0.0-vc14_vc15 下载得到 安装 运行op…

QGIS Python脚本开发(入门级)

随着人工智能技术的飞速发展&#xff0c;编程语言和脚本开发正变得前所未有的便捷。在GIS领域&#xff0c;QGIS作为一款卓越的开源地理信息系统软件&#xff0c;凭借其易于下载、界面简洁、功能强大等诸多优势&#xff0c;赢得了全球用户的青睐。更令人兴奋的是&#xff0c;QGI…

【算法】分支限界

一、基本思想 &#xff08;分支限界&#xff0c; 分枝限界&#xff0c; 分支界限 文献不同说法但都是一样的&#xff09; 分支限界法类似于回溯法&#xff0c;也是一种在问题的解空间树上搜索问题解的算法。 但一般情况下&#xff0c;分支限界法与回溯法的求解目标不同。回溯…

【springcloud】快速搭建一套分布式服务springcloudalibaba(四)

第四篇 基于nacos搭建分布式项目 分布式系统日志&#xff08;skywalkinges&#xff09; 项目所需 maven nacos java8 idea git mysql redis skywalking es 本文主要从客户下单时扣减库存的操作&#xff0c;将链路日志模拟出来&#xff0c;网关系统/用户系统/商品系统/订…

设计模式(行为型)-中介者模式

目录 定义 类图结构展示 角色职责详解 模式的优缺点分析 优点 缺点 适用场景 应用实例 与其他模式的结合与拓展 总结 定义 中介者模式的核心思想可以概括为&#xff1a;用一个中介对象来封装一系列的对象交互。这个中介者就像一个通信枢纽&#xff0c;使各对象不需要…

PMOS以及电源转换电路设计

PMOS的使用 5V_EN5V时&#xff0c;PMOS截止&#xff1b; 5V_EN0V时&#xff0c;PMOS导通&#xff1b; 电源转换电路 当Vout0V时&#xff0c;Vg0V, Vgs>Vth, PMOS导通&#xff0c;只有电池供电&#xff1b; 当Vout5V时&#xff0c;Vg4.9V, Vs4.8V?, Vgs<Vth, PMOS截止&am…

本地部署 DeepSeek R1(最新)【从下载、安装、使用和调用一条龙服务】

文章目录 一、安装 Ollama1.1 下载1.2 安装 二、下载 DeepSeek 模型三、使用 DeepSeek3.1 在命令行环境中使用3.2 在第三方软件中使用 一、安装 Ollama 1.1 下载 官方网址&#xff1a;Ollama 官网下载很慢&#xff0c;甚至出现了下载完显示 无法下载&#xff0c;需要授权 目…

数据治理的演变与AI趋势

知识星球&#xff1a;数据书局。打算通过知识星球将这些年积累的知识分享出来&#xff0c;让各位在数据治理、数据分析的路上少走弯路&#xff0c;另外星球也方便动态更新最近的资料&#xff0c;提供各位一起讨论数据的小圈子 1.数据治理的演变 1.1.摘要 数据治理是指组织管…

Fullstack 面试复习笔记:操作系统 / 网络 / HTTP / 设计模式梳理

Fullstack 面试复习笔记&#xff1a;操作系统 / 网络 / HTTP / 设计模式梳理 面试周期就是要根据JD调整准备内容&#xff08;挠头&#xff09;&#xff0c;最近会混合复习针对全栈这块的内容&#xff0c;目前是根据受伤的JD&#xff0c;优先选择一些基础的操作系统、Java、Nod…

【MIMO稳定裕度】基于数据驱动的多输入多输出系统稳定裕度分析

最近一直在忙着写论文&#xff0c;只能说要写一篇高水平论文确实不容易&#xff0c;要一直反复来回修改调整&#xff0c;要求比较高&#xff0c;所以没太有时间和精力写博客&#xff0c;这两天结束了初稿&#xff0c;又正好是假期&#xff0c;出来冒个泡。 本次分享的主题是&am…

Python 训练营打卡 Day 33-神经网络

简单神经网络的流程 1.数据预处理&#xff08;归一化、转换成张量&#xff09; 2.模型的定义 继承nn.Module类 定义每一个层 定义前向传播流程 3.定义损失函数和优化器 4.定义训练过程 5.可视化loss过程 预处理补充&#xff1a; 分类任务中&#xff0c;若标签是整…

TDengine 的 AI 应用实战——电力需求预测

作者&#xff1a; derekchen Demo数据集准备 我们使用公开的UTSD数据集里面的电力需求数据&#xff0c;作为预测算法的数据来源&#xff0c;基于历史数据预测未来若干小时的电力需求。数据集的采集频次为30分钟&#xff0c;单位与时间戳未提供。为了方便演示&#xff0c;按…

【03】完整开发腾讯云播放器SDK的UniApp官方UTS插件——优雅草上架插件市场-卓伊凡

【03】完整开发腾讯云播放器SDK的UniApp官方UTS插件——优雅草上架插件市场-卓伊凡 一、项目背景与转型原因 1.1 原定计划的变更 本系列教程最初规划是开发即构美颜SDK的UTS插件&#xff0c;但由于甲方公司内部战略调整&#xff0c;原项目被迫中止。考虑到&#xff1a; 技术…

(aaai2024) Omni-Kernel Network for Image Restoration

代码&#xff1a;https://github.com/c-yn/OKNet 研究动机&#xff1a;作者认为Transformer模型计算复杂度太高&#xff0c;因此提出了 omni-kernel module &#xff08;OKM&#xff09;&#xff0c;可以有效的学习局部到全局的特征表示。该模块包括&#xff1a;全局、大分支、…

useMemo useCallback 自定义hook

useMemo & useCallback & 自定义hook useMemo 仅当依赖项发生变化的时候&#xff0c;才去重新计算&#xff1b;其他状态变化时则不去做不必要的计算。 useCallback 缓存函数。但是使用注意&#x1f4e2; &#xff0c;useCallback没有特别明显的优化。 *合适的场景——父…

android binder(二)应用层编程实例

一、binder驱动浅析 从上图看出&#xff0c;binder的通讯主要涉及三个步骤。 在 Binder Server 端定义好服务&#xff0c;然后向 ServiceManager 注册服务在 Binder Client 中向 ServiceManager 获取到服务发起远程调用&#xff0c;调用 Binder Server 中定义好的服务 整个流…

GESP2024年3月认证C++二级( 第三部分编程题(2)小杨的日字矩阵)

参考程序&#xff1a; #include <iostream> using namespace std;int main() {int n;cin >> n; // 读入奇数 n// 外层循环控制每一行for (int i 0; i < n; i) {// 内层循环控制每一列for (int j 0; j < n; j) {char ch;// 如果当前列是最左或最右&#x…