流知识超详细总结!一文搞懂!

  • Post author:
  • Post category:其他







流思维导图

在这里插入图片描述



方法


操作方法


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)是一种用于

处理输入和输出操作



抽象

概念。它提供了一种

统一

的方式来处理

各种类型的数据流

,无论是从

文件、网络连接还是其他数据源

。流提供了丰富的方法和操作,使得数据的处理更加简洁、灵活和高效。


输入流用于从数据源读取数据,输出流用于将数据写入到目标位置。

流的处理通常是

按照顺序一次性处理数据的一部分

,而不是一次性将整个数据加载到内存中。



流的特性
  1. 抽象和统一:流提供了一种抽象和统一的方式来处理输入和输出操作。不论数据来自于文件、网络还是其他数据源,都可以使用相同的方式进行处理。
  2. 高效和延迟处理:流的处理是

    按需进行

    的,只有在需要时才会读取或写入数据,这样可以节省内存资源并提高处理效率。流还支持

    延迟处理

    ,可以将

    多个操作组合起来

    ,一次性进行处理,减少中间过程的数据存储和交互。
  3. 方法丰富: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();
        }
    }
}



流的定义

网络流:网络传输

文件流:读写文件

字节流:二进制数据

字符流:文本数据



不同数据类型的输入和输出流
  1. 字节流(Byte Streams):


    • InputStream



      OutputStream

      是字节流的抽象基类。它们用于读取和写入字节数据。

    • FileInputStream



      FileOutputStream

      用于读取和写入文件中的字节数据。

    • ByteArrayInputStream



      ByteArrayOutputStream

      用于读取和写入字节数组中的数据。

    • BufferedInputStream



      BufferedOutputStream

      提供了缓冲功能,可以提高读写效率。
  2. 字符流(Character Streams):


    • Reader



      Writer

      是字符流的抽象基类。它们用于读取和写入字符数据。

    • FileReader



      FileWriter

      用于读取和写入文件中的字符数据。

    • BufferedReader



      BufferedWriter

      提供了缓冲功能和更高效的字符处理。
  3. 基本数据类型流:


    • DataInputStream



      DataOutputStream

      用于读取和写入基本数据类型(如int、double、boolean等)的数据。

    • ObjectInputStream



      ObjectOutputStream

      用于读取和写入Java对象。
  4. 字符串流:


    • StringReader



      StringWriter

      用于读取和写入字符串数据。
  5. 压缩流:


    • ZipInputStream



      ZipOutputStream

      用于读取和写入压缩文件。

    • GZIPInputStream



      GZIPOutputStream

      用于读取和写入GZIP格式的压缩文件。
  6. 网络流:


    • Socket



      ServerSocket

      用于在网络上进行数据通信。

    • SocketInputStream



      SocketOutputStream

      用于读取和写入网络流。


流的学习框架


序列化

涉及到接口

java.io.Serializable

(Serializable:可序列化的)。Serializable是一个标记接口,无需实现任何方法,只是标记了该类的对象可以被序列化。



定义

序列化是指将

对象转换为字节流

的过程,以便

在网络上传输或持久化到磁盘

中。反序列化则是将字节流转换回对象的过程。字符在网络中流动中是明文,很容易被解析,是不安全的,所以需要被序列化。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6PhyaCD-1686149133542)(./d9feafe3b388487c896126c4724a9c57.png)]



不安全传输的解决方法
  1. 使用加密传输:通过使用安全套接层(SSL)或传输层安全(TLS)等

    加密协议

    ,对数据进行加密传输。这可以防止窃听者获取敏感数据。
  2. 数字签名和证书验证:使用数字签名和证书验证来确保通信的完整性和身份验证。发送方可以使用

    私钥对数据进行签名

    ,接收方使用发送方的

    公钥来验证签名的有效性

    。证书验证可以确保通信双方的身份。
  3. 身份验证和授权:要求通信双方进行身份验证,确保只有授权的用户或设备可以进行通信。可以使用

    用户名和密码、令牌、双因素认证等方式进行身份验证

    ,并基于角色或权限进行授权。
  4. 防止重放攻击:在传输过程中,防止恶意用户重复发送已经被捕获的通信数据,可以使用

    一次性令牌、时间戳或随机数

    等方式来防止重放攻击。
  5. 数据完整性校验:通过使用消息摘要算法(如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();
    }

如何实现字节/字符流的数据切割?

  1. 先将数据块切分为长度为chunkSize的数据块(字符数组)

    chunkSize的大小要根据实际的业务进行确定。

  2. 读取输入流中的数据,存入数据块中,并且返回实际读取的数据大小。

    while(-1 != (count = br.read(buffer)))
    
  3. 根据获取的数据大小,将buffer中的数据写入输出流(自定义输出流的路径:文件路径 + 数据块大小)

数据切割的作用

  1. 提高传输效率
  2. 避免内存溢出
  3. 支持断点续传:对每个数据块都是单独进行传输的,如果出现网络中断的情况,出错时只需单独处理中断的数据块即可。


“读取是输入,写入是输出”

将数据的流动比作水流,从外部获取数据(例如文件、网络等)并将其引入到程序中时,我们将数据视为流入程序,因此称之为输入。相反,当程序将数据发送到外部(例如写入文件、发送网络请求等),我们将数据视为流出程序,因此称之为输出。



协议

等级 协议名称 协议特性
底层
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)]流在分布式计算中的应用:利用网络流、字节流和文件流,将数据拷贝到远程的集群中。


网络流,字节流,文件流

将任何一台机器的数据传输到网络能够到达的机器上去。

字节流主要面向文件拷贝,文件拷贝可以是群拷贝也可以是单独拷贝。



流操作的命名

字符输入节点流(不同类型主体(网络流/字符流/字节流/文件流)+输入/输出流+是否直接面向数据源(节点流/处理流))



版权声明:本文为m0_74120525原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。