Java-day18

引入

Java 中的 IO 流是数据传输的核心机制,负责实现程序与文件、网络等设备的数据交互;而 Lambda 表达式则是 Java 8 引入的函数式编程特性,彻底简化了代码编写,尤其在多线程、集合操作等场景中大放异彩。本文将先深入解析 IO 流的分类与实战用法,再系统讲解 Lambda 表达式的思想、语法与练习,帮助读者掌握这两大实用技术。

一、IO 流:数据传输的“管道”

1.1 IO 流的分类与核心概念

IO 流是 Java 中用于**数据输入/输出**的核心机制,主要分为两类:

- **字符流**:处理文本数据(如 .java、.txt 文件),基于字符编码(如 UTF-8),核心类为 Reader 和 Writer;

- **字节流**:处理二进制数据(如图片、音频文件),基于字节(8 位)传输,核心类为 InputStream 和 OutputStream。

1.2 字符流实战:文本文件的读写

(1)字符输出流 Writer 及其实现类 FileWriter

Writer 是字符输出流的抽象基类,FileWriter 用于向文件写入字符数据。

``java

package com.qcby;

import java.io.FileWriter;

import java.io.IOException;

import java.io.Writer;

public class WriterExample {

public static void main(String[] args) {

// try-with-resources 自动关闭资源

try (Writer writer = new FileWriter("output.txt")) {

// 1. 写入单个字符

writer.write('H');

// 2. 写入字符数组

char[] array = {'e', 'l', 'l', 'o'};

writer.write(array);

// 3. 写入字符数组的一部分

writer.write(array, 1, 2); // 写入 "ll"

// 4. 写入字符串

writer.write(", World!");

// 5. 写入字符串的一部分

String str = "\nThis is Java IO.";

writer.write(str, 0, 11); // 写入 "This is Java"

System.out.println("数据已写入文件!");

} catch (IOException e) {

e.printStackTrace();

}

}

}

```

(2)字符输入流 Reader 及其实现类 FileReader

Reader 是字符输入流的抽象基类,FileReader 用于从文件读取字符数据。

```java

package com.qcby;

import java.io.FileReader;

import java.io.IOException;

import java.io.Reader;

public class ReaderExample {

public static void main(String[] args) {

try (Reader reader = new FileReader("output.txt")) {

int data;

while ((data = reader.read()) != -1) {

System.out.print((char) data);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

```

1.3 字节流实战:二进制文件的读写

(1)字节输入流 InputStream 及其实现类 FileInputStream

InputStream 是字节输入流的抽象基类,FileInputStream 用于从文件读取字节数据。

```java

package com.qcby;

import java.io.FileInputStream;

import java.io.IOException;

public class FileInputStreamTest {

public static void main(String[] args) {

FileInputStream fis = null;

try {

fis = new FileInputStream("hello.txt");

byte[] buffer = new byte[5];

int len;

while ((len = fis.read(buffer)) != -1) {

System.out.print(new String(buffer, 0, len));

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (fis != null) {

try {

fis.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

```

(2)字节输出流 OutputStream 及其实现类 FileOutputStream

OutputStream 是字节输出流的抽象基类,FileOutputStream 用于向文件写入字节数据。

```java

package com.qcby;

import java.io.FileOutputStream;

import java.io.IOException;

public class FileOutputStreamTest {

public static void main(String[] args) {

FileOutputStream fos = null;

try {

fos = new FileOutputStream("hello.txt");

fos.write(97); // 写入字符 'a'(ASCII 码 97)

fos.write("中国人!\r\n".getBytes());

fos.write("ABCDEFGH".getBytes(), 2, 4); // 写入 "CDEF"

} catch (IOException e) {

e.printStackTrace();

} finally {

if (fos != null) {

try {

fos.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

```

二、Lambda 表达式:函数式编程的简化艺术

2.1 函数式编程思想概述

  • 数学中的函数:有输入量和输出量的计算方案,核心是 “对数据做操作”;
  • 面向对象编程:强调 “通过对象做事”,必须依赖类和对象的语法结构;
  • 函数式编程:忽略对象的复杂语法,强调 “做什么”,而非 “以什么形式做”,Lambda 表达式是其核心体现。

Lambda 表达式的核心价值:简化 “只有一个抽象方法的接口(函数式接口)” 的实现代码,消除冗余的匿名内部类。

2.2 体验 Lambda 表达式:多线程案例

需求:启动一个线程,在控制台输出 “多线程启动了”,对比三种实现方式。

(1)方案 1:传统实现 Runnable 接口

```java

运行

// 1. 定义实现类
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("多线程启动了");
    }
}

public class LambdaDemo {
    public static void main(String[] args) {
        // 2. 创建实现类对象
        MyRunnable myRunnable = new MyRunnable();
        // 3. 创建线程并启动
        new Thread(myRunnable).start();
    }
}

问题:代码冗余,仅为了实现一个简单的 run() 方法,需要定义完整的类。

(2)方案 2:匿名内部类改进

```java

运行

public class LambdaDemo {
    public static void main(String[] args) {
        // 匿名内部类:省略实现类定义
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("多线程启动了");
            }
        }).start();
    }
}

优化:减少了类定义,但仍保留了 new Runnable()@Override 等冗余语法。

(3)方案 3:Lambda 表达式终极简化

java

运行

public class LambdaDemo {
    public static void main(String[] args) {
        // Lambda 表达式:仅保留核心逻辑
        new Thread(() -> {
            System.out.println("多线程启动了");
        }).start();
    }
}

核心Runnable 是函数式接口(仅一个抽象方法 run()),Lambda 表达式直接替代其实现,只关注 “要做的事情”。

2.3 Lambda 表达式的标准格式

Lambda 表达式由三要素组成:形式参数、箭头、代码块,语法格式固定:

plaintext

(形式参数) -> { 代码块 }
  • 形式参数:函数式接口中抽象方法的参数列表;无参数则留空 (),多个参数用逗号分隔;
  • ->:固定语法,读作 “箭头”,表示 “执行以下操作”;
  • 代码块:抽象方法的实现逻辑,即要做的事情;若代码块只有一行,可省略 {} 和 ;(return 也可省略)。

2.4 Lambda 表达式的使用前提

  1. 必须有一个函数式接口(接口中仅有一个抽象方法,可加 @FunctionalInterface 注解校验);
  2. 需通过该接口的引用接收 Lambda 表达式(或作为方法参数传递)。

2.5 Lambda 表达式实战练习

下面通过不同参数和返回值的函数式接口,练习 Lambda 表达式的用法。

(1)练习 1:无参无返回值

```java

运行

// 函数式接口(无参无返回)
@FunctionalInterface
interface NoReturnNoParam {
    void method();
}

public class LambdaExercise {
    public static void main(String[] args) {
        // Lambda 实现
        NoReturnNoParam demo = () -> {
            System.out.println("无参无返回值的 Lambda 表达式");
        };
        demo.method(); // 调用方法
    }
}

(2)练习 2:单参数无返回值

java

运行

// 函数式接口(单参数无返回)
@FunctionalInterface
interface NoReturnOneParam {
    void method(int a);
}

public class LambdaExercise {
    public static void main(String[] args) {
        // 简化写法:参数类型可省略
        NoReturnOneParam demo = (a) -> {
            System.out.println("单参数无返回值:" + a);
        };
        demo.method(6); // 输出:单参数无返回值:6
    }
}

(3)练习 3:多参数无返回值

```java

运行

// 函数式接口(多参数无返回)
@FunctionalInterface
interface NoReturnMultiParam {
    void method(int a, int b);
}

public class LambdaExercise {
    public static void main(String[] args) {
        NoReturnMultiParam demo = (a, b) -> {
            System.out.println("多参数无返回值:a=" + a + ", b=" + b);
        };
        demo.method(3, 5); // 输出:多参数无返回值:a=3, b=5
    }
}

(4)练习 4:无参有返回值

```java

运行

// 函数式接口(无参有返回)
@FunctionalInterface
interface ReturnNoParam {
    int method();
}

public class LambdaExercise {
    public static void main(String[] args) {
        // 简化写法:单条返回语句可省略 {} 和 return
        ReturnNoParam demo = () -> 100;
        int result = demo.method();
        System.out.println("无参有返回值:" + result); // 输出:100
    }
}

(5)练习 5:单参数有返回值

```java

运行

// 函数式接口(单参数有返回)
@FunctionalInterface
interface ReturnOneParam {
    int method(int a);
}

public class LambdaExercise {
    public static void main(String[] args) {
        ReturnOneParam demo = (a) -> a * 2; // 简化写法
        int result = demo.method(6);
        System.out.println("单参数有返回值:" + result); // 输出:12
    }
}

(6)练习 6:多参数有返回值

```java

运行

// 函数式接口(多参数有返回)
@FunctionalInterface
interface ReturnMultiParam {
    int method(int a, int b);
}

public class LambdaExercise {
    public static void main(String[] args) {
        ReturnMultiParam demo = (a, b) -> a + b; // 求和
        int result = demo.method(6, 8);
        System.out.println("多参数有返回值:" + result); // 输出:14
    }
}

三、总结:IO 流与 Lambda 表达式核心要点

1. IO 流核心

  • 分类:字节流(InputStream/OutputStream)处理所有文件,字符流(Reader/Writer)处理文本;
  • 实战FileInputStream/FileOutputStream 用于字节读写,FileReader/FileWriter 用于文本读写;
  • 关键:必须释放资源(推荐 try-with-resources),避免路径错误和编码乱码。

2. Lambda 表达式核心

  • 思想:函数式编程,强调 “做什么” 而非 “形式”;
  • 格式(参数) -> { 代码块 },可根据场景简化;
  • 前提:依赖函数式接口(仅一个抽象方法);
  • 优势:简化匿名内部类代码,提高开发效率,尤其适用于多线程、集合排序等场景。

通过本文的学习,你已掌握 Java IO 流的实战用法和 Lambda 表达式的完整语法。IO 流是数据交互的基础,Lambda 是代码简化的利器,二者结合能让你的 Java 代码更高效、更简洁。后续可进一步学习 IO 流的高级用法(如缓冲流、转换流)和 Lambda 表达式在集合中的应用(如 stream API)。

更多推荐