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;

小程序端的懂车帝二手车数据采集

import datetime import random import string import time import pymysql import requests import json def mysql_sql(conn, cur): """创建一个存储数据表和一个存储链接表""" cur.execute( CREATE TABLE if not exists dcd_x…

AcWing 851:spfa求最短路 ← 链式前向星存图

【题目来源】https://www.acwing.com/problem/content/853/【题目描述】 给定一个 n 个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c; 边权可能为负数。 请你求出 1 号点到 n 号点的最短距离&#xff0c;如果无法从 1 号点走到 n 号点&#xff0c;则输出 i…

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

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

【STM32项目】基于STM32多传感器融合的新型智能导盲杖设计(完整工程资料源码)

基于STM32多传感器融合的新型智能导盲杖设计演示效果 基于stm32智能盲杖 前言: 目前,中国盲人数量已突破两千万大关,而城市盲道设计不合理、盲道被非法侵占等危害盲人出行安全的问题屡禁不止[1-3]。随着科技发展,智能盲杖不断涌现,但这些智能盲杖并不智能[4,5]。针对市售…

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…

laravel、tp等框架底层代码config方法实现示例

剖析php如何优雅得实现框架config方法核心代码 在php的laravel、tp框架中,普遍采用配置文件直接return数组的方式存放配置信息、日常的代码编写我们并不会这样做&#xff0c;其实核心代码很简单,只需要把include file赋值给变量即可 php if(!function_exists("config&quo…

Eclipse中开启服务,网页无法打开 运行程序显示404

一、eclipse中开启服务后&#xff0c;网页无法打开的问题 当你在eclipse中开启服务后&#xff0c;如果网页无法打开&#xff0c;可能是以下几个原因导致的&#xff1a; 1. 端口冲突&#xff1a;请确保你所使用的端口没有被其他程序占用。可以尝试更换一个未被占用的端口。 2…

【QEMU系统分析之实例篇(十四)】

系列文章目录 第十四章 QEMU系统仿真的机器创建分析实例 文章目录 系列文章目录第十四章 QEMU系统仿真的机器创建分析实例 前言一、QEMU是什么&#xff1f;二、QEMU系统仿真的机器创建分析实例1.系统仿真的命令行参数2.完成早期后端驱动的设置工作qemu_create_early_backends(…

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;或者出于其他网络需求。华为手机作为市场上的热门品牌…

开源相机管理库Aravis学习——pixel format编码规则

开源相机管理库Aravis学习——pixel format编码规则 前言前置知识PixelFormatBpp 编码规则源码分析分类标准 补充ARV_PIXEL_FORMAT_BIT_PER_PIXEL 参考文章 前言 在学习Aravis官方例程的时候&#xff0c;有这么一个函数&#xff1a;arv_camera_get_pixel_format&#xff0c;它…

Docker安装MySQL8数据表名大小写问题

项目使用了Flowable工作流&#xff0c;导入sql时候需要MySQL忽略大小写&#xff0c;使用MySQL5.7时可以通过 在my.cnf文件中添加lower_case_table_names1实现。 [mysqld] lower_case_table_names1使用MySQL8上述方法失效&#xff0c;可以通过创建Docker容器时添加参数--lower_…

微信小程序开发中的网络请求和数据获取:从入门到实践

微信小程序开发中的网络请求和数据获取&#xff1a;从入门到实践 在微信小程序开发中&#xff0c;网络请求和数据获取是构建动态、交互式应用的关键环节。本文将深入探讨微信小程序的网络请求机制&#xff0c;并提供丰富的代码示例&#xff0c;帮助读者从零开始掌握这一重要技…

《从Paxos到Zookeeper》读书笔记

本文是对于从Paxos到Zookeeper的笔记和提纲整理 主要用于复习和知识点梳理 第一、二、三章&#xff1a;分布式基础 链接&#xff1a;《从Paxos到Zookeeper》——第一、二、三章&#xff1a;分布式基础 第一章 分布式架构 [1.1] 分布式的特点&#xff08;集中式/分布式&#xf…

C语言经典例题-12

1.杨辉三角 题目描述: KK知道什么叫杨辉三角之后对杨辉三角产生了浓厚的兴趣&#xff0c;他想知道杨辉三角的前n行&#xff0c;请编程帮他 解答。杨辉三角&#xff0c;本质上是二项式(ab)的n次方展开后各项的系数排成的三角形。其性质包括&#xff1a;每行的端点数为1&#…