✏️
kingkong
  • Introduction
  • Go
    • 入门
    • 并发
    • 避坑
    • 测试
    • GC
    • 性能剖析PProf
    • 第三方库
    • 学习资料
    • 编写可维护Go语言代码建议
    • SOLID Go Design
    • 数组与切片
    • Go Mudules
    • mac 系统go升级 1.12到1.14
  • Kubernetes
    • 安装
    • 本质
    • 常用命令
    • 架构
    • 配置文件
    • Pod
    • Kubectl
    • 学习资料
  • Mac
    • Mac
    • Alfred4
    • 开机启动项管理
    • 升级macOS Big Sur11.1后蓝牙不能用
    • macOs磁盘清理之Homebrew数据清理
  • Docker
    • 常用命令
    • Dockerfile
    • Compose
    • Registry
    • Limit
    • Network
    • Volume
    • 特殊的进程
    • Namespace-Process
    • Namespace-Mount
    • Namespace-UTS
    • Namespace-IPC
    • Namespace-Network
    • Namespace-User
    • 踩坑
  • DevOps
    • ChatOps
    • GitOps
    • SecOps
    • VictorOps
  • Algorithm
    • raft
  • 中间件
    • etcd
    • Nacos集群部署
    • zookeeper
  • 分布式
    • CAP理论
    • BASE理论
    • Gossip协议
  • 网络
    • IP地址编址方式
    • C10k
    • NIO-BIO-AIO
    • Http
  • Linux
    • 常用命令
    • 常用命令1
    • 常用网络命令
    • 进程管理
    • 守护进程
    • Systemd
    • Unix哲学
    • 端口
    • 网络
    • CentOS目录结构
    • IT
    • 文件系统
    • 开源协定
    • 基础知识
    • bash
    • shell
    • vim
    • lvm2
    • btrfs文件系统
    • raid
    • 任务计划及周期性任务执行
    • find
    • 程序包的安装卸载
    • yum
    • sed
    • 用户、组和权限
  • 数据库
    • Redis
    • MySQL
  • 消息队列
    • kafka
  • 语言之道
  • 程序设计原则
  • LoadBalancer
    • LVS
    • HAProxy
  • 敏捷
    • 影响地图
    • 卡诺模型
    • 精益画布
    • 电梯演讲
    • INVEST原则
    • 复杂系统
    • AARRR模型
    • 用户故事
    • 看板
    • Scrum
  • MicroService
    • 分布式链接追踪系统
    • ServiceMesh
    • 如何设计微服务
    • 领域驱动设计
  • 项目实战
    • 多通道告警服务
    • IAM
  • 管理
    • 沟通
    • 演讲
    • 面试官
  • Authorization
    • JWT
  • Spring
    • IoC
    • SpringFramework
    • Spring核心编程思想
  • Java
    • SPI机制
    • Jar
    • tutorial
    • 面向对象
    • 核心类
    • 泛型
    • 集合
    • IO
    • 日期与时间
    • 单元测试
    • maven
    • 函数式编程
  • Mix
    • Bookmark
    • WorkStation
    • 快速压力转换
    • 手机拍照
    • markdown画图
    • RESTful API设计
    • 如何做单元测试
    • 赶走脂肪肝
  • Aphorism
  • 互联网
    • DNS
    • Nginx
  • Rust
  • Quarkus
    • java.util.zip.ZipException: zip END header not found
  • Python
    • tutorial
  • 区块链
    • Substrate
    • BTC
Powered by GitBook
On this page
  • Lambda表达式
  • FunctionalInterface
  • stream
  • 创建stream

Was this helpful?

  1. Java

函数式编程

函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

Lambda表达式

(s1, s2) -> {
    return s1.compareTo(s2);
}

Arrays.sort(array, (s1, s2) -> s1.compareTo(s2));

FunctionalInterface

定义了单方法的接口称之为FunctionalInterface,用注解@FunctionalInterface标记

  • 单方法接口被称为FunctionalInterface。

  • 接收FunctionalInterface作为参数的时候,可以把实例化的匿名类改写为Lambda表达式,能大大简化代码。

  • Lambda表达式的参数和返回值均可由编译器自动推断。

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

因为Comparator接口定义的方法是int compare(String, String),和静态方法int cmp(String, String)相比,除了方法名外,方法参数一致,返回类型相同,因此,我们说两者的方法签名一致,可以直接把方法名作为Lambda表达式传入

public class Main {
    public static void main(String[] args) {
        String[] array = new String[] { "Apple", "Orange", "Banana", "Lemon" };
        Arrays.sort(array, Main::cmp);
        System.out.println(String.join(", ", array));
    }

    static int cmp(String s1, String s2) {
        return s1.compareTo(s2);
    }
}

在这里,方法签名只看参数类型和返回类型,不看方法名称,也不看类的继承关系

方法引用

  • 静态方法

  • 实例方法

  • 构造方法

public class Main {
    public static void main(String[] args) {
        List<String> names = List.of("Bob", "Alice", "Tim");
        List<Person> persons = names.stream().map(Person::new).collect(Collectors.toList());
        System.out.println(persons);
    }
}

class Person {
    String name;
    public Person(String name) {
        this.name = name;
    }
    public String toString() {
        return "Person:" + this.name;
    }
}

FunctionalInterface允许传入:

  • 接口的实现类(传统写法,代码较繁琐);

  • Lambda表达式(只需列出参数名,由编译器推断类型);

  • 符合方法签名的静态方法;

  • 符合方法签名的实例方法(实例类型被看做第一个参数类型);

  • 符合方法签名的构造方法(实例类型被看做返回类型)。

FunctionalInterface不强制继承关系,不需要方法名称相同,只要求方法参数(类型和数量)与方法返回类型相同,即认为方法签名相同。

stream

划重点:这个Stream不同于java.io的InputStream和OutputStream,它代表的是任意Java对象的序列

java.io

java.util.stream

存储

顺序读写的byte或char

顺序输出的任意Java对象实例

用途

序列化至文件或网络

内存计算/业务逻辑

再次划重点:这个Stream和List也不一样,List存储的每个元素都是已经存储在内存中的某个Java对象,而Stream输出的元素可能并没有预先存储在内存中,而是实时计算出来的。

List的用途是操作一组已存在的Java对象,而Stream实现的是惰性计算,两者对比如下:

java.util.List

java.util.stream

元素

已分配并存储在内存

可能未分配,实时计算

用途

操作一组已存在的Java对象

惰性计算

Stream API的特点是:

  • Stream API提供了一套新的流式处理的抽象序列;

  • Stream API支持函数式编程和链式操作;

  • Stream可以表示无限序列,并且大多数情况下是惰性求值的。

创建stream

// Stream.of()
Stream<String> stream = Stream.of("A", "B", "C", "D");
        // forEach()方法相当于内部循环调用,
        // 可传入符合Consumer接口的void accept(T t)的方法引用:
        stream.forEach(System.out::println);

//基于数组或Collection
Stream<String> stream1 = Arrays.stream(new String[] { "A", "B", "C" });
Stream<String> stream2 = List.of("X", "Y", "Z").stream();
//Collection(List、Set、Queue等),直接调用stream()方法就可以获得Stream


//基于Supplier
Stream<String> s = Stream.generate(Supplier<String> sp);

//创建Stream的第三种方法是通过一些API提供的接口,直接获得Stream
try (Stream<String> lines = Files.lines(Paths.get("/path/to/file.txt"))) {
    ...
}

// 另外,正则表达式的Pattern对象有一个splitAsStream()方法,可以直接把一个长字符串分割成Stream序列而不是数组
Pattern p = Pattern.compile("\\s+");
Stream<String> s = p.splitAsStream("The quick brown fox jumps over the lazy dog");
s.forEach(System.out::println);

// Java标准库提供了IntStream、LongStream和DoubleStream这三种使用基本类型的Stream,它们的使用方法和范型Stream没有大的区别,设计这三个Stream的目的是提高运行效率
// 将int[]数组变为IntStream:
IntStream is = Arrays.stream(new int[] { 1, 2, 3 });
// 将Stream<String>转换为LongStream:
LongStream ls = List.of("1", "2", "3").stream().mapToLong(Long::parseLong);
PreviousmavenNextMix

Last updated 4 years ago

Was this helpful?