LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

Maven,工厂模式,反射模式,Lambda表达式,stream流式处理

2023/10/26 后端

Maven构建工具

Maven介绍
  • Maven是项目管理工具,对软件项目提供构建与依赖管理
  • Maven是Apache下的Java开源项目
  • Maven为Java项目提供了统一的管理方式,已经成为业界标准
Maven核心特性
  • 项目设置遵循统一的规则,保证不同开发环境的兼容性
  • 强大的依赖管理,项目依赖组件自动下载、自动更新
  • 可扩展的插件机制,使用简单,功能丰富
Maven的坐标
  • GroupId:机构或者团体的英文,采用”逆向域名”形式书写
  • ArtifactId:项目名称,说明其用途,例如:cms、oa…
  • Version:版本号,一般采用”版本+单词”形式,例如:1.0.0.RELEASE

Maven项目标准结构

目录 用途
${basedir} 根目录,用于保存pom.xml
${basedir}/src/main/java Java源代码目录
${basedir}/src/main/resources 资源目录,保存配置文件、静态图片等
${basedir}/src/test/java 测试类的源代码
${basedir}/src/test/resources 测试时需要使用的资源文件
${basedir}/target 项目输出的目录,用于存储jar、war文件
${basedir}/target/class 字节码(.class)的编译输出目录
${basedir}/pom.xml 项目(Project)对象(Object)模型(Model)文件

Maven依赖管理

  • Maven利用dependency(依赖) 自动下载、管理第三方Jar
  • 在pom.xml文件中配置项目依赖的第三方组件
  • maven自动将依赖从远程仓库下载至本地仓库,并在工程中引用
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
</dependencies>

Maven Central Repository Search可以搜索maven

pom.xml
<dependencies>
    <dependency>
          <groupId>com.belerweb</groupId>
          <artifactId>pinyin4j</artifactId>
          <version>2.5.1</version>
    </dependency>
</dependencies>
PinyinTestor.java
import net.sourceforge.pinyin4j.PinyinHelper;

import java.util.Scanner;

public class PinyinTestor {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        String[] pingyin = PinyinHelper.toHanyuPinyinStringArray(str.charAt(0)); //将输入的第一个数据变成字符串数组
        for (String py : pingyin){
            System.out.println(py);
        }
    }
}

本地仓库与中央仓库

maven 在项目启动的时候会对 pom.xml 进行加载 之后会在本地仓库 .m2\repository 去查找依赖文件(jar包) 如果查不到或不存在 就会去中央仓库下载(repo.maven.apache.org)到本地仓库

项目打包

  • Maven可将Java项目打包为jar、war
  • Maven项目打包是通过Plugins(插件)技术实现
  • Maven输出jar包插件:maven-assembly-plugin
//阿里云镜像下载地址
<repositories>
  <repository>
      <!-- 创建私服的地址 -->
    <id>aliyun</id>
    <name>aliyun</name>
    <url>https://maven.aliyun.com/repository/public</url>
  </repository>
</repositories>

Maven构建Web工程

创建Maven-Project

Group Id: maven-first
Artifacr Id: maven
Version: 1.0.0-RELEASE
Packaging: jar

IntelliJ IDEA创建maven web项目(IDEA新手适用)_idea maven创建web项目-CSDN博客
IDEA2022版本创建maven web项目(两种方式)最全图文教学_idea创建maven项目没有webapp-CSDN博客
IDEA中创建Maven Web项目的两种方法_idea maven创建web项目-CSDN博客
Project Structure → Modules → +增加Web

web application exploded:这个是以文件夹形式发布项目,发布项目时就会自动生成文件夹在指定的output directory;
web application archive:就是war包形式,将项目打成一个war包在指定位置

Tomcat报404问题解决方案大全(包括tomcat可以正常运行但是报404)_tomcat 404_ISAS的博客-CSDN博客
Windows下如何查看某个端口被谁占用 | 菜鸟教程 (runoob.com)
(.iml的问题)IDEA中用Maven创建web项目部署运行时页面报错404解决方法_maven web项目404-CSDN博客

Web应用打包

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Web_one</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar\war</packaging>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.2</version>
            </plugin>
        </plugins>
    </build>

</project>

打包成war\jar后可以通过tomcat中的临时启动服务器来运行

Maven常用命令

命令 用途
mvn archetype:generate 创建Maven工程结构
mvn compile 编译源代码 .class
mvn test 执行测试用例
mvn clean 清除产生的项目
mvn package 项目打包
mvn install 安装至本地仓库

修改本地仓库地址

工厂模式 [运用于真实项目]

设计模式
  • 设计模式是前辈总结的设计经验
  • 设计模式的目标是代码更容易理解,更容易维护
  • 通过设计模式可以让代码更加可靠
设计模式的分类
  • 创建型模式 [帮助我们如何更精巧的创建对象]
  • 结构型模式 [在软件结构上通过重构\抽象 让软件结构变得更有条理]
  • 行为型模式 [现实中的场景对软件的设计和优化]
工厂模式
  • 工厂模式用于隐藏创建对象的细节
  • 工厂模式核心:工厂类(Factory)
  • 工厂模式可以细分为简单工厂、工厂方法与抽象方法

简单工厂图

项目应用-i18n国际化 (软件分工更明确 软件耦合降低)

不同国家显示页面的语言不同
抽象一个接口!!

反射

反射Reflect
  • 反射式在运行时动态访问类与对象的技术 [写死的代码不灵活]
  • 反射是JDK1.2版本后的高级特性,隶属于java.lang.reflect
  • 大多数Java框架都是基于反射实现参数配置、动态注入等特性
初始反射技术
未运用反射技术
 public static void case1(){
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入计算类名:");
        String op = scanner.next();
        System.out.print("请输入a:");
        int a = scanner.nextInt();
        System.out.print("请输入b:");
        int b = scanner.nextInt();
        MathOperation mathOperation = null;
        if(op.equals("Addition")){
            mathOperation = new Addition();
        }else if(op.equals("Subtraction")) {
            mathOperation = new Subtraction();
        }else if(op.equals("Multiplication")){
            mathOperation = new Multiplication();
        }else{
            System.out.println("无效的计算类");
            return;
        }
        float result = mathOperation.operate(a, b);
        System.out.println(result);
    }

======================================================
运用反射技术
 public static void case2(){
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入计算类名:");
        String op = scanner.next(); ****
        System.out.print("请输入a:");
        int a = scanner.nextInt();
        System.out.print("请输入b:");
        int b = scanner.nextInt();
        MathOperation mathOperation = null;
        try {
            mathOperation = (MathOperation) Class.forName("com.imooc.reflect." + op).newInstance(); //class.forName加载指定的类 实例化对象 运行时动态决定op创建哪些对象 访问哪些属性****
        }catch(Exception e){
            System.out.println("无效的计算类");
            return;
        }
        float result = mathOperation.operate(a, b);
        System.out.println(result); 
    }

反射的核心类

Class类

Class是JVM中代表”类和接口”的类
Class对象具体包含了某个特定类的结构信息
通过Class对象可获取对应类的构造方法/方法/成员变量

Class核心方法
方法 用途
Class.forName() [传入完整类名包括包] 静态方法,用于获取指定Class对象
classObj.newInstance() 通过默认构造方法创建新的对象
classObj.getConstructor() 获得指定的public修饰构造方法Constructor对象
classObj.getMethod() 获取指定的public修饰方法Method对象
classObj.getField() 获取指定的public修饰成员变量Field对象
Employee.java
package com.imooc.reflect.entity;

public class Employee {
    static {//静态块初始化
        System.out.println("Employee类已被加载到jvm,并已初始化");
    }
    private Integer eno;
    private String ename;
    private Float salary;
    private String dname;

    public Employee() {
        System.out.println("Employee默认构造方法已被执行");
    }

    public Integer getEno() {
        return eno;
    }

    public void setEno(Integer eno) {
        this.eno = eno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Float getSalary() {
        return salary;
    }

    public void setSalary(Float salary) {
        this.salary = salary;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }
}
ClassSample.java
package com.imooc.reflect;

import com.imooc.reflect.entity.Employee;

public class ClassSample {
    public static void main(String[] args) {
        try {
            //Class.forName()方法将指定的类加载到jvm,并返回对应Class对象
            Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
            System.out.println("Employee已被加载到jvm");
            //newInstance通过默认构造方法创建新的对象
            Employee emp = (Employee)employeeClass.newInstance();
            System.out.println(emp);
        } catch (ClassNotFoundException e) {
            //类名与类路径书写错误时抛出"类无法找到"异常
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            //对象无法被实例化,抛出"实例化异常"
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            //非法访问异常 在程序外或作用域外访问对象或成员变量时抛出
            throw new RuntimeException(e);
        }
    }
Constructor构造方法类
  • Constructor类是对Java类中的构造方法的抽象
  • Contructor对象包括了具体类的某个具体构造方法的声明
  • 通过Constructor对象调用带参构造方法创建对象
方法 用途
classObj.getConstructor() 获取指定public修饰的构造方法对象
constructorObj.newInstance() 通过对应的构造方法创建对象
Employee.java
package com.imooc.reflect.entity;

public class Employee {
    static {//静态块初始化
        System.out.println("Employee类已被加载到jvm,并已初始化");
    }
    private Integer eno;
    private String ename;
    private Float salary;
    private String dname;

    public Employee() {
        System.out.println("Employee默认构造方法已被执行");
    }

    public Employee(Integer eno, String ename, Float salary, String dname) {
        this.eno = eno;
        this.ename = ename;
        this.salary = salary;
        this.dname = dname;
        System.out.println("Employee带参构造方法已被执行");
    }

    public Integer getEno() {
        return eno;
    }

    public void setEno(Integer eno) {
        this.eno = eno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Float getSalary() {
        return salary;
    }

    public void setSalary(Float salary) {
        this.salary = salary;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "eno=" + eno +
                ", ename='" + ename + '\'' +
                ", salary=" + salary +
                ", dname='" + dname + '\'' +
                '}';
    }
}
ConstructorSample.java
package com.imooc.reflect;

import com.imooc.reflect.entity.Employee;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ConstructorSample {
    public static void main(String[] args) {
        try {
            Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
            Constructor constructor = employeeClass.getConstructor(new Class[]{ //得到对应的class对象
                    Integer.class, String.class, Float.class, String.class
            });
            Employee employee = (Employee) constructor.newInstance(new Object[]{
                    100, "李磊", 3000f, "研发部"
            });
            System.out.println(employee);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
            //类名与类路径书写错误时抛出"类无法找到"异常
        } catch (NoSuchMethodException e) {
            //没有找到与之对应格式的写法
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            //当被调用的方法的内部抛出了异常而没有被捕获时
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            //对象无法被实例化,抛出"实例化异常"
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            //非法访问异常 在程序外或作用域外访问对象或成员变量时抛出
            throw new RuntimeException(e);
        }
    }
}
Method类
  • Method对象指代某个类中的方法的描述
  • Method对象使用classObj.getMethod()方法获取
  • 通过Method对象调用指定对象的对应方法

Method核心方法

方法 用途
classObj.getMethod() 获取指定public修饰的方法对象
methodObj.invoke() 调用指定对象的对应方法
Employee.java
package com.imooc.reflect.entity;

import com.sun.org.apache.bcel.internal.generic.RETURN;

public class Employee {
    static {//静态块初始化
        System.out.println("Employee类已被加载到jvm,并已初始化");
    }
    private Integer eno;
    private String ename;
    private Float salary;
    private String dname;

    public Employee() {
        System.out.println("Employee默认构造方法已被执行");
    }

    public Employee(Integer eno, String ename, Float salary, String dname) {
        this.eno = eno;
        this.ename = ename;
        this.salary = salary;
        this.dname = dname;
        System.out.println("Employee带参构造方法已被执行");
    }

    public Integer getEno() {
        return eno;
    }

    public void setEno(Integer eno) {
        this.eno = eno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Float getSalary() {
        return salary;
    }

    public void setSalary(Float salary) {
        this.salary = salary;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "eno=" + eno +
                ", ename='" + ename + '\'' +
                ", salary=" + salary +
                ", dname='" + dname + '\'' +
                '}';
    }

    public Employee updateSalary(Float val){
        this.salary = this.salary + val;
        System.out.println(this.ename + "调薪至" + this.salary + "元");
        return this;

    }
}
MethodSample.java
package com.imooc.reflect;

import com.imooc.reflect.entity.Employee;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodSample {
    public static void main(String[] args) {
        try {
            Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
            Constructor constructor = employeeClass.getConstructor(new Class[]{
                    Integer.class, String.class, Float.class, String.class
            });
            Employee employee = (Employee) constructor.newInstance(new Object[]{
                    100, "李磊", 3000f, "研发部"
            });
            Method updateSalaryMethod = employeeClass.getMethod("updateSalary", new Class[]{ //传入参数
               Float.class
            });
            Employee employee1 = (Employee)updateSalaryMethod.invoke(employee, new Object[]{1000f}); //若有返回值 要强制转换
            System.out.println(employee1);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
Field成员变量类
  • Field对应某个具体类中的成员变量的声明
  • Field对象使用**classObj.getField()**方法获取
  • 通过Field对象可为某对象成员变量赋值/取值

Field类核心方法

方法 用途
classObj.getField() 获取指定publicc修饰的成员变量对象
fieldObj.set() 为某对象指定成员变量赋值
fieldObj.get() 获取某对象指定成员变量数值

快速添加包裹try catch → 框上要包裹的 点Code → surround with
get()/set()都是(在entify中)public共有方法

Employee.java
package com.imooc.reflect.entity;

import com.sun.org.apache.bcel.internal.generic.RETURN;

public class Employee {
    static {//静态块初始化
        System.out.println("Employee类已被加载到jvm,并已初始化");
    }
    private Integer eno;
    public String ename;
    private Float salary;
    private String dname;

    public Employee() {
        System.out.println("Employee默认构造方法已被执行");
    }

    public Employee(Integer eno, String ename, Float salary, String dname) {
        this.eno = eno;
        this.ename = ename;
        this.salary = salary;
        this.dname = dname;
        System.out.println("Employee带参构造方法已被执行");
    }

    public Integer getEno() {
        return eno;
    }

    public void setEno(Integer eno) {
        this.eno = eno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Float getSalary() {
        return salary;
    }

    public void setSalary(Float salary) {
        this.salary = salary;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "eno=" + eno +
                ", ename='" + ename + '\'' +
                ", salary=" + salary +
                ", dname='" + dname + '\'' +
                '}';
    }

    public Employee updateSalary(Float val){
        this.salary = this.salary + val;
        System.out.println(this.ename + "调薪至" + this.salary + "元");
        return this;

    }
}
FieldSample.java
package com.imooc.reflect;

import com.imooc.reflect.entity.Employee;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class FieldSample {
    public static void main(String[] args) {
        try {
            Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
            Constructor constructor = employeeClass.getConstructor(new Class[]{
                    Integer.class, String.class, Float.class, String.class
            });
            Employee employee = (Employee) constructor.newInstance(new Object[]{
                    100, "李磊", 3000f, "研发部"
            });
            Field enameField = employeeClass.getField("ename");
            enameField.set(employee,"李雷");
            String ename = (String) enameField.get(employee);
            System.out.println("ename:" + ename);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }
}

getDeclared系列方法

  • getDeclaredConstructor(s) | Method(s) | Field(s) 获取对应对象
  • getConstructor(s) | Method(s) | Field(s) 只能获取public对象
  • 访问非作用域内构造方法、方法、成员变量,会抛出异常

public可以直接获取 private只能通过get…获取

Employee.java + getDeclaredSample.java
package com.imooc.reflect;

import com.imooc.reflect.entity.Employee;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class getDeclaredSample {
    public static void main(String[] args) {
        try {
            Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
            Constructor constructor = employeeClass.getConstructor(new Class[]{
                    Integer.class, String.class, Float.class, String.class
            });
            Employee employee = (Employee) constructor.newInstance(new Object[]{
                    100, "李磊", 3000f, "研发部"
            });
            Field[] fields = employeeClass.getDeclaredFields();
            for (Field field : fields){
//                System.out.println(field.getName());
                if (field.getModifiers() == 1) {//成员变量修饰符 public修饰
                    Object val = field.get(employee);
                    System.out.println(field.getName() + ":" + val);
                } else if (field.getModifiers() == 2) { //private修饰
                    String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);//(0,1)是截取字符串 第一个大写字母
                    Method getMethod = employeeClass.getMethod(methodName);
                    Object ret = getMethod.invoke(employee);
                    System.out.println(field.getName() + ":" + ret);
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}

反射在项目中的应用

反射最重要的就是可以在运行时

反射的应用网站

对原始程序无需任何调整,只需要把对应的接口进行实现,放到线上服务器,再调整配置文件。

Zhcn.java
package com.imooc.i18n;

public class Zhcn implements I18N{
    @Override
    public String say() {
        return "生命不息奋斗不止";
    }
}
=========================================================
En.java
package com.imooc.i18n;

public class En implements I18N{
    @Override
    public String say() {
        return "Case to the struggle and cease to the life";
    }
}
========================================================
接口I18N.java
package com.imooc.i18n;

public interface I18N {
    public String say();
}
package com.imooc.i18n;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Properties;

public class Application {
    public static void say(){
        Properties properties = new Properties(); //加载指定的配置文件
        String configPath = Application.class.getResource("/config.properties").getPath();
        try {
            configPath = new URLDecoder().decode(configPath,"UTF-8");//路径中的空格默认得到url编码所以要转换一下
            properties.load(new FileInputStream(configPath)); //内容来源于文件 文件输入流
            String language = properties.getProperty("language");
            I18N i18n = (I18N)Class.forName(language).newInstance();
            System.out.println(i18n.say());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        Application.say();
    }
}
language=com.imooc.i18n.En
或
language=com.imooc.i18n.Zhcn

Lambda表达式

  • JDK8(1.8以上)开始支持Lambda表达式,用来让程序编写更优雅
  • 利用Lambda可以更简洁的实现匿名内部类函数声明与调用
  • 基于Lambda提供stream流式处理极大简化对集合的操作
传统代码
List<String> names = Arrays.asList("peter","anna","mike","xenia");
//实现集合排序
Collections.sort(names,new Comparator<String>(){
  @Override
  public int compare(String a,String b){
      return b.compareTo(a);
  }  
});
使用Lambda表达式
List<String> names = Arrays.asList("peter","anna","mike","xenia");
//通过lambda表达式简化匿名类的编写
Collections.sort(names,(a,b) -> b.compareTo(a));

Lambda表达式语法 [代码脚手架]

(参数列表) —>实现语句
[使用逗号分割参数,参数类型可省略,单参数括号可省略]
[单行直接写 多行用{}包括]

MathOperation.java
public interface MathOperation {
    //四则运算接口
    public Float operate(Integer a, Integer b);
}
LambdaSample.java
public class LambdaSample {
    public static void main(String[] args) {
        //标准Lambda使用方法
        //约束条件:Lambda表达式只能实现有且只有一个抽象方法的接口,Java称为"函数式接口"
        //1.标注使用方式
        MathOperation addition = (Integer a, Integer b) -> {
            System.out.println("加法运算");
            return a+b+0f; //定义的接口是Float
        };
        System.out.println(addition.operate(5, 5));

        //2.lambda允许忽略参数类型
        MathOperation substration = (a,b) -> {
            return a-b+0f;
        };
        System.out.println(substration.operate(5, 3));

        //3.单行实现代码可以省略大括号和return
        MathOperation multiplication = (a,b) -> a*b+0f;
        System.out.println(multiplication.operate(3, 5));
    }
}

函数式编程

  • 函数式编程是基于函数式接口并使用lambda表达的编程方式
  • 函数式编程理念是将代码作为可重用数据带入到程序运行中
  • 函数式编程强调”你想做什么“,而不是”你想怎么做

函数式接口

  • 函数式接口是有且只有一个抽象方法的接口
  • Java中拥有大量函数式接口,如java.lang.Runnable
  • JDK8后提供了一系列新的函数式接口,位于java.util.function

函数式接口Perdicate

  • Perdicate是新增的函数式接口,位于java.util.function
  • Perdicate用于测试传入的数据是否满足判断要求
  • Perdicate接口需要实现test()方法进行逻辑判断

lambda表达式来实现predicate的验证
将已有的代码变成可重复使用的资源放入程序中

PredicateSample.java
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/*
    理解函数式编程
    Perdicate函数式接口的使用方法
 */
public class PredicateSample {
    public static void main(String[] args) {
        Predicate <Integer> predicate = n->n>4; //隐藏着return
        boolean result = predicate.test(10);
        System.out.println(result);
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        filter(list,n->n%2==1); //传入函数式接口的实现lambda 取所有奇数
        filter(list,n->n%2==0); //取所有偶数
        filter(list,n->n>5 && n%2==0); //取所有大于5的偶数
    }
    public static void filter(List<Integer> list, Predicate<Integer> predicate){
        for (Integer num:list){
            if (predicate.test(num)){
                System.out.println(num + " ");
            }
        }
    }
}

各种函数接口

JDK8常用函数式接口
consumer函数接口
接口 用途
Consumer< T > 对应有一个输入参数无输出的功能代码
Function< T,R > 对应有一个输入参数且需要返回参数的功能代码
Predicate< T > 用于条件判断,固定返回布尔值
ConsumerSample.java
import java.util.function.Consumer;

/*
    Consumer接口的使用
 */
public class ConsumerSample {
    public static void main(String[] args) {
        output(s-> System.out.println("向控制台打印:" + s));
        //字符串作为网络数据包向某个网站发送
        output(s->{
            System.out.println("向XXX网络发送数据包:" + s);
        });
    }
    public static void output(Consumer<String> consumer){
        String text = "苦其心志,劳其筋骨";
        consumer.accept(text);
    }
}
Function接口
FunctionSample.java
import java.util.Random;
import java.util.function.Function;

/*
    利用Function函数式接口生成定长随机字符串[加密解密会用到]
 */
public class FunctionSample {
    public static void main(String[] args) {
        Function<Integer,String> randomStringFunction = l->{
            String chars = "abcdefghijklmnopqrstuvxwyz0123456789";
            StringBuffer stringBuffer = new StringBuffer();
            Random random = new Random();
            for (int i = 0; i < l; i++) {
                int position = random.nextInt(chars.length());
                stringBuffer.append(chars.charAt(position));//按指定位置将字符提取并追加
            }
            return stringBuffer.toString();
        };
        String randowmString = randomStringFunction.apply(16);//生成16位长的字符串
        System.out.println(randowmString);
    }
}
@functionalInterface注解
MathOperation.java
@FunctionalInterface //通知编译器这是函数式接口,进行抽象方法检查
public interface MathOperation {
    //四则运算接口

    public Float operate(Integer a, Integer b);
}

函数式编程与面向对象编程比较

面向对象编程 函数式编程
设计思路 面向对象 面向过程
开发侧重 侧重过程,重分析,重设计 侧重结果,快速实现
可读性 结构复杂,相对较差 更适合人眼阅读,可读性更好
代码量
并发问题 设计不当,会出现线程安全问题 不会出现线程安全问题
健壮性
使用场景 中大型项目,多人协作工程 小型应用,要求快速实现

Stream流式处理

  • Stream流式处理式建立在Lambda基础上的多数据处理技术
  • Stream对集合数据处理进行高度抽象,极大简化代码量
  • Stream可对集合进行迭代,去重,筛选,排序,聚合等一系列处理

Stream示例

//获取List集合中最大的偶数
Optional<Integer> op = Arrays.asList(1,2,3,4,5,6).stream()
.filter(x->x%2==0) //处理完得到一个只包含偶数的list流数据
.sorted((a,b)->b-a) //大的在前面 小的在后面
.findFirst(); //获取最大的数据
System.out.println(op.get());

Stream常用方法

接口 用途
forEach 循环遍历
map map方法用于映射每个元素到对应的结果
filter filter方法用于通知设置的条件过滤出元素
limit limit方法用于获取指定数量的流
sorted sorted方法用于对流进行排序
Collectors Collectors类实现将流转换成集合和聚合元素
StreamGenerator.java
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/*
Stream流对象的五种创建方式
 */
public class StreamGenerator {
    //1.基于数组进行创建
    @Test
    public void generator1(){
        String[] arr = {"Lily","Andy","Jackson","Smith"};
        Stream<String> stream = Stream.of(arr);
        stream.forEach(s -> System.out.println(s)); //forEach中使用Lambda表达式
    }

    //2.基于集合进行创建
    @Test
    public void generator2(){
        List<String> list = new ArrayList<>();
        list.add("Lily");
        list.add("Andy");
        list.add("Jackson");
        list.add("Smith");
        Stream<String> stream = list.stream(); //利用集合获取stream
        stream.forEach(s -> System.out.println(s));
    }

    //3.利用generate方法创建无限长度流
    @Test
    public void generator3(){
        Stream<Integer> stream = Stream.generate(() -> new Random().nextInt(100000));//Supplier<T> s 创建新对象
        stream.limit(10).forEach(i -> System.out.println(i)); //limit限制长度
    }

    //4.基于迭代器创建流
    @Test
    public void generator4(){
        Stream<Integer> stream = Stream.iterate(1, n -> n + 1);//无限长度自增
        stream.limit(100).forEach(i -> System.out.println(i));
    }

    //5.基于字符序列创建流
    @Test
    public void genetator5(){
        String str = "abcdefg我";
        IntStream stream = str.chars();
        stream.forEach(c -> System.out.println((char)c));
    }
}
StreamMethod.java
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamMethod {
    @Test //提取集合中所有偶数并求和
    public void case1(){
        List<String> list = Arrays.asList("1", "2", "3", "4", "5");
        int sum = list.stream() //获取stream对象
                .mapToInt(s -> Integer.parseInt(s)) //对每个元素字符串转为整数
                .filter(n -> n%2==0) //filter对流数据进行过滤
                .sum();//求和
        System.out.println(sum);
    }

    @Test //所有名字首字母大写
    public void case2(){
        List<String> list = Arrays.asList("lily","smith","jackson");
        List newList = list.stream()
                .map(s -> s.substring(0, 1).toUpperCase() + s.substring(1)) //首字母大写转换
//                .forEach(s -> System.out.println(s));
                .collect(Collectors.toList()); //collect对流数据进行收集,生成新的List/Set(将重复数据自动清除)
        System.out.println(newList);
    }

    @Test //将所有奇数从大到小进行排序,且不允许出现重复
    public void case3(){
        List<Integer> list = Arrays.asList(1, 60, 38, 21, 51, 60, 51, 73);
        List newList = list.stream().distinct() //去除重复的流数据
                .filter(n -> n%2==1)
                .sorted((a,b) -> b-a) //从大到小的数据排列
                .collect(Collectors.toList());
        System.out.println(newList);
    }
}