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);
}
}