当前位置: 首页 > news >正文

Java基础:Stream流常用方法

获取Stream流的方式
java.util.stream.Stream 是Java 8新加入的流接口。(并不是一个函数式接口)
获取一个流非常简单,有以下几种常用的方式:

  • 所有 Collection 集合都可通过 stream 默认方法获取流(顺序流)
  • 所有 Collection 集合都可通过parallelStream获取并行流
  • Stream 接口的静态方法 of 可以获取数组对应的流。
  • Arrays的静态方法stream也可以获取流

根据Collection获取流

public static void main(String[] args) {List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();Set<String> set = new HashSet<>();Stream<String> stream2 = set.stream();Vector<String> vector = new Vector<>();// ...
}   

根据Map获取流

public static void main(String[] args) {Map<String, String> map = new HashMap<>();Stream<String> keyStream = map.keySet().stream();Stream<String> valueStream = map.values().stream();Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
}

根据数组获取流

如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以 Stream 接口中提供了静态方法of ,使用很简单:

public static void main(String[] args) {//使用 Stream.ofString[] array = { "张无忌", "张翠山", "张三丰", "张一元" };Stream<String> stream = Stream.of(array);//使用Arrays的静态方法Arrays.stream(array)
}

Stream流中的常用方法

方法可分成两种:

  • 延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除终结方法外,其余方法均为延迟方法)
  • 终结方法:返回值类型不是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调用。本节中,终结方法包括 count 和 forEach 方法。

1.forEach(终结方法)

用于遍历的方法,参数传入一个函数式接口:Consumer

public static void main(String[] args) {Stream<String> stream = Stream.of("张无忌", "张三丰", "周芷若");stream.forEach(name‐> System.out.println(name));
}

2.过滤:filter

可用于过滤。可通过 filter 方法将一个流转换成另一个子集流。

public static void main(String[] args) {//创建一个流Stream<String> stream = Stream.of( "刘德华", "张国荣", "彭于晏", "纳什", "吴彦祖");//对流中元素过滤,只要姓张的人Stream<String> stream2 = stream.filter(name -> {return name.startsWith("张");});//遍历过滤后的流stream2.forEach(name -> System.out.println(name));
}

3.映射(转换):map

如果需要将流中的元素映射到另一个流中,可用 map 方法。

该接口需要一个 Function 函数式接口参数

/*** stream流的map方法练习* map方法可以将流中的元素映射到另一个流中* map方法的参数是一个Function函数式接口*/@Testpublic void test(){//创建一个流,里面是字符串类型的整数Stream<String> stream1 = Stream.of("2", "32", "2", "33", "2");//把stream1流中的整数全部转成int类型Stream<Integer> stream2 = stream1.map((String s) -> {return Integer.parseInt(s);});//遍历stream2.forEach((i)-> System.out.println(i));}

4.统计个数:count(终结方法)

正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数:

该方法返回一个long值代表元素个数(不像旧集合那样是int值)。

public class Demo09StreamCount {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//筛选姓张的Stream<String> result = original.filter(s ‐> s.startsWith("张"));//输出个数System.out.println(result.count()); // 2}
}

5.取用前几个(截取):limit

limit 方法可对流进行截取,只取用前n个。

参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。

public class Demo10StreamLimit {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//截取前两个Stream<String> result = original.limit(2);System.out.println(result.count()); // 2}
}

6.跳过前几个元素:skip

如果希望跳过前几个元素,可用 skip 方法获取一个截取后的新流:

如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。

public class Demo11StreamSkip {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//跳过前两个,返回一个新的流Stream<String> result = original.skip(2);System.out.println(result.count()); // 1}
}

7.组合(合并流):concat

如果有两个流,希望合并为一个流,可以用 Stream 接口的静态方法 concat :

public class Demo12StreamConcat {public static void main(String[] args) {Stream<String> streamA = Stream.of("张无忌");Stream<String> streamB = Stream.of("张翠山");//合并成一个新的流Stream<String> result = Stream.concat(streamA, streamB);}
}

8.筛选:distinct

去除流中重复元素(使用hashcode和equals方法来对比)

9.映射(打开后再转换):flatMap

内部传入一个Function函数式接口,跟map的区别就是这个会把流中的元素打开,再组合成一个新的流

// map和flatMap的练习
public class StreamDemo {@Testpublic void test(){List<String> list = Arrays.asList("aa","bb","cc","dd");// 练习1 (map) 输出的全是大写list.stream().map(s -> s.toUpperCase()).forEach(System.out::println);System.out.println("----------");// 练习2(map)流里还有流,需要两个遍历才行看到里面内容Stream<Stream<Character>> streamStream = list.stream().map(StreamDemo::fromStringToStream);streamStream.forEach(s -> {s.forEach(System.out::println);});System.out.println("---------");// 练习3(flatMap)流里还有流,使用flatMap可以直接把里面的流打开,一次遍历就可以了Stream<Character> characterStream = list.stream().flatMap(StreamDemo::fromStringToStream);characterStream.forEach(System.out::println);}/***  将字符串中的多个字符构成的集合转换为对应的stream* @param str* @return*/public static Stream<Character> fromStringToStream(String str){ArrayList<Character> list = new ArrayList();// 将字符串转成字符数组,并遍历加入list集合for(Character c : str.toCharArray()){list.add(c);}// 返回list集合的stream流return list.stream();}
}

10.自然排序:sorted

看下一条里的代码

11.定制排序:sorted(Comparator com)

 /*** 排序的练习*/@Testpublic void test2(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 按照自然排序integers.stream().sorted().forEach(System.out::println);System.out.println("---------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 定制排序(大到小),需要传入Comparator接口(如果流中的是引用类型,只能用定制排序)// 简写:integers2.stream().sorted((e1,e2) -> e2-e1).forEach(System.out::println);integers2.stream().sorted((e1,e2) -> {return e2-e1;}).forEach(System.out::println);}

12.检测匹配(终结方法):

返回一个Boolean值

是否全部匹配:allMatch

是否至少匹配一个:anyMatch

是否没有匹配的:noneMatch

 /*** 匹配的练习*/@Testpublic void test3(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 判断是否全部大于5boolean b = integers.stream().allMatch(i -> i > 5);// 结束输出falseSystem.out.println(b);System.out.println("-------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 检测是否匹配至少一个元素boolean b1 = integers2.stream().anyMatch(i -> i > 5);// 输出trueSystem.out.println(b1);System.out.println("-------");List<Integer> integers3 = List.of(124, 2, 15, 12, 51, -5, 5);// 检查是否没有匹配的元素boolean b2 = integers3.stream().noneMatch(i -> i > 1000);// 输出true,全部不匹配System.out.println(b2);}

13.查找元素(终结方法)

查找第一个元素:findFirst,返回Optional类型

查找其中一个元素:findAny,返回Optional类型

public void test4(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 输出第一个元素Optional<Integer> first = integers.stream().findFirst();// 输出结果是Optional[124]System.out.println(first);System.out.println("-------------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 返回其中一个元素Optional<Integer> any = integers2.stream().findAny();System.out.println(any);}

14.查找最大最小值(终结方法)

max(comparator c)

min(comparator c)

 /*** 查找最大最小值*/@Testpublic void test5(){List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));//  查找年龄最大的人Optional<Person> max = list.stream().max((e1, e2) -> e1.getAge() - e2.getAge());// 返回马云,55岁年龄最大System.out.println(max.get());System.out.println("--------");

15.规约(终结方法)

reduce(T identity ,BinaryOperator) 第一个参数是初始值,第二个参数是一个函数式接口

reduce(BinaryOperator) 参数是一个函数式接口

/*** 归约的练习*/@Testpublic void test6(){List<Integer> integers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 求集合里数字的和(归约)reduce第一个参数是初始值。Integer sum = integers.stream().reduce(0, Integer::sum);System.out.println(sum);System.out.println("-------");List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));// 求所有人的工资和(归约)// 不用方法引用写法:Optional<Integer> reduce = list.stream().map(person -> person.getSalary()).reduce((e1, e2) -> e1 + e2);Optional<Integer> reduce = list.stream().map(Person::getSalary).reduce(Integer::sum);// 输出Optional[19937]System.out.println(reduce);}

16.收集(终结方法)

collect(Collector c):将流转化为其他形式,接收一个Collector接口的实现

/*** 收集的练习*/@Testpublic void test7(){List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));// 把年龄大于30岁的人,转成一个list集合List<Person> collect = list.stream().filter(person -> person.getAge() > 30).collect(Collectors.toList());// 遍历输出(输出雷军和马云)for (Person person : collect) {System.out.println(person);}System.out.println("----------");List<Person> list2 = new ArrayList<>();list2.add(new Person("马化腾",25,3000));list2.add(new Person("李彦宏",27,2545));list2.add(new Person("雷军",35,4515));list2.add(new Person("马云",55,9877));// 把姓马的人,转成Set集合Set<Person> set = list2.stream().filter(person -> person.getName().startsWith("马")).collect(Collectors.toSet());// 输出马云和马化腾set.forEach(System.out::println);}

17.迭代:iterate

可以使用Stream.iterate创建流值,即所谓的无限流。

//Stream.iterate(initial value, next value)Stream.iterate(0, n -> n + 1).limit(5).forEach(x -> System.out.println(x));

输出:

0
1
2
3
4   

18.查看:peek

peek接收的是一个Consumer函数,peek 操作会按照 Consumer 函数提供的逻辑去消费流中的每一个元素,同时有可能改变元素内部的一些属性

@Testpublic void test1(){List<String> collect = Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.println("查看一下刚过滤出的值:" + e)).map(String::toUpperCase).peek(e -> System.out.println("查看一下转大写之后的值:" + e)).collect(Collectors.toList());System.out.println("-----分割线-----");// 遍历过滤后的集合for (String s : collect) {System.out.println(s);}}

输出:

查看一下刚过滤出的值:three
查看一下转大写之后的值:THREE
查看一下刚过滤出的值:four
查看一下转大写之后的值:FOUR
-----分割线-----
THREE
FOUR

Srtream流中方法的使用练习

/*** 	1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。*	2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。*	3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。*	4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。*	5. 将两个队伍合并为一个队伍;存储到一个新集合中。*	6. 根据姓名创建 Person 对象;存储到一个新集合中。*	7. 打印整个队伍的Person对象信息。*/
public class Demo3 {public static void main(String[] args) {//第一支队伍ArrayList<String> one = new ArrayList<>();one.add("迪丽热巴");one.add("宋远桥");one.add("苏星河");one.add("石破天");one.add("石中玉");one.add("老子");one.add("庄子");one.add("洪七公");//第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。//第一个队伍筛选之后只要前3个人;存储到一个新集合中。Stream<String> stream = one.stream();Stream<String> stream1 = stream.filter(name -> name.length() == 3).limit(3);//第二支队伍ArrayList<String> two = new ArrayList<>();two.add("古力娜扎");two.add("张无忌");two.add("赵丽颖");two.add("张三丰");two.add("尼古拉斯赵四");two.add("张天爱");two.add("张二狗");//第二个队伍只要姓张的成员姓名;存储到一个新集合中。//第二个队伍筛选之后不要前2个人;存储到一个新集合中。Stream<String> stream2 = two.stream();Stream<String> stream3 = stream2.filter(name -> name.startsWith("张")).skip(2);//合并两个队伍Stream<String> concat = Stream.concat(stream1, stream3);//把合并后的队伍根据姓名创建Person对象,并存入新的集合中,然后打印concat.map(name -> new Person(name)).forEach(p -> System.out.println(p));}
}

相关文章:

Java基础:Stream流常用方法

获取Stream流的方式 java.util.stream.Stream 是Java 8新加入的流接口。&#xff08;并不是一个函数式接口&#xff09; 获取一个流非常简单&#xff0c;有以下几种常用的方式&#xff1a; 所有 Collection 集合都可通过 stream 默认方法获取流&#xff08;顺序流&#xff09;…...

ImageNet使用方法(细节)自用!

学习记录&#xff0c;自用。 1. 下载数据集 点击以下链接下载种子文件&#xff0c;然后使用迅雷进行下载&#xff0c;仅下载勾选的文件即可。 https://hyper.ai/datasets/4889/c107755f6de25ba43c190f37dd0168dbd1c0877e 2. 解压 找到下载好的ILSVRC2012_img_train.tar 和…...

C/C++外观模式解析:简化复杂子系统的高效方法

C外观模式揭秘&#xff1a;简化复杂子系统的高效方法 引言设计模式的重要性外观模式简介与应用场景外观模式在现代软件设计中的地位与价值 外观模式基本概念外观模式的定义与核心思想提供简单接口隐藏复杂子系统设计原则与外观模式的关系外观模式实现外观模式的UML图 外观模式的…...

追梦之旅【数据结构篇】——详解小白如何使用C语言实现堆数据结构

详解小白如何使用C语言实现堆数据结构 “痛”撕堆排序~&#x1f60e; 前言&#x1f64c;什么是堆&#xff1f;堆的概念及结构 堆的性质&#xff1a;堆的实现堆向下调整算法画图分析&#xff1a;堆向下调整算法源代码分享&#xff1a;向下调整建小堆向下调整建大堆 堆向上调整算…...

cocoscreator性能优化4-Sprite颜色数据去除

前言 Sprite是游戏内容的一个基本组成元素&#xff0c;包括ui、道具、立绘等各种地方都会用到。大部分情况下美术会帮我们调好图片颜色&#xff0c;我们只要把图片直接放到游戏里就行了。Sprite默认的渲染顶点数据中包含了颜色数据&#xff0c;由于我们并不需要去修改颜色&…...

系统接口幂等性设计探究

前言&#xff1a; 刚开始工作的时候写了一个带UI页面的工具&#xff0c;需要设计登录功能&#xff0c;登录功能也很简单&#xff0c;输入用户名密码点击登录&#xff0c;触发后台查询并比对密码&#xff0c;如果登录成功则返回消息给前端&#xff0c;前端把消息弹出提示一下。…...

C learning_7

目录 1.for循环 1.虽然while循环和for循环本质上都可以实现循环&#xff0c;但是它们在使用方法和场合上还是有一些区别的。 2.while循环中存在循环的三个必须条件&#xff0c;但是由于风格的问题使得三个部分很可能偏离较远&#xff0c;这样 查找修改就不够集中和方便。所以…...

PageRank算法介绍

互联网上有数百亿个网页&#xff0c;可以分为这么几类&#xff1a;不含有用信息的&#xff0c;比如垃圾邮件&#xff1b;少数人比较感兴趣的&#xff0c;但范围不是很广的&#xff0c;比如个人博客、婚礼公告或家庭像册&#xff1b;很多人感兴趣的并且十分有用的&#xff0c;比…...

springboot+vue职称评审管理系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的职称评审管理系统。项目源码请联系风歌&#xff0c;文末附上联系信息 。 目前有各类成品java毕设&#xff0c;需要请看文末联系方式 …...

腾讯云4核8G轻量服务器12M支持多少访客同时在线?并发数怎么算?

腾讯云轻量4核8G12M轻量应用服务器支持多少人同时在线&#xff1f;通用型-4核8G-180G-2000G&#xff0c;2000GB月流量&#xff0c;系统盘为180GB SSD盘&#xff0c;12M公网带宽&#xff0c;下载速度峰值为1536KB/s&#xff0c;即1.5M/秒&#xff0c;假设网站内页平均大小为60KB…...

图片英文翻译成中文转换器-中文翻译英文软件

您正在准备一份重要的英文资料或文件&#xff0c;但是您还不是很熟练地掌握英文&#xff0c;需要翻译才能完成您的任务吗&#xff1f;哪个软件能够免费把英文文档翻译成中文&#xff1f;让我们带您了解如何使用我们的翻译软件来免费翻译英文文档为中文。 我们的翻译软件是一款功…...

月薪10k和40k的程序员差距有多大?

程序员的薪资一直是大家关注的焦点&#xff0c;相较于其他行业&#xff0c;程序员的高薪也是有目共睹的&#xff0c;而不同等级的程序员处理问题的方式与他们的薪资直接挂钩。 接下来就一起看一下月薪10k、20k、30k、40k的程序员面对问题都是怎么处理的吧&#xff01; 场景一 …...

gateway整合knife4j(微服务在线文档)

文章目录 knife4j 微服务整合一、微服务与单体项目文档整合的区别二、开始整合1. 搭建一个父子maven模块的微服务,并引入gateway2.开始整合文档 总结 knife4j 微服务整合 由于单个服务的knife4j 整合之前已经写过了,那么由于效果比较好,然后微服务的项目中也想引入,所以开始微…...

ASP.NET 记录 HttpRequest HttpResponse HttpServerUtility

纯属个人记录,会有错误 HttpRequest Browser是获取客户端浏览器的信息 Cookies是获取客户端的Cookies QueryString是获取客户端提交的数据 ServerVariables是获取服务器端或客户端的环境变量信息 Browser 语法格式: Request.Browser[“浏览器特性名”] 常见的特性名 名称说…...

Python 人工智能:11~15

原文&#xff1a;Artificial Intelligence with Python 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形象&#xff0c;只关心如何…...

辉煌优配|军工板块逆市上涨,16只概念股已披露一季度业绩预喜

今日&#xff0c;军工股逆市上涨。 4月21日&#xff0c;A股三大股指低开低走&#xff0c;半导体、AI使用、信创工业、软件等科技属性概念领跌&#xff0c;国防军工、食品饮料和电力设备等板块上涨。 工业互联网中心工业规模超1.2万亿元 据央视新闻报道&#xff0c;本年是《工业…...

看板与 Scrum:有什么区别?

看板和Scrum是项目管理方法论&#xff0c;以小增量完成项目任务并强调持续改进。但是他们用来实现这些目标的过程是不同的。看板以可视化任务和连续流程为中心&#xff0c;而Scrum更多是关于为每个交付周期实施时间表和分配设定角色。 在看板和Scrum之间做出选择并不总是必要…...

零代码是什么?零代码平台适合谁用?

随着信息技术的发展&#xff0c;软件开发领域也不断发生变革&#xff0c;零代码&#xff08;No-Code&#xff09;开发模式越来越受到关注。 零代码到底是什么&#xff0c;能不能用通俗的话来说&#xff1f;这就来给大家讲一讲&#xff01; 01 零代码为什么出现&#xff1f; 随…...

CNStack 云服务云组件:打造丰富的云原生技术中台生态

作者&#xff1a;刘裕惺 CNStack 相关阅读&#xff1a; CNStack 多集群服务&#xff1a;基于OCM 打造完善的集群管理能力 CNStack 虚拟化服务&#xff1a;实现虚拟机和容器资源的共池管理 CNStack 云边协同平台&#xff1a;实现原生边缘竟能如此简单 01 前言 CNStack 2.0…...

#PythonPytorch 1.如何入门深度学习模型

我之前也写过一篇关于Keras的深度学习入门blog&#xff0c;#Python&Keras 1.如何从无到有在自己的数据集上实现深度学习模型&#xff08;入门&#xff09;&#xff0c;里面也有介绍了一下一点点机器学习的概念和理解深度学习的输入&#xff0c;如果对这方面有疑惑的朋友可以…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...

Python爬虫实战:研究Restkit库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...

深入解析 ReentrantLock:原理、公平锁与非公平锁的较量

ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...