流
流思维导图
方法
操作方法
list.stream().filter()
list.stream().filter()
是使用 Java 8 引入的 Stream API 对 List 进行过滤操作的语法。
list
是一个 List 对象,
.stream()
方法将其转换为一个流(Stream)(注意所有的集合都可以转化为一个流)
下面是一个简单的示例,展示了如何使用 .filter()
方法对 List 进行过滤操作:
list
.stream()
.filter(name->name.startsWith("h"))//.filter(name->name.length()==4)
.forEach(e-> System.out.println(e));
filter()方法只会过滤出Predicate返回值为TRUE的值,通过predicate函数式接口,定义传入参数和判断逻辑,以用来判断过滤条件
stream().map( Function )
map方法通常用于将一个流中的元素映射为另一个流中的元素,即对流中的每个元素应用一个函数,将其转换为另一个元素。
List<String> words = Arrays.asList("Hello", "World");
List<String> uniqueLetters = words.stream()
.flatMap(word -> Arrays.stream(word.split("")))
.distinct()
.collect(Collectors.toList());
System.out.println(uniqueLetters); // Output: [H, e, l, o, W, r, d]
//map()的两个作用
//转化数据类型
Stream<String> stringStream = Stream.of("1","2","3");
Stream<Integer> integerStream = stringStream.map(Integer::valueOf);
//数据过滤后的数据处理
//业务场景:过滤出整数流的偶数并且乘上2
Stream<Integer> newStream = Stream.of(1,2,3,4,5);
System.out.println(newStream.filter(m -> m % 2 == 0).map(n -> n * 2).collect(Collectors.toList()));
Sorted
使用sorted
方法可以对流中的元素进行排序。它接受一个可选的Comparator
比较器作为参数,用于指定元素的排序规则。
Distinct
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 3, 2, 1);
List<Integer> uniqueNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
使用distinct
方法可以去除流中的重复元素,只保留唯一的元素。
终端方法
stream().collect(Collectors.toList())
collect
方法接受返回值(通常转化为列表)
异步处理方法
顺序流和平行流
顺序流(Sequential Stream)是默认的流类型,在顺序流中,操作是按照顺序(流的开始到结束)依次应用于每个元素的。顺序流适用于单线程环境,每个操作都在前一个操作完成后依次执行。
平行流(Parallel Stream)是流的另一种类型,它可以将操作并行执行,将流中的元素划分为多个部分,并利用多个线程同时处理这些部分。平行流适用于多核处理器或需要处理大量数据的情况,可以显著提高处理速度。最后将多段数据进行合并(合并数据是很快的,但是顺序处理数据是很慢的。)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = numbers.stream()
.map(n -> n * 2)
.filter(n -> n % 3 == 0)
.collect(Collectors.toList());
平行流的转化只需调用流中的parallel()方法
List<Integer> result = numbers.stream()
.parallel() // 将顺序流转换为平行流
.map(n -> n * 2)
.filter(n -> n % 3 == 0)
.collect(Collectors.toList());
流(统一处理各类型的数据流的输入输出操作的抽象的数据处理方法)
在Java中,流(Stream)是一种用于处理输入和输出操作的抽象概念。它提供了一种统一的方式来处理各种类型的数据流,无论是从文件、网络连接还是其他数据源。流提供了丰富的方法和操作,使得数据的处理更加简洁、灵活和高效。
输入流用于从数据源读取数据,输出流用于将数据写入到目标位置。流的处理通常是按照顺序一次性处理数据的一部分,而不是一次性将整个数据加载到内存中。
流的特性
- 抽象和统一:流提供了一种抽象和统一的方式来处理输入和输出操作。不论数据来自于文件、网络还是其他数据源,都可以使用相同的方式进行处理。
- 高效和延迟处理:流的处理是按需进行的,只有在需要时才会读取或写入数据,这样可以节省内存资源并提高处理效率。流还支持延迟处理,可以将多个操作组合起来,一次性进行处理,减少中间过程的数据存储和交互。
- 方法丰富:Java流提供了丰富的方法和操作,如过滤、映射、排序、聚合等,可以灵活地对数据进行处理和转换。这些方法可以通过链式调用,使代码更加简洁和可读。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class StreamExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
// 从文件中读取数据并使用流进行处理
reader.lines()
.filter(line -> line.contains("Java"))
.map(String::toUpperCase)
.forEach(System.out::println);
//我们使用流的方法链来对数据进行处理:首先使用filter方法过滤出包含"Java"的行,然后使用map方法将行转换为大写,最后使用forEach方法打印处理后的行。
} catch (IOException e) {
e.printStackTrace();
}
}
}
流的定义
网络流:网络传输
文件流:读写文件
字节流:二进制数据
字符流:文本数据
不同数据类型的输入和输出流
- 字节流(Byte Streams):
InputStream
和OutputStream
是字节流的抽象基类。它们用于读取和写入字节数据。FileInputStream
和FileOutputStream
用于读取和写入文件中的字节数据。ByteArrayInputStream
和ByteArrayOutputStream
用于读取和写入字节数组中的数据。BufferedInputStream
和BufferedOutputStream
提供了缓冲功能,可以提高读写效率。
- 字符流(Character Streams):
Reader
和Writer
是字符流的抽象基类。它们用于读取和写入字符数据。FileReader
和FileWriter
用于读取和写入文件中的字符数据。BufferedReader
和BufferedWriter
提供了缓冲功能和更高效的字符处理。
- 基本数据类型流:
DataInputStream
和DataOutputStream
用于读取和写入基本数据类型(如int、double、boolean等)的数据。ObjectInputStream
和ObjectOutputStream
用于读取和写入Java对象。
- 字符串流:
StringReader
和StringWriter
用于读取和写入字符串数据。
- 压缩流:
ZipInputStream
和ZipOutputStream
用于读取和写入压缩文件。GZIPInputStream
和GZIPOutputStream
用于读取和写入GZIP格式的压缩文件。
- 网络流:
Socket
和ServerSocket
用于在网络上进行数据通信。SocketInputStream
和SocketOutputStream
用于读取和写入网络流。
流的学习框架
序列化
涉及到接口java.io.Serializable
(Serializable:可序列化的)。Serializable是一个标记接口,无需实现任何方法,只是标记了该类的对象可以被序列化。
定义
序列化是指将对象转换为字节流的过程,以便在网络上传输或持久化到磁盘中。反序列化则是将字节流转换回对象的过程。字符在网络中流动中是明文,很容易被解析,是不安全的,所以需要被序列化。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6PhyaCD-1686149133542)(./d9feafe3b388487c896126c4724a9c57.png)]
不安全传输的解决方法
- 使用加密传输:通过使用安全套接层(SSL)或传输层安全(TLS)等加密协议,对数据进行加密传输。这可以防止窃听者获取敏感数据。
- 数字签名和证书验证:使用数字签名和证书验证来确保通信的完整性和身份验证。发送方可以使用私钥对数据进行签名,接收方使用发送方的公钥来验证签名的有效性。证书验证可以确保通信双方的身份。
- 身份验证和授权:要求通信双方进行身份验证,确保只有授权的用户或设备可以进行通信。可以使用用户名和密码、令牌、双因素认证等方式进行身份验证,并基于角色或权限进行授权。
- 防止重放攻击:在传输过程中,防止恶意用户重复发送已经被捕获的通信数据,可以使用一次性令牌、时间戳或随机数等方式来防止重放攻击。
- 数据完整性校验:通过使用消息摘要算法(如SHA-256)对数据进行哈希计算,发送方将计算得到的摘要附加到数据中,接收方收到数据后重新计算摘要并与接收到的摘要进行比对,以确保数据的完整性。
随机读写流
定义:支持在文件的任意位置进行读写操作的流。可以利用随机读写流进行数据切割。
数据切割
public static void splitFile(int chunkSize,String filePath) throws IOException{
//读取文件
FileReader fr = new FileReader(filePath);
BufferedReader br = new BufferedReader(fr);
//切割文件
char[] buffer = new char[chunkSize];
int count = 0;
// br.read(buffer) 从输入流中读取一定字符数并且存储在buffer数组中,同时也会返回实际读取的字符数
while(-1 != (count = br.read(buffer))){
FileWriter fw = new FileWriter(filePath + "." + count);
//通过字符串拼接构造一个包含文件路径和数据块大小的文件名,并将count大小的数据块存储到文件之中
BufferedWriter bw = new BufferedWriter(fw);
bw.write(buffer,0,count);
bw.close();
}
fr.close();
br.close();
}
如何实现字节/字符流的数据切割?
先将数据块切分为长度为chunkSize的数据块(字符数组)
chunkSize的大小要根据实际的业务进行确定。
读取输入流中的数据,存入数据块中,并且返回实际读取的数据大小。
while(-1 != (count = br.read(buffer)))
根据获取的数据大小,将buffer中的数据写入输出流(自定义输出流的路径:文件路径 + 数据块大小)
数据切割的作用
- 提高传输效率
- 避免内存溢出
- 支持断点续传:对每个数据块都是单独进行传输的,如果出现网络中断的情况,出错时只需单独处理中断的数据块即可。
“读取是输入,写入是输出”
将数据的流动比作水流,从外部获取数据(例如文件、网络等)并将其引入到程序中时,我们将数据视为流入程序,因此称之为输入。相反,当程序将数据发送到外部(例如写入文件、发送网络请求等),我们将数据视为流出程序,因此称之为输出。
协议
等级 | 协议名称 | 协议特性 |
---|---|---|
底层 | IP (Internet Protocol)互联网协议 |
1.定义数据包的格式(数据包像信一样,都需要有固定的格式)(存放数据格式:从哪个字节到哪个字节存放的是数据的长度,数据的内容,双方的地址,端口号…),分割、标识数据包,确定传输路径2.所有网络传输都基于IP |
底层 | TCP协议/UDP协议 (Transmission Control Protocol/User Datagram Protocol) 传输控制协议/用户包协议 |
1.TCP面向连接(常连接),UDP无连接(用户的两台电脑自成客户端)2.TCP可靠 UDP快速3.TCP用于文件传输,电子邮件;UDP用于实时视频,音频(用户之间) |
底层 | HTTP协议(S) (Hypertext Transfer Protocol)超文本传输协议 |
1.对TTP协议的一种包装,面向web。2.无状态:基于单次请求给单次反馈,不需要常连接,反馈完连接就断开了。 |
底层 | SMTP (Simple Mail Transfer Protocol)简单邮件传输协议 |
面向邮箱 上班用邮件 |
高级 | FTP (File Transfer Protocol) 文件传输协议 |
文件传输 数据传到hadoop |
以QQ为例
QQ中既有TCP/UDP,聊天是通过UDP协议,登陆状态的维持/文件的传输是通过TCP协议,实际上没有办法有那么强大的服务器能够支撑数十亿人口并发量,因此,实际上,在聊天的过程中将用户的两台电脑自己互相作为客户端即可,也就是说这方面并不需要我控制。有限的资源就投入到登录和文件传输上面,因为聊天丢几帧影响也不大。
TCP/UDP 与 IP
IP负责将数据包从源主机传递到目标主机,TCP/UDP负责将数据打包成数据包,并在不同主机之间建立连接与传输。
TCP/UDP打包好了货物,搭好了桥,IP是邮递员负责将打包好的货物记录好信息,处理好,进行派送。
流计算与分布式计算的区别
流计算:用本机cpu和本地的磁盘,将磁盘的文件调到内存中,并用cpu进行计算
分布式计算:将一个计算任务分成子任务,并交给多台计算机并行计算,每台计算机都有自己的计算资源和存储资源,最后合并计算结果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-muZv3LkW-1686149133543)(./分布式计算.png)]流在分布式计算中的应用:利用网络流、字节流和文件流,将数据拷贝到远程的集群中。
网络流,字节流,文件流将任何一台机器的数据传输到网络能够到达的机器上去。
字节流主要面向文件拷贝,文件拷贝可以是群拷贝也可以是单独拷贝。
流操作的命名
字符输入节点流(不同类型主体(网络流/字符流/字节流/文件流)+输入/输出流+是否直接面向数据源(节点流/处理流))