Stream流操作

看到Stream流这个概念,我们很容易将其于IO流联系在一起,事实上,两者并没有什么关系,IO流是用于处理数据传输的,而Stream流则是用于操作集合的。

当然,为了方便我们区分,我们依旧在这里复习一下IO流的相关知识。
1.什么是IO流?
IO: output: input流:像水流一样传输数据
2.IO流的作用?
用于读写数据(本地文件,网络)存储和读取数据的解决方案
3.IO流按照流向可以分类哪两种流?
输出流:程序
输入流:文件
4.IO流按照操作文件的类型可以分类哪两种流?
字节流:可以操作所有类型的文件
字符流:只能操作纯文本文件
5.什么是纯文本文件?
用windows系统自带的记事本打开并且能读懂的文件txt文件,md文件,xml文件,lrc文件等

在学习Stream流之前,我们需要先学习Lambda表达式的用法。,这涉及到几个概念,分别是函数式编程,匿名内部类

函数式编程

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

匿名内部类

假设我们有一个接口A
内部有一个未被实现的方法eat
如果我们想在main中直接调用eat方法

Lambda表达式

Lambda该怎么用呢?其可以用在只有一个方法的接口上。

在这里插入图片描述
在这里插入图片描述

Function<T, R> 是 Java 8 中的一个函数式接口,
用于表示接受一个输入参数 T,并返回一个结果 R 的函数。
Function接口中有一个抽象方法apply,用于定义函数的逻辑。
Function接口通常用于将数据进行转换、映射或者执行某种转换操作。

通过这种函数式接口,我们可以实现不同的操作。

package Lambda;import java.util.function.Function;public class Lambda1 {public static void main(String[] args) {//使用匿名内部类,直接重写接口中的方法,省去创建实现类实现接口的过程和创建实现类对象的过程。Integer i = TypeConver(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.valueOf(s);}});System.out.println(i);Integer m = TypeConver((String s) ->{return Integer.valueOf(s);});System.out.println(m);//Lambda实现字符串拼接String string = TypeConver((String str) -> {return str + "你好";});System.out.println(string);}public static <R> R TypeConver(Function<String,R> function){String str="12345";R result=function.apply(str);return result;}
}

案例4:对IntConsumer接口进行实现。

package Lambda;import java.util.function.IntConsumer;public class Lambda2 {public static void main(String[] args) {forEachArr(new IntConsumer() {@Overridepublic void accept(int value) {System.out.println(value);}});forEachArr((int value)->{System.out.println(value);});}public static void forEachArr(IntConsumer intConsumer){int[] arr={1,2,3,4,5,6,7,8};for(int i:arr){intConsumer.accept(i);}}
}

事实上,我们可以将含有匿名内部类的写法直接一键转化为Lambda表达式的形式。

在这里插入图片描述

由此可见,Lambda就是对匿名内部类的优化。

Stream流

学完了Lambda表达式,我们来看看Stream到底是如何操作集合的,尽管集合中为我们提供了大量的方法,但在Stream操作面前根本不值一提。

在这里插入图片描述
场景:获取List中元素含"州"的元素,并放入一个List集合中。Stream支持链式编程与Lamba表达式
下面首先是通过我们的一般方法来实现

 		List<String> citys=hashMap.get("江苏省");for (String c:citys){System.out.println(c);}List<String> cs1=new ArrayList<>();for(String city:citys){if(city.contains("州")){cs1.add(city);}}System.out.println(cs1);

使用Stream实现,当然,这里的forEach只是将其输出了一下,并没有将其放到一个新的List中。

 citys.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {return s.contains("州");}}).forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});

通过StreamLambda实现:

List<String> cs2=citys.stream().filter(s->s.contains("州")).collect(Collectors.toList());

Stream的流操作涉及三个过程,分别是流创建,中间操作以及结束操作,如果我们不启用结束操作,那么中间操作的过程也是不会执行的。

创建流

package Stream;
import java.util.*;
import java.util.stream.Stream;
public class CreateStream {public static void main(String[] args) {//列表创建StreamList list=new ArrayList<>();Collections.addAll(list, 1,2,3,4,5);Stream stream = list.stream();stream.filter(o -> {int i= (int) o;return i>=2;}).forEach(o -> System.out.print(o));//数组创建StreamInteger[] arr={1,2,3,4,5,6,7,8};Stream<Integer> stream1 = Arrays.stream(arr);Stream<Integer> stream2 = Stream.of(arr);stream1.filter(s->s>=2).forEach(s->System.out.print(s));stream2.forEach(s->{System.out.print(s);});//对于双列集合,将其转换为单列集合后再创建Stream流HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("李白",135);hashMap.put("杜甫",123);hashMap.put("白居易",234);//通过entrySet方法可以将map转换为setSet<Map.Entry<String, Integer>> entries = hashMap.entrySet();System.out.println();//set可以创建stream流Stream<Map.Entry<String, Integer>> stream3 = entries.stream();stream3.forEach(s->{System.out.println(s);});}
}

中间操作

filter操作

filter,筛选操作,我们先前已经使用过了。

map操作

map,可以对流中的元素进行计算与转换。如下,通过map操作,将原本列表中的对象转换为字符串

		list.stream().filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge()>50;}}).forEach(new Consumer<Author>() {@Overridepublic void accept(Author author) {System.out.println(author);}});

在这里插入图片描述

		list.stream().filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge()>50;}}).map(new Function<Author, String>() {@Overridepublic String apply(Author author) {return author.getName();}}).forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});

可以看到,通过map操作,将原本流中的对象转换为字符串

在这里插入图片描述

distinct操作

去除流中的重复元素。其内部是依靠Object中的equals方法来实现的,因此可能需要重写equals方法。

list.add(new Author("李白",46));
list.add(new Author("杜甫",55));
list.add(new Author("白居易",67));
list.add(new Author("白居易",67));
list.stream().distinct().forEach(author -> System.out.println(author));

在这里插入图片描述

这里推荐一个插件 Java Stream Debugger,可以方便我们对Stream进行调试。

在这里插入图片描述
在这里插入图片描述

sorted操作

sorted共有两个,分别是空参的与非空参的。其中空参的那个需要我们在类上实现Comparable接口的方法,而非空参则采用在sorted中实现排序比较。
我们先来试一下无参的sorted

ArrayList<Author> list = new ArrayList<>();list.add(new Author("李白",46));list.add(new Author("杜甫",55));list.add(new Author("白居易",67));list.add(new Author("白居易",67));list.stream().sorted().forEach(author -> System.out.println(author));

发生报错,说要让我们去实现Comparable接口
在这里插入图片描述

package Stream;import java.util.Objects;public class Author implements Comparable<Author>{private String name;private Integer age;public String getName() {return name;}public Integer getAge() {return age;}@Overridepublic int compareTo(Author o) {return this.getAge()-o.getAge();}
}

随后再次运行即可。
在这里插入图片描述
那么带参数的该怎么做呢?

		list.stream().distinct().sorted(new Comparator<Author>() {@Overridepublic int compare(Author o1, Author o2) {return o2.getAge()-o1.getAge();}}).forEach(author -> System.out.println(author));

limit操作

设置流的最大长度,超出的将被抛弃。设置排序后的前2个。

list.stream().distinct().sorted((o1, o2) -> o2.getAge()-o1.getAge()).limit(2).forEach(author -> System.out.println(author));

在这里插入图片描述

skip操作

跳过流中的前n个元素,返回后面的元素。

在这里插入图片描述

flatMap操作

先前所接触的map可以将一个对象转换为另一个对象,而flatMap可以将一个对象转换为多个对象作为流中的元素。
下面的代码是什么意思呢,事实上,他是将原本的Author中的Book提取处理,由原本一个Author变为多个Book

authors.stream().distinct().map(author -> author.getBooks()).forEach(books -> System.out.println(books));

在这里插入图片描述

 		authors.stream().distinct().flatMap(new Function<Author, Stream<Books>>() {@Overridepublic Stream<Books> apply(Author author) {return author.getBooks().stream();}}).forEach(new Consumer<Books>() {@Overridepublic void accept(Books books) {System.out.println(books);}});

其对应的lambda表达式的写法:

authors.stream().distinct().flatMap(author -> author.getBooks().stream()).forEach( books -> System.out.println(books));

在这里插入图片描述

接下来我们再通过一个案例来看看flatMap的作用,我们的书籍类中有一个类别属性,其属性内含有多个值,我们是这样定义的:

在这里插入图片描述

我们希望这个类别值能够按",”分开,因此也使用flatMap实现:

		List<Author> authors=getAuthors();authors.stream().distinct().flatMap(new Function<Author, Stream<Books>>() {@Overridepublic Stream<Books> apply(Author author) {return author.getBooks().stream();}}).distinct().flatMap(new Function<Books, Stream<String>>() {@Overridepublic Stream<String> apply(Books books) {return Arrays.stream(books.getCategory().split(","));}}).forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});

对应的Lambda表达式如下:

 authors.stream().distinct().flatMap( author -> author.getBooks().stream()).distinct().flatMap( books -> Arrays.stream(books.getCategory().split(","))).forEach((Consumer<String>) s -> System.out.println(s));

在这里插入图片描述

终结操作

forEach操作

这个用于遍历输出流中的元素,前面我们已经用过多次了。

count操作

用于计算流中元素的数量,注意要删除重复元素。
统计这些作者发表的书籍的数目。

		ArrayList<Author> authors = getAuthors();authors.stream().flatMap( author -> author.getBooks().stream()).distinct().forEach(books -> System.out.println(books));long count = authors.stream().flatMap( author -> author.getBooks().stream()).distinct().count();System.out.println(count);

在这里插入图片描述

min与max操作

		ArrayList<Author> authors = getAuthors();Optional<Integer> max = authors.stream().flatMap(author -> author.getBooks().stream()).distinct().map(new Function<Books, Integer>() {@Overridepublic Integer apply(Books books) {return books.getPrice();}}).max(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o1 - o2;}});System.out.println(max.get());

对应的Lambda表达式写法:

  		ArrayList<Author> authors = getAuthors();Optional<Integer> max = authors.stream().flatMap(author -> author.getBooks().stream()).distinct().map(books -> books.getPrice()).max((o1, o2) -> o1 - o2);System.out.println(max.get());

在这里插入图片描述

collect操作

将流中的元素转换为集合。集合分为三种,分别是ListSet以及Map
需求:获取所有作者名字的集合
collect转换为List集合,如下:

 		ArrayList<Author> authors = getAuthors();List<String> collect = authors.stream().map(new Function<Author, String>() {@Overridepublic String apply(Author author) {return author.getName();}}).distinct().collect(Collectors.toList());//我们不调用对象去写匿名方法,而是直接调用Collectors这个工具类System.out.println(collect);

转换为Set的方式很类似,如下:

		Set<String> collect1 = authors.stream().map(new Function<Author, String>() {@Overridepublic String apply(Author author) {return author.getName();}}).distinct().collect(Collectors.toSet());System.out.println(collect1);

其对应的Lambda表达式如下:

		ArrayList<Author> authors = getAuthors();List<String> collect = authors.stream().map(author -> author.getName()).distinct().collect(Collectors.toList());//我们不调用对象去写匿名方法,而是直接调用Collectors这个工具类System.out.println(collect);Set<String> collect1 = authors.stream().map(author -> author.getName()).distinct().collect(Collectors.toSet());System.out.println(collect1);

转换为Map,需要指定两个参数,分别是Key与Value,内部匿名方法实现如下:

		Map<String, List<Books>> collect2 = authors.stream().distinct().collect(Collectors.toMap(new Function<Author, String>() {@Overridepublic String apply(Author author) {return author.getName();}}, new Function<Author, List<Books>>() {@Overridepublic List<Books> apply(Author author) {return author.getBooks();}}));System.out.println(collect2);

对应的Labmbda表达式如下:

		Map<String, List<Books>> collect2 = authors.stream().distinct().collect(Collectors.toMap( author -> author.getName(), author -> {return author.getBooks();}));System.out.println(collect2);

在这里插入图片描述

anyMatch操作

该操作用于进行查找与匹配,其返回值为Boolean,如下面判断是否有作家年龄在80岁以上:

		boolean b = authors.stream().anyMatch(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge() > 80;}});System.out.println(b);

对应的Lambda表达式:

boolean b = authors.stream().anyMatch(author -> author.getAge() > 80);

allMatch操作

所有流元素是否满足条件,若满足则返回True,否则为False。判断所有作家是否都大于30岁。

		ArrayList<Author> authors = getAuthors();boolean b = authors.stream().allMatch(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge() > 30;}});System.out.println(b);

findAny操作

findAny的返回值是Optional对象,返回值是其中一个流元素,即任意一个流元素,他可以调用ifPresent方法,即判断结果为否存在。

		ArrayList<Author> authors = getAuthors();Optional<Author> any = authors.stream().filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge() > 16;}}).findAny();any.ifPresent(new Consumer<Author>() {@Overridepublic void accept(Author author) {System.out.println(author);}});

Lambda表达式写法。

		ArrayList<Author> authors = getAuthors();Optional<Author> any = authors.stream().filter(author -> author.getAge() > 16).findAny();any.ifPresent(author -> System.out.println(author));

在这里插入图片描述

findFirst操作

findFirst返回查询的第一个结果。

	ArrayList<Author> authors = getAuthors();Optional<Author> first = authors.stream().sorted().distinct().findFirst();System.out.println(first);

在这里插入图片描述

reduce操作

归并操作,reduce的作用是把stream中的元素给组合起来,按照指定方式得出一个结果,故又被称为缩减操作。reduce的作用是把stream中的元素给组合起来,我们可以传入一个初始值,它会按照我们的计算方式依次拿流中的元素和初始化值进行计算,计算结果再和后面的元素计算。
下面的代码即reduce的原理,可以看到,我们所需的值,一个是初始化值,另一个便是遍历的值了。

在这里插入图片描述

在使用reduce时,一般情况下都需要在前面加一个map用于转换,这在谷歌中十分常用。
计算作家的年龄之和:

		ArrayList<Author> authors = getAuthors();Integer reduce = authors.stream().distinct().map(new Function<Author, Integer>() {@Overridepublic Integer apply(Author author) {return author.getAge();}}).reduce(0, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer result, Integer element) {return result + element;}});System.out.println(reduce);

对应的Lambda表达式:

Integer reduce1 = authors.stream().distinct().map(author -> author.getAge()).reduce(0, (result, element) -> result + element);

利用reduce求流元素中的最大值:其实我们max也可求出,事实上,max的实现就是reduce。通过指定的初始值为一个最小的int类型,此时第一次max的值即为Integer.MIN_VALUE,随后通过三目运算求出即可。

 		ArrayList<Author> authors = getAuthors();Integer reduce = authors.stream().map(author -> author.getAge()).reduce(Integer.MIN_VALUE, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer max, Integer element) {return max > element ? max : element;}});System.out.println(reduce);

对应的Lambda表达式:

Integer reduce1 = authors.stream().map(author -> author.getAge()).reduce(Integer.MIN_VALUE, (max, element) -> max > element ? max : element);

上面的reduce方法中需要传递两个参数,分别是初始值以及BinaryOperator(一种操作对象)事实上,reduce还有其他形式,比如不指定初始值的情况,其计算原理如下:可以看到,它是将流元素中的第一个值赋值给初始值。
在这里插入图片描述

那么了解了这一种reduce的计算原理后,我们先前的计算最值似乎更简单了。
即无需指定初始值,直接计算即可。需要注意的是,其最终的返回值被封装为Optional,所以要调用get方法来获取值。

ArrayList<Author> authors = getAuthors();Optional<Integer> reduce = authors.stream().map(author -> author.getAge()).reduce(new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer result, Integer element) {return result > element ? result : element;}});System.out.println(reduce.get());

如果不调用get方法,reduce的值为:

在这里插入图片描述

Stream注意事项

  • 惰性求值(如果没有终结操作,没有中间操作是不会得到执行的)
  • 流是一次性的(一旦一个流对象经过一个终结操作后。这个流就不能再被使用)
  • 不会影响原数据(我们在流中可以多数据做很多处理。但是正常情况下是不会影响原来集合中的元素的。这往往也是我们期望的)正常情况下,只要你不调用set方法之类的。

比如下面我们已经将流使用过一次终结操作了,那么再次使用时便会报错:

ArrayList<Author> authors = getAuthors();Stream<Author> stream = authors.stream();stream.map(author -> author.getAge()).reduce((result, element) -> result > element ? result : element);stream.map(author -> author.getAge()).reduce((result, element) -> result > element ? result : element);
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closedat java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203)at java.util.stream.ReferencePipeline.<init>(ReferencePipeline.java:94)at java.util.stream.ReferencePipeline$StatelessOp.<init>(ReferencePipeline.java:618)at java.util.stream.ReferencePipeline$3.<init>(ReferencePipeline.java:187)at java.util.stream.ReferencePipeline.map(ReferencePipeline.java:186)at Stream.Test4.main(Test4.java:18)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/6726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

长期找 AI 专家,邀请参加线上聊天直播

诚邀 AI 专家参加线上聊天&#xff0c;成为嘉宾。 分享前沿观点、探讨科技和生活 除节假日外&#xff0c;每周举办在线聊天直播 根据话题和自愿形式结合&#xff0c;每期 2~3 位嘉宾 成为嘉宾&#xff0c;见下&#xff1a;

ADS软件(PathWave 先进设计系统软件)分享与安装

ADS软件的简介 ADS软件&#xff08;Advanced Design System&#xff09;主要用于射频&#xff08;RF&#xff09;、微波&#xff08;Microwave&#xff09;和毫米波&#xff08;Millimeter-wave&#xff09;电路的设计、仿真和分析。它提供了一套强大的工具和功能&#xff0c;…

Angular进阶-NVM管理Node.js实现不同版本Angular环境切换

一、NVM介绍 1. NVM简介 Node Version Manager&#xff08;NVM&#xff09;是一个用于管理多个Node.js版本的工具。它允许用户在同一台机器上安装和使用多个Node.js版本&#xff0c;非常适合需要同时进行多个项目的开发者。NVM是开源的&#xff0c;支持MacOS、Windows和Linux…

【解决】docker一键部署报错

项目场景见&#xff1a;【记录】Springboot项目集成docker实现一键部署-CSDN博客 问题&#xff1a; 1.docker images 有tag为none的镜像存在。 2.有同事反馈&#xff0c;第一次启动docker-compose up -d 项目无法正常启动。后续正常。 原因&#xff1a; 1.服务中指定了镜像m…

Jackson-jr 对比 Jackson

关于Jackson-jr 对比 Jackson 的内容&#xff0c;有人在做了一张下面的图。 简单点来说就 Jackson-jr 是Jackson 的轻量级应用&#xff0c;因为我们在很多时候都用不到 Jackson 的很多复杂功能。 对很多应用来说&#xff0c;我们可能只需要使用简单的 JSON 读写即可。 如我们…

【Linux网络】网络文件共享

目录 一、存储类型 二、FTP文件传输协议 2.1 FTP工作原理 2.2 FTP用户类型 2.3 FTP软件使用 2.3.1 服务端软件vsftpd 2.3.2 客户端软件ftp 2.4 FTP的应用 2.4.1 修改端口号 2.4.2 匿名用户的权限 2.4.3 传输速率 三、NFS 3.1 工作原理 3.2 NFS软件介绍 3.3 NFS配…

企业级数据治理学习总结

1. 水在前面 “数据治理”绝对是吹过的牛里面最高大上的题目了&#xff0c;本来想直接以《企业级数据治理》为题来水的&#xff0c;码字前又跑去图书馆借了几本书&#xff0c;翻了几页才发现自己连半桶水都提不起&#xff0c;撑死只能在小屁孩跟前吹吹牛。 好吧&#xff0c;实在…

怎么把jpg图片变成gif?参考这个方法一键制作

Jpg图片如何变成gif图片&#xff1f;Jpg、gif都是最常用的图片格式&#xff0c;想要将这两种格式的图片互相转化的时候要怎么操作呢&#xff1f;想要将jpg图片变成gif方法很简单&#xff0c;只需要使用gif图片制作&#xff08;https://www.gif5.net/&#xff09;工具-GIF5工具网…

华为手机ip地址怎么切换

随着移动互联网的普及&#xff0c;IP地址成为了我们手机上网的重要标识。然而&#xff0c;在某些情况下&#xff0c;我们可能需要切换手机的IP地址&#xff0c;以更好地保护个人隐私、访问特定地区的内容或服务&#xff0c;或者出于其他网络需求。华为手机作为市场上的热门品牌…

用队列实现栈——leetcode刷题

题目的要求是用两个队列实现栈&#xff0c;首先我们要考虑队列的特点&#xff1a;先入先出&#xff0c;栈的特点&#xff1a;后入先出&#xff0c;所以我们的目标就是如何让先入栈的成员后出栈&#xff0c;后入栈的成员先出栈。 因为有两个队列&#xff0c;于是我们可以这样想&…

vue3(实现上下无限来往滚动)

一、问题描述 一般在大屏项目中&#xff0c;很常见的效果&#xff0c;就是容器中的内容缓慢地向下移动&#xff0c;直到底部停止&#xff0c;然后快速滚动回顶部&#xff0c;然后接着缓慢滚动到底部。并且在特定的情况下&#xff0c;还需要进行一些小交互&#xff0c;那就还得让…

Leetcode——面试题02.04.分割链表

面试题 02.04. 分割链表 - 力扣&#xff08;LeetCode&#xff09; 对于该链表OJ&#xff0c;我们两种大的方向&#xff1a; 1.在原链表上修改&#xff1b;2.创建新链表&#xff0c;遍历原链表。 在原链上进行修改&#xff1a;如果该节点的val小于x则继续往后走&#xff0c;如…

Ubuntu服务器创建新用户及解决新用户登录Access denied问题

目录 Ubuntu服务器创建新用户及解决新用户登录Access denied问题创建账号步骤创建用户只创建用户添加用户到sudo组 允许账号远程连接重启ssh服务 删除账号要删除用户而不删除用户文件如果要删除并且删除用户的家目录和邮件 查询指令查看所有用户查询特定用户账户信息查看用户组…

【Micropython Pitaya Lite教程】key按键与EXTI中断

文章目录 前言一、按键的使用1.1 按键的简介1.2 读取按键的高低电平 二、EXIT外部中断2.1 EXIT外部中断简介2.2 外部中断基础知识2.3 设置外部中断2.4 示例代码 总结 前言 Micropython Pitaya Lite开发板提供了丰富的功能和灵活的扩展性&#xff0c;其中包括了按键&#xff08…

Python 全栈系列241 GFGo Lite迭代

说明 随着整个算网开发逐渐深入&#xff0c;各个组件、微服务的数量、深度在不断增加。由于算网是个人项目&#xff0c;我一直按照MVP(Minimum Viable Product )的原则在推进。由于最初的时候对架构、算法和业务的理解并没有那么深刻&#xff0c;所以MVP的内容还是在不断变化&…

IoTDB 入门教程 基础篇①——时序数据库为什么选IoTDB ?

文章目录 一、前文二、性能排行第一三、完全开源四、数据文件TsFile五、乱序数据高写入六、其他七、参考 一、前文 IoTDB入门教程——导读 关注博主的同学都知道&#xff0c;博主在物联网领域深耕多年。 时序数据库&#xff0c;博主已经用过很多&#xff0c;从最早的InfluxDB&a…

Linux基础之yum和vim

目录 一、软件包管理器yum 1.1 软件包的概念 1.2 软件包的查看 1.3 软件包的安装和删除 二、Linux编辑器之vim 2.1 vim的基本概念 2.2 正常模式&#xff08;命令模式&#xff09; 2.3 底行模式 2.4 输入模式 2.5 替换模式 2.6 视图模式 2.7 总结 一、软件包管理器yu…

MATLAB可视化图形绘制详解

图形常见的修饰命令 ①曲线修饰 曲线修饰包括曲线的顔色、线型和标示符号的设置。曲线修饰的命令格式如下。 plot(x,y,option):option定义了曲线的颜色、线型和标示符号。 MATLAB曲线修饰的各种选项见表 举例&#xff1a; x-2*pi:pi/50:2*pi; y1x.^2;y2cos(2*X);y3y1.*y2…

【Python项目】基于DJANGO的【基于语音识别的智能垃圾分类系统】

技术简介&#xff1a;使用Python技术、DJANGO框架、MYSQL数据库等实现。 系统简介&#xff1a;用户们可以在系统上面录入自己的个人信息&#xff0c;录入后还可以对信息进行修改&#xff0c;网站可以对用户上传的音频文件进行识别&#xff0c;然后进行垃圾分类。 背景&#xf…

【竞技宝jjb.lol】LOL:TES顺利晋级却暴露问题

北京时间2024年5月5日,英雄联盟2024MSI季中赛正在如火如荼的进行之中,目前入围赛阶段的比赛已经进入尾声,入围赛实力最强的两支战队T1、TES都已经顺利晋级淘汰赛阶段,在昨天的比赛结束之后,A组的FLY、PSG,B组的FNC、GAM将争夺剩下的两个出线名额。 回顾这次入围赛中,T1和TES的比…