java高频面试题-设计模式

article/2025/8/28 14:47:47

1 你所知道的设计模式有哪些?

Java 中一般认为有 23 种设计模式,我们不需要所有的都会,但是其中常用的几种设计模式应该去掌握。下面列出了所有的设计模式。需要掌握的设计模式我单独列出来了,当然能掌握的越多越好。

总体来说设计模式分为三大类:

创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

2 单例设计模式?

2.1单例模式定义

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态。

2.2 单例模式的特点

● 单例类只能有一个实例。

● 单例类必须自己创建自己的唯一实例。

● 单例类必须给所有其他对象提供这一实例。

单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要单例保证配置的一致性。

2.3 单例的四大原则

● 构造器私有化

● 以静态方法或者枚举返回实例

● 确保实例只有一个,尤其是多线程环境

● 确保反序列化时不会重新构建对象

2.4 实现单例模式的方式

(1)饿汉式(立即加载):

饿汉式单例在类加载初始化时就创建好一个静态的对象供外部使用,除非系统重启,这个对象不会改变,所以本身就是线程安全的。

Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,会使Java单例实现失效)

 package com.atguigu.interview.chapter02;
/*** @author : atguigu.com* @since 2019/7/22** 饿汉式(立即加载)*/public class Singleton1 {
/*** 私有构造*/private Singleton1() {System.out.println("构造函数Singleton1");
}
/*** 初始值为实例对象*/private static Singleton1 single = new Singleton1();
/*** 静态工厂方法* @return 单例对象*/public static Singleton1 getInstance() {System.out.println("getInstance");
return single;
}public static void main(String[] args){System.out.println("初始化");Singleton1 instance = Singleton1.getInstance();
}
}

(2)懒汉式(延迟加载):

该示例虽然用延迟加载方式实现了懒汉式单例,但在多线程环境下会产生多个Singleton对象

 package com.atguigu.interview.chapter02;
/*** @author : atguigu.com* @since 2019/7/22** 懒汉式(延迟加载)*/public class Singleton2 {
/*** 私有构造*/private Singleton2() {System.out.println("构造函数Singleton2");
}
/*** 初始值为null*/private static Singleton2 single = null;
/*** 静态工厂方法* @return 单例对象*/public static Singleton2 getInstance() {
if(single == null){System.out.println("getInstance");single = new Singleton2();
}
return single;
}public static void main(String[] args){System.out.println("初始化");Singleton2 instance = Singleton2.getInstance();
}
}

(3)同步锁(解决线程安全问题):

在方法上加synchronized同步锁或是用同步代码块对类加同步锁,此种方式虽然解决了多个实例对象问题,但是该方式运行效率却很低下,下一个线程想要获取对象,就必须等待上一个线程释放锁之后,才可以继续运行。

 package com.atguigu.interview.chapter02;
/*** @author : atguigu.com* @since 2019/7/22** 同步锁(解决线程安全问题)*/public class Singleton3 {
/*** 私有构造*/private Singleton3() {}
/*** 初始值为null*/private static Singleton3 single = null;public static Singleton3 getInstance() {// 等同于 synchronized public static Singleton3 getInstance()
synchronized(Singleton3.class){// 注意:里面的判断是一定要加的,否则出现线程安全问题
if(single == null){single = new Singleton3();
}
}
return single;
}
}

(4)双重检查锁(提高同步锁的效率):

使用双重检查锁进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。

 package com.atguigu.interview.chapter02;
/*** @author : atguigu.com* @since 2019/7/22* 双重检查锁(提高同步锁的效率)*/public class Singleton4 {
/*** 私有构造*/private Singleton4() {}
/*** 初始值为null*/private static Singleton4 single = null;
/*** 双重检查锁* @return 单例对象*/public static Singleton4 getInstance() {
if (single == null) {
synchronized (Singleton4.class) {
if (single == null) {single = new Singleton4();
}
}
}
return single;
}
}

(5) 静态内部类:

这种方式引入了一个内部静态类(static class),静态内部类只有在调用时才会加载,它保证了Singleton 实例的延迟初始化,又保证了实例的唯一性。它把singleton 的实例化操作放到一个静态内部类中,在第一次调用getInstance() 方法时,JVM才会去加载InnerObject类,同时初始化singleton 实例,所以能让getInstance() 方法线程安全。

特点是:即能延迟加载,也能保证线程安全。

静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。

 package com.atguigu.interview.chapter02;
/*** @author : atguigu.com* @since 2019/7/22** 静态内部类(延迟加载,线程安全)*/public class Singleton5 {
/*** 私有构造*/private Singleton5() {}
/*** 静态内部类*/private static class InnerObject{private static Singleton5 single = new Singleton5();
}public static Singleton5 getInstance() {
return InnerObject.single;
}
}

(6)内部枚举类实现(防止反射攻击):

事实上,通过Java反射机制是能够实例化构造方法为private的类的。这也就是我们现在需要引入的枚举单例模式。

 package com.atguigu.interview.chapter02;
/*** @author : atguigu.com* @since 2019/7/22*/public class SingletonFactory {
/*** 内部枚举类*/private enum EnumSingleton{Singleton;private Singleton6 singleton;//枚举类的构造方法在类加载是被实例化private EnumSingleton(){singleton = new Singleton6();
}public Singleton6 getInstance(){
return singleton;
}
}public static Singleton6 getInstance() {
return EnumSingleton.Singleton.getInstance();
}
}
class Singleton6 {public Singleton6(){}
}

3 工厂设计模式(Factory)

3.1 什么是工厂设计模式?

工厂设计模式,顾名思义,就是用来生产对象的,在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则,如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦

3.2 简单工厂(Simple Factory)

定义:

一个工厂方法,依据传入的参数,生成对应的产品对象;
角色:
1、抽象产品
2、具体产品
3、具体工厂
4、产品使用者
使用说明:

先将产品类抽象出来,比如,苹果和梨都属于水果,抽象出来一个水果类Fruit,苹果和梨就是具体的产品类,然后创建一个水果工厂,分别用来创建苹果和梨。代码如下:

水果接口:

public interface Fruit {
void whatIm();
}

苹果类:

public class Apple implements Fruit {@Overridepublic void whatIm() {System.out.println("苹果");
}
}

梨类:

public class Pear implements Fruit {@Overridepublic void whatIm() {System.out.println("梨");
}
}

水果工厂:

public class FruitFactory {public Fruit createFruit(String type) {
if (type.equals("apple")) {//生产苹果
return new Apple();
} else if (type.equals("pear")) {//生产梨
return new Pear();
}
return null;
}
}

使用工厂生产产品:

public class FruitApp {public static void main(String[] args) {FruitFactory mFactory = new FruitFactory();Apple apple = (Apple) mFactory.createFruit("apple");//获得苹果Pear pear = (Pear) mFactory.createFruit("pear");//获得梨apple.whatIm();pear.whatIm();
}
}

以上的这种方式,每当添加一种水果,就必然要修改工厂类,违反了开闭原则;

所以简单工厂只适合于产品对象较少,且产品固定的需求,对于产品变化无常的需求来说显然不合适。

3.3 工厂方法(Factory Method)

定义:

将工厂提取成一个接口或抽象类,具体生产什么产品由子类决定;
角色:
1、抽象产品
2、具体产品
3、抽象工厂
4、具体工厂
使用说明:

和上例中一样,产品类抽象出来,这次我们把工厂类也抽象出来,生产什么样的产品由子类来决定。代码如下:
水果接口、苹果类和梨类:

代码和上例一样

抽象工厂接口:

public interface FruitFactory {Fruit createFruit();//生产水果
}

苹果工厂:

public class AppleFactory implements FruitFactory {@Overridepublic Apple createFruit() {
return new Apple();
}
}

梨工厂:

public class PearFactory implements FruitFactory {@Overridepublic Pear createFruit() {
return new Pear();
}
}

使用工厂生产产品:

public class FruitApp {public static void main(String[] args){AppleFactory appleFactory = new AppleFactory();PearFactory pearFactory = new PearFactory();Apple apple = appleFactory.createFruit();//获得苹果Pear pear = pearFactory.createFruit();//获得梨apple.whatIm();pear.whatIm();
}
}

以上这种方式,虽然解耦了,也遵循了开闭原则,但是如果我需要的产品很多的话,需要创建非常多的工厂,所以这种方式的缺点也很明显。

3.4 抽象工厂(Abstract Factory)

定义:

为创建一组相关或者是相互依赖的对象提供的一个接口,而不需要指定它们的具体类。
角色:

  1. 1、抽象产品
    2、具体产品3、抽象工厂4、具体工厂

使用说明:

抽象工厂和工厂方法的模式基本一样,区别在于,工厂方法是生产一个具体的产品,而抽象工厂可以用来生产一组相同,有相对关系的产品;重点在于一组,一批,一系列;举个例子,假如生产小米手机,小米手机有很多系列,小米note、红米note等;假如小米note生产需要的配件有825的处理器,6英寸屏幕,而红米只需要650的处理器和5寸的屏幕就可以了。用抽象工厂来实现:

cpu接口和实现类:

public interface Cpu {
void run();
class Cpu650 implements Cpu {@Overridepublic void run() {System.out.println("650 也厉害");
}
}
class Cpu825 implements Cpu {@Overridepublic void run() {System.out.println("825 更强劲");
}
}
}

屏幕接口和实现类:

public interface Screen {
void size();
class Screen5 implements Screen {@Overridepublic void size() {System.out.println("" +
"5寸");
}
}
class Screen6 implements Screen {@Overridepublic void size() {System.out.println("6寸");
}
}
}

抽象工厂接口:

public interface PhoneFactory {Cpu getCpu();//使用的cpuScreen getScreen();//使用的屏幕
}

小米手机工厂:

public class XiaoMiFactory implements PhoneFactory {@Overridepublic Cpu.Cpu825 getCpu() {
return new Cpu.Cpu825();//高性能处理器
}@Overridepublic Screen.Screen6 getScreen() {
return new Screen.Screen6();//6寸大屏
}
}

红米手机工厂:

public class HongMiFactory implements PhoneFactory {@Overridepublic Cpu.Cpu650 getCpu() {
return new Cpu.Cpu650();//高效处理器
}@Overridepublic Screen.Screen5 getScreen() {
return new Screen.Screen5();//小屏手机
}
}

使用工厂生产产品:

public class PhoneApp {public static void main(String[] args){HongMiFactory hongMiFactory = new HongMiFactory();XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();Cpu.Cpu650 cpu650 = hongMiFactory.getCpu();Cpu.Cpu825 cpu825 = xiaoMiFactory.getCpu();cpu650.run();cpu825.run();Screen.Screen5 screen5 = hongMiFactory.getScreen();Screen.Screen6 screen6 = xiaoMiFactory.getScreen();screen5.size();screen6.size();
}
}

以上例子可以看出,抽象工厂可以解决一系列的产品生产的需求,对于大批量,多系列的产品,用抽象工厂可以更好地管理和扩展。

3.5三种工厂方式总结

1、对于简单工厂和工厂方法来说,两者的使用方式实际上是一样的,如果对于产品的分类和名称是确定的,数量是相对固定的,推荐使用简单工厂模式;

2、抽象工厂用来解决相对复杂的问题,适用于一系列、大批量的对象生产。

4 代理模式(Proxy)

4.1什么是代理模式?

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗地来讲代理模式就是我们生活中常见的中介。

举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下:

4.2 为什么要用代理模式?

中介隔离作用:

在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。

开闭原则,增加功能:

代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是通过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要修改已经封装好的委托类。

4.3 有哪几种代理模式?

我们有多种不同的方式来实现代理。

如果按照代理创建的时期来进行分类的话,可以分为两种:静态代理、动态代理。

  • ● 静态代理是由程序员创建或特定工具自动生成源代码,再对其编译。在程序员运行之前,代理类.class文件就已经被创建了。
  • ● 动态代理是在程序运行时通过反射机制动态创建的。

4.4 静态代理(Static Proxy)

第一步:创建服务类接口

public interface BuyHouse {
void buyHouse();
}

第二步:实现服务接口

public class BuyHouseImpl implements BuyHouse {@Overridepublic void buyHouse() {System.out.println("我要买房");
}
}

第三步:创建代理类

 public class BuyHouseProxy implements BuyHouse {private BuyHouse buyHouse;public BuyHouseProxy(final BuyHouse buyHouse) {
this.buyHouse = buyHouse;
}@Overridepublic void buyHouse() {System.out.println("买房前准备");buyHouse.buyHouse();System.out.println("买房后装修");
}
}

第四步:编写测试类

public class HouseApp {public static void main(String[] args) {BuyHouse buyHouse = new BuyHouseImpl();BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);buyHouseProxy.buyHouse();
}
}

静态代理总结:

优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。

缺点:我们得为每一个服务创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。

4.5 JDK动态代理(Dynamic Proxy)

在动态代理中我们不再需要再手动的创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象由JDK在运行时为我们动态地来创建。

第一步:创建服务类接口

代码和上例一样

第二步:实现服务接口

代码和上例一样

第三步:编写动态处理器

public class HouseApp {public static void main(String[] args) {BuyHouse buyHouse = new BuyHouseImpl();BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);buyHouseProxy.buyHouse();
}
}

第四步:编写测试类

public class HouseApp {public static void main(String[] args) {BuyHouse buyHouse = new BuyHouseImpl();BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);buyHouseProxy.buyHouse();
}
}

Proxy是所有动态生成的代理的共同的父类,这个类有一个静态方法Proxy.newProxyInstance(),接收三个参数:

● ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的

● Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型

● InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法

JDK动态代理总结:

优点:相对于静态代理,动态代理大大减少了开发任务,同时减少了对业务接口的依赖,降低了耦合度。

缺点:Proxy是所有动态生成的代理的共同的父类,因此服务类必须是接口的形式,不能是普通类的形式,因为Java无法实现多继承。

4.6 CGLib动态代理(CGLib Proxy)

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对final修饰的类进行代理。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

Cglib子类代理实现方法:

(1)引入cglib的jar文件,asm的jar文件

(2)代理的类不能为final

(3)目标业务对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法

第一步:创建服务类

public class BuyHouse2 {public void buyHouse() {System.out.println("我要买房");
}
}

第二步:创建CGLIB代理类

public class CglibProxy implements MethodInterceptor {private Object target;public CglibProxy(Object target) {
this.target = target;
}
/*** 给目标对象创建一个代理对象* @return 代理对象*/public Object getProxyInstance() {//1.工具类Enhancer enhancer = new Enhancer();//2.设置父类enhancer.setSuperclass(target.getClass());//3.设置回调函数enhancer.setCallback(this);//4.创建子类(代理对象)
return enhancer.create();
}public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("买房前准备");//执行目标对象的方法Object result = method.invoke(target, args);System.out.println("买房后装修");
return result;
}
}

第三步:创建测试类

public class HouseApp {public static void main(String[] args) {BuyHouse2 target = new BuyHouse2();CglibProxy cglibProxy = new CglibProxy(target);BuyHouse2 buyHouseCglibProxy = (BuyHouse2) cglibProxy.getProxyInstance();buyHouseCglibProxy.buyHouse();
}
}

CGLib代理总结:

CGLib创建的动态代理对象比JDK创建的动态代理对象的性能更高,但是CGLIB创建代理对象时所花费的时间却比JDK多得多。所以对于单例的对象,因为无需频繁创建对象,用CGLIB合适,反之使用JDK方式要更为合适一些。同时由于CGLib由于是采用动态创建子类的方法,对于final修饰的方法无法进行代理。

4.7 简述动态代理的原理, 常用的动态代理的实现方式

动态代理的原理: 使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。

代理对象决定是否以及何时将方法调 用转到原始对象上

动态代理的方式

基于接口实现动态代理: JDK动态代理

基于继承实现动态代理: Cglib、Javassist动态代理

 

 


http://chatgpt.dhexx.cn/article/pCetIukw.shtml

相关文章

Java常见设计模式面试题及答案

文章目录 1.设计模式是什么&#xff1f;你是否在代码中使用过&#xff1f;2. JDK 中常用的设计模式有哪些&#xff1f;3.单例模式是什么&#xff1f;请用 Java 写出线程安全的单例模式4.在 Java 中&#xff0c;什么叫观察者模式&#xff08;observer design pattern&#xff09…

JAVA常见设计模式面试题

一、单例模式 java中单例模式是一种常见的设计模式&#xff0c;单例模式的写法有好几种&#xff0c;这里主要介绍三种&#xff1a;懒汉式单例、饿汉式单例、双重检查锁定 1.单例模式有以下特点&#xff1a;   a、单例类只能有一个实例。   b、单例类必须自己创建自己的唯一…

设计模式面试题

设计模式 详解 设计模式 参考&#xff1a; https://www.jianshu.com/p/fc4b2e679a1e 单例模式 整个应用中保证只有一个类的实例存在 参考&#xff1a; https://mp.weixin.qq.com/s/dlVXW6aW4wLcLpey9NxPig 饿汉式单例类 懒汉式单例类 instance new SingletonClas…

设计模式面试题(设计模式速成版)

文章目录 说明名词解释UML基础面向对象编程中&#xff0c;都有哪些设计原则开闭原则里氏替换原则&#xff08;Liskov Substitution Principle&#xff09;依赖转置&#xff08;依赖倒置&#xff09;原则单一职责原则接口隔离原则迪米特法则合成复用原则 设计模式的分类创建型模…

【前端面试题】06—16道设计模式面试题(附答案)

设计模式不是针对某个框架的&#xff0c;而是针对某类问题或某类需求提出的&#xff0c;因此有广泛的适用性。 我们学习设计模式不仅要学习理论&#xff0c;还要学习如何解决实际工作中的问题&#xff0c;所以在面试中&#xff0c;设计模式通常是结合某类需求考察的。 1、什么是…

❤️设计模式肝完了,还挺全!腾讯和阿里的offer已拿!❤️

设计模式肝完了&#xff0c;还挺全&#xff01;腾讯和阿里的offer已拿&#xff01; 金九银十已经来了&#xff0c;挺近大厂最好的机会已经来了&#xff01;如果你是要找工作的&#xff0c;一定要抓住这个机会&#xff01; 前面已经整理了很多的面试资料&#xff1a; 1&#x…

「面试必背」设计模式面试题(收藏)

前言 设计模式在日常的工作中&#xff0c;是非常重要的一项技能&#xff0c;使用设计模式可以重构整体架构代码、提交代码复用性、扩展性、减少代码冗余问题。这是每个 Java 工程师必备的技能&#xff01;今日小编主要讲的是设计模式之一的策略模式&#xff0c;小编会通过案例…

textRank杂谈

转自&#xff1a;这些文章 1. PageRank算法概述 PageRank,即网页排名&#xff0c;又称网页级别、Google左侧排名或佩奇排名。 是Google创始人拉里佩奇和谢尔盖布林于1997年构建早期的搜索系统原型时提出的链接分析算法&#xff0c;自从Google在商业上获得空前的成功后&#xff…

人工智能自然语言处理—PageRank算法和TextRank算法详解

人工智能自然语言处理—PageRank算法和TextRank算法详解 一、PageRank算法 PageRank算法最初被用作互联网页面重要性的计算方法。它由佩奇和布林于1996年提出&#xff0c;并被用于谷歌搜索引擎的页面排名。事实上&#xff0c;PageRank可以在任何有向图上定义&#xff0c;然后…

TextRank算法学习及使用

文章目录 一、算法思想二、python代码实现三、TextRank算法使用1、textrank4zh模块的安装2、实例介绍 总结 参考资料&#xff1a; 文本关键词抽取、文本摘要生成是自然语言处理&#xff08;NLP&#xff09;的应用之一&#xff0c;一定会对我们的生活产生巨大影响。随着数字媒体…

自然语言处理NLP--TextRank算法

文本摘要方法 早在20世纪50年代&#xff0c;自动文本摘要已经吸引了人们的关注。在20世纪50年代后期&#xff0c;Hans Peter Luhn发表了一篇名为《The automatic creation of literature abstract》的研究论文&#xff0c;它利用词频和词组频率等特征从文本中提取重要句子&…

【自然语言处理】基于TextRank算法的文本摘要

基于TextRank算法的文本摘要 文本摘要是自然语言处理&#xff08;NLP&#xff09;的应用之一&#xff0c;一定会对我们的生活产生巨大影响。随着数字媒体的发展和出版业的不断增长&#xff0c;谁还会有时间完整地浏览整篇文章、文档、书籍来决定它们是否有用呢&#xff1f; 利…

【自然语言处理】利用TextRank算法提取关键词

利用TextRank提取关键词 TextRank 是一种基于 PageRank 的算法&#xff0c;常用于关键词提取和文本摘要。在本文中&#xff0c;我将通过一个关键字提取示例帮助您了解 TextRank 如何工作&#xff0c;并展示 Python 的实现。 使用 TextRank、NER 等进行关键词提取 1.PageRank简…

【NLP】关键词提取:TFIDF、TextRank

前两天看到论文《Chinese Poetry Generation with Planning based Neural Network》中使用TextRank进行关键词提取。在阅读文章时也想到了除了TextRank之外&#xff0c;经常还使用TFIDF进行关键词提取。 一些算法的使用取决于业务场景和算法的特性。关键词提取是干什么的呢&am…

TF-IDF算法和TextRank算法的分析比较

TF-IDF算法 TF-IDF&#xff08;词频-逆文档频率&#xff09;算法是一种统计方法&#xff0c;用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加&#xff0c;但同时会随着它在语料库中出现的频率成反比下降…

Python文本处理工具——TextRank

背景 TextRank是用与从文本中提取关键词的算法&#xff0c;它采用了PageRank算法&#xff0c;原始的论文在这里。Github地址。 这个工具使用POS( part-of-speech tagging : 词性标注 )然后抽取名词&#xff0c;这种方法对于关键词提取独具特色。 注意&#xff1a; 先安装NL…

TextRank学习笔记

TextRank起源与PageRank TextRank的灵感来源于大名鼎鼎的PageRank算法&#xff0c;这是一个用作网页重要度排序的算法。 并且&#xff0c;这个算法也是基于图的&#xff0c;每个网页可以看作是一个图中的结点&#xff0c;如果网页A能够跳转到网页B&#xff0c;那么则有一条A-…

【TextRank】关键词提取 算法原理 公式推导 源码分析

1.前言 在介绍TextRank前&#xff0c;我想先给大家介绍下PageRank&#xff0c;实质上个人认为可以把TextRank当做PageRank2.0。 谷歌的两位创始人的佩奇和布林&#xff0c;借鉴了学术界评判学术论文重要性的通用方法&#xff0c;“那就是看论文的引用次数”。由此想到网页的重要…

NLP - 关键词提取 - TextRank

NLP - 关键词提取 - TextRank 一、TextRank介绍二、PageRank介绍三、PageRank计算过程四、关键词提取任务 一、TextRank介绍 TextRank算法则可以脱离语料库的基础&#xff0c;仅对单篇文档进行分析就可以提取该文档的关键词。这也是TextRank算法的重要特点。TextRank算法的基本…

textrank算法原理与提取关键词、自动提取摘要PYTHON

首先介绍原理与概念 TextRank 算法是一种用于文本的基于图的排序算法。其基本思想来源于谷歌的 PageRank算法&#xff08;其原理在本文在下面&#xff09;, 通过把文本分割成若干组成单元(单词、句子)并建立图模型, 利用投票机制对文本中的重要成分进行排序, 仅利用单篇文档本…