自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(65)
  • 收藏
  • 关注

原创 数据结构与算法(Java语言)之 并查集

另一个是10个元素但是是倾斜二叉树,或者说极端一点退化成一个链表的数结构,这样的话其实我们应该把100个元素的挂在倾斜的10个元素的集合上,这样我们的树结构高度才不会进一步倾斜。其实它主要解决的是我们有一个主要集合,里面有很多元素,我们现在要快随判断这些元素一共有多少组,也要快速返回每一个元素属于哪个组的问题。版本二的 union的时候,要更改的只有一个元素,p节点的代表节点改成q节点的代表节点。union的时候,我们不考虑每个子集合元素的多少,都是取右边元素为新的子集合的代表节点。输入:grid = [

2024-12-07 15:35:56 1497 18

原创 thinking in java - 泛型2

虽然ArrayMaker的kind参数通过Class保留了类型信息,但Array.newInstance的返回类型设计为Object,因为它需要支持所有可能的componentType(如String.class、Integer.class等),无法在编译时静态绑定到具体类型。当通过反射创建数组时,返回的实际类型(如String[])在运行时是明确的,但编译器无法验证其与泛型类型T[]的兼容性,因此需要显式强制转换。其实泛型,本身就是为了,让我们的代码能够处理多个类,让代码更加具有泛化能力。

2025-02-23 23:02:23 257

原创 thinking in java - 泛型1

而使用泛型方法的时候,通常不需要我们指定具体的参数类型,因为编译器会通过类型推断帮助我们找到具体的类型,这也叫类型参数推断。所以当我们调用泛型方法的时候,我们可以像普通方法一样调用即可,但是注意如果传入基本类型的时候,编译器会使用自动打包,将基本类型的包装类型传入。但是有的时候,限制我们的参数在一个派生组合里面,也非常限制我们的代码的扩展性。Java泛型是通过擦除来实现的,这意味着,当我们使用泛型的时候,实际上所有的类型信息都被擦出了,你唯一知道的是我们在使用一个对象。聪明的你,也许会相到接口。

2025-02-23 22:25:22 554

原创 【从字节码的角度看switch-case】

虽然Java的语法,switch-case语句是用来处理条件判断的。Java编译器会根据case值的分布情况,生成两种不同的字节码指令:tableswitch(表跳转)和lookupswitch(查找跳转)。当我们的条件比较多的时候,我们一般就不采用if-else的判断方式来进行判断了。执行效率高(时间复杂度 O(1)),但占用空间较大(需为所有可能的索引值分配表项)。适用场景:当case的值稀疏不连续(如 1, 10, 100)时使用。适用场景:当case的值连续且密集(如 1, 2, 3)时使用。

2025-02-18 20:50:17 302

原创 比简单工厂更好的 - 工厂方法模式(Factory Method Pattern)

产品接口(Product):声明了所有具体产品必须实现的操作。所有的具体产品类都实现了这个接口或继承自这个抽象类。具体产品(ConcreteProduct):实现了Product接口,提供了具体产品的实现。@Override@Override创建者/工厂接口(Creator):接口或抽象类,声明了工厂方法,该方法返回Product类型的对象。创建者还可以包含其他业务逻辑,这些逻辑可以调用工厂方法来创建产品对象。// 工厂方法// 其他业务逻辑// 使用创建的产品。

2025-01-21 22:40:25 1561 1

原创 少一点If/Else - 状态模式(State Pattern)

环境类(Context):环境类拥有对状态对象的引用,并且提供了客户端访问状态的方法。它还负责管理状态的变化。抽象状态(State):这是一个接口或抽象类,声明了所有具体状态必须实现的方法。这些方法定义了不同状态下对象的行为。具体状态(ConcreteState):具体状态实现了State接口,每个具体状态类都包含了与该状态相关的行为逻辑。@Override// 改变状态@Override// 改变状态状态模式的优点。

2025-01-15 22:48:36 1645 2

原创 更灵活的对象之间的联动 - 观察者模式(Observer Pattern)

主题(Subject):主题接口声明了添加、删除和通知观察者的方法。它可以是接口或抽象类,具体主题实现类会实现这些方法,并维护观察者的列表。} } }List;具体主题(ConcreteSubject):具体主题实现了Subject接口,并包含有状态信息。当状态发生变化时,它会通知所有注册的观察者。// 状态改变后通知所有观察者。

2025-01-14 20:24:18 1278 9

原创 有时候还是需要后悔药的 - 备忘录模式(Memento Pattern)

发起人(Originator):发起人是一个包含有状态信息的对象,它可以创建一个备忘录,用来记录当前的状态;也可以使用一个备忘录来恢复其状态。} // 创建备忘录 public Memento createMemento() {} // 恢复状态 public void restoreFromMemento(Memento memento) {} }} // 创建备忘录 public Memento createMemento() {

2025-01-13 22:15:05 837 5

原创 还是开个会议吧 - 中介者模式(Mediator Pattern)

如果在一个系统中,对象与对象之间的联系呈现出一种网状结构的时候,这就会导致系统非常复杂。而我们的中介者模式可以使得我们对象之间的关系大量减少。所有的对象都跟中介者进行沟通。这样的话,对象之间的关系就会出现从网状结构转化成星形结构,减少了对象之间的耦合度。降低耦合度:通过引入中介者,减少了对象之间直接的依赖关系,使得系统中的对象更加独立。集中化控制:所有的通信逻辑都集中在中介者中,这有助于管理和维护复杂的交互过程。易于扩展:新增加的同事对象只需要实现同事接口,并注册到中介者中即可,无需修改现有的代码。

2025-01-10 17:28:24 1459 2

原创 开关不一定是开关灯用 - 命令模式(Command Pattern)

降低了系统的耦合度。新的命令可以很容易地加入到系统中。可以方便地实现对请求的撤销和重做。不过,命令模式也可能增加系统的复杂性,因为它需要引入许多新的类。如果系统比较简单,使用命令模式可能会显得过于繁琐。

2025-01-09 23:04:57 1508

原创 一个个顺序挨着来 - 责任链模式(Chain of Responsibility Pattern)

定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。目的:解耦请求的发送者与接收者,提供一个灵活的方式来处理请求,支持动态添加或移除处理逻辑。责任链可以帮助我们降低耦合度;增加灵活性;可以帮助我们更好地组织代码。我们上面实现地责任链模式是类似与拦截器的那种方式。责任链还可以设计为一些别的方式。责任链模式一般适用于日志记录;审批流程等等。

2025-01-08 23:30:54 1071 12

原创 【Java从入门到放弃 之 final 关键字】

修饰基本类型的时候,代表的是修饰变量的值不能变化;修饰Object引用的时候,代表的是这个变量代表的引用不能改变(引用不能改变,但是引用指向的对象是可以改变的)Overriding 只会发生在父类非私有的方法中,上面代码案例中我们在最下面的子类把f()改成自己的实现,实际上这个方法是public,父类的是private;Java允许你用final 修饰参数列表中的形参,这个意味着,在这个函数中不能修改这个形参。因为我们没有获取私有方法的权限,这也就意味着,我们不能改变父类中的私有方法的实现。

2025-01-07 22:16:50 1416 3

原创 你内部啥样跟我没关系 - 迭代器模式(Iterator Pattern)

迭代器接口(Iterator):声明了用于遍历集合的方法,如 hasNext() 和 next() 等。具体迭代器必须实现这些方法,以提供特定类型的遍历逻辑。T next();具体迭代器(ConcreteIterator):实现了 Iterator 接口的具体类。聚合接口(Aggregate):接口或抽象类,声明了一个创建迭代器对象的方法。具体聚合类必须实现这个方法,以返回一个与之对应的迭代器实例。Iterator;

2025-01-03 21:45:21 1052 11

原创 电影院售票 - 策略模式(Strategy Pattern)

策略接口(Strategy):定义了所有支持算法公共操作的接口或抽象类。具体策略类必须实现这个接口中的方法。具体策略(ConcreteStrategy):实现了 Strategy 接口的具体类。每个具体策略都提供了一种算法的实现方式。@Override@Override上下文(Context):上下文类拥有一个对策略对象的引用,并提供了设置和获取策略的方法。上下文委托给策略对象来执行具体的算法逻辑。// 设置策略// 执行策略= null) {} else {策略模式的优点。

2025-01-02 21:46:31 1705 3

原创 复杂对象的创建与组装 - 建造者模式(Builder Pattern)

产品(Product): 最终被构建出来的复杂对象。它可以是一个具体的类,也可以是包含多个组件的对象。产品对象并不知道如何创建自己;相反,它依赖于建造者来完成其组装。抽象建造者(Builder):接口或抽象类,声明了用于构建各个组件的方法。具体建造者必须实现这些方法,以提供特定类型的对象构建逻辑。具体建造者(ConcreteBuilder):实现了 Builder 接口的具体类。每个具体建造者都对应一种特定的产品类型,并负责一步一步地构建该产品的不同部分。@Override。

2025-01-01 22:47:13 1529 1

原创 从家谱的层级结构 - 组合模式(Composite Pattern)

定义: 组合多个对象形成树状结构以表示“部分-整体”的层次结构。组合模式让客户端可以一致地使用单个对象和组合。目的: 简化客户端代码对复杂层次结构的操作,同时保持良好的扩展性和灵活性。一致性:客户端可以一致地对待单个对象和组合对象,不需要关心它们的具体类型。灵活性:很容易通过组合模式构建复杂的树形结构,并且可以在不影响现有代码的情况下增加新的组件。符合开闭原则:当需要添加新类型的组件时,只需创建一个新的叶子或组合类,而无需修改现有的代码。

2024-12-28 22:56:56 1100 3

原创 买东西不一定要亲自去,叫个代购也很方便 - 代理模式(Proxy Pattern)

封装变化:可以通过代理对象隐藏真实对象的变化,减少客户端代码与真实对象之间的耦合。增强功能:在不修改真实对象的情况下,通过代理对象添加新的功能,如日志记录、事务管理等。延迟加载:对于大型或复杂对象,可以使用虚拟代理实现延迟加载,提高性能。访问控制:通过保护代理实现细粒度的访问控制,确保只有授权用户才能访问特定资源。代理设计模式是一种非常有用的设计模式,它可以在不修改原始对象的情况下,为其添加额外的功能或控制其访问。然而,在使用时也需要注意其可能带来的复杂性和性能问题。

2024-12-27 22:30:41 1342 1

原创 能省一点是一点 - 享元模式(Flyweight Pattern)

当一个软件需要创建大量的对象的时候,就会导致内存消耗过多,系统性能下降。而享元模式就是为了解决这个问题而出现的设计模式。享元模式(Flyweight Pattern)的核心思想: 如果一个对象实例创建之后不可变的话,反复创建这种实例就变得没有必要,直接向客户端返回一个共享的实例就可以了,这样既节省了内存,还避免了创建对象的过程,提升运行效率。当代码实现中出现大量相同对象的时候,我们就可以考虑使用享元模式。这种设计模式通过共享对象,节约了内存空间,提升了系统性能。减少内存中的对象数量。

2024-12-26 22:42:29 1175 1

原创 有个服务员真好 - 外观模式(Facade Pattern)

外观模式定义与目的定义:为一个复杂的子系统提供一个更简单的接口。目的:简化客户代码对复杂子系统的调用过程,隐藏子系统的内部实现细节。外观模式的角色外观(Facade):提供了简化了的接口给客户端使用。外观类知道如何委托给子系统的各个类,以及如何协调它们的工作。子系统类(Subsystem Classes):每个子系统类都有自己的接口和方法,但它们并不直接暴露给客户端,而是通过外观类来访问。外观模式是一个非常有用的设计模式,特别是在需要简化复杂子系统的使用时。

2024-12-25 21:53:58 882 1

原创 你穿上马甲我还认识你 - 装饰器(Decorator)模式

装饰器(Decorator)模式定义与目的定义:装饰器模式是在不修改原始类文件和使用继承的情况下,动态地扩展一个对象的功能。目的:能够在运行时将责任附加到对象上,提供一种比静态子类化更灵活的解决方案。装饰器(Decorator)模式包含的角色组件(Component): 定义了所有具体组件和装饰器必须实现的操作。它可以是任何可以被装饰的对象。具体组件(ConcreteComponent) : 实现了 Component 接口的具体类,表示被装饰的基本对象。

2024-12-24 19:35:23 1332 8

原创 【只生一个好 - 单例设计模式(Singleton Pattern)】

单例模式的优点唯一性:确保了类在整个应用程序中只有一个实例。控制资源:对于需要严格控制资源使用的场合非常适合。延迟加载:可以通过某些实现方式(如懒汉式、静态内部类)实现延迟初始化,节省资源。线程安全:通过适当的实现方式可以保证在多线程环境下的安全性。单例模式的缺点难以测试:单例模式引入了全局状态,这可能使得单元测试变得困难。隐藏依赖关系:因为单例模式通常通过静态方法提供实例,所以依赖关系往往被隐藏起来,不利于依赖注入和代码维护。

2024-12-23 18:58:55 1559 10

原创 带着国标充电器出国怎么办? 适配器模式(Adapter Pattern)

适配器模式定义与目的定义:适配器模式是一种结构型设计模式,它使接口不兼容的对象能够协作。适配器充当两个不兼容接口之间的桥梁。目的:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式的实现方式在Java中,我们主要通过组合或聚合的方式,在适配器内部包含一个对适配者的引用。代码案例// 对象适配器// 构造函数注入适配者@Override适配器模式的过程中一般涉及三个角色:Target 目标。

2024-12-22 22:51:03 1146 3

原创 【Spring框架 四】

Spring 测试框架与 Spring 本身的集成非常紧密,它利用了 Spring 的核心特性如依赖注入(DI)、面向切面编程(AOP)、事务管理等,使得测试更加高效和便捷。

2024-12-22 22:04:03 875 1

原创 跟着我左手右手一个慢动作 —— 模板方法模式

我们通过上面的这个案例,让大家了解了模板方法设计模式。这个模式的核心思想是父类定义主干流程,子类负责细节的实现。同时为了防止子类重写父类的主干流程方法,我们可以把主干流程方法设置为final关键字,这个final关键字用于方法的效果是子类不能更改父类的实现。对final关键字不了解的同学,可以看一下我的这篇文章关键字。对于子类需要实现的抽象方法,我们一般使用protected关键字修饰,这样的话,外部客户端就不可见这些方法了。

2024-12-20 22:06:20 1554 20

原创 还在为什么是面向对象而挠头吗?详解面向对象OOP

面向过程编程和面向对象编程各有优劣,适用于不同类型的应用场景。对于小型、简单的任务,面向过程编程可能是更直接的选择;而对于大型、复杂的系统,尤其是那些需要良好的维护性和扩展性的项目,面向对象编程提供了更强大的工具和支持。在实际开发中,很多现代编程语言都支持多种编程范式,开发者可以根据具体需求选择最合适的风格或混合使用。

2024-12-18 21:11:29 3061 20

原创 【Spring框架 三】

Spring Web 框架概述定义:Spring Web 框架是一个用于开发 Web 应用程序的轻量级框架,它简化了创建复杂的 Web 应用程序的过程。特点:MVC 架构:遵循模型-视图-控制器(MVC)设计模式,使得应用程序的不同方面可以解耦,便于测试和维护。非侵入性:通过依赖注入(DI)和面向接口编程,减少了代码之间的耦合度。灵活性:支持多种视图技术(如 JSP、Thymeleaf、FreeMarker 等),并且可以轻松集成其他第三方库和技术。

2024-12-17 21:16:05 1054

原创 【Java从入门到放弃 之 应用反射实现简单的序列化与反序列化】

上面,我们写了一个简单的序列化与反序列化的案例,让我们体会到反射技术的强大。很明显,通过使用反射,我们的代码会具有更大的灵活性。但是需要注意的是,上面这个简答的序列化与反序列化只是一个让我们体会反射技术的案例,实际上要实现一个序列化与反序列化的通用方法要考虑很多安全性,性能与兼容性的处理。

2024-12-16 21:46:17 466 1

原创 【Java从入门到放弃 之 通用容器类】

Collection 接口概述定义:Collection 是一个代表一组对象(称为元素)的容器的接口。它是所有集合类的顶级接口,但不包括映射(Map)。特点:提供了基本的集合操作方法,如添加、删除、遍历等。不保证元素的顺序,也不保证元素是否唯一(这些特性由具体实现决定)。可以包含重复元素(取决于具体实现),并且允许 null 元素(同样取决于具体实现)List 接口概述定义:List 是一个有序集合,其中每个元素都有一个对应的索引位置。你可以通过索引来访问、插入或删除元素。

2024-12-15 21:00:39 2537 9

原创 【Git教程 之 基本使用】

这一部分,我们主要讲解使用,不带入过多的概念与知识,git一般只是给我们用来管理代码的工具。我们基本的只需要了解工具的使用就好了。如果对git的原理有兴趣,之后我会把自己对git底层原理的理解分享出来。

2024-12-14 14:47:49 293

原创 【Java从入门到放弃 之 HashMap 和 HashSet】

概述定义:HashMap 是一种以哈希表为基础的实现,提供了常数时间复杂度 O(1) 的基本操作(如 get 和 put),假设哈希函数分布均匀。特点:线程不安全:与 Hashtable 不同,HashMap 不是同步的,因此在多线程环境中需要额外的同步机制。允许一个 null 键和多个 null 值:可以包含一个 null 键和任意数量的 null 值。无序:不保证元素的迭代顺序;如果需要有序,可以考虑使用 LinkedHashMap 或 TreeMap。内部工作原理。

2024-12-12 20:40:29 1487 4

原创 【Java从入门到放弃 之 LinkedList 和 ArrayDeque】

概述定义:LinkedList 是一个可以动态调整大小的双向链表实现,允许在列表两端快速添加或移除元素,并且支持按位置插入和删除。特点:线程不安全:与 ArrayList 类似,LinkedList 也不是同步的,多线程环境下需要额外的同步机制。允许重复元素:可以包含多个相同的元素。允许空值:支持存储 null 值,甚至可以存储多个 null。双端队列功能:除了作为普通列表使用外,LinkedList 还提供了双端队列的功能,如在头部或尾部添加/移除元素。内部工作原理。

2024-12-12 15:17:30 1397 1

原创 【Java从入门到放弃 之 ArrayList】

概述定义:ArrayList 是一个可以动态增长和缩小的数组实现,允许存储任意数量的对象。特点:线程不安全:ArrayList 不是同步的,如果多个线程同时修改同一个 ArrayList 实例,则必须显式地进行同步。允许重复元素:与 Set 不同,ArrayList 允许存储重复的元素。允许空值:支持存储 null 值,甚至可以存储多个 null。内部工作原理ArrayList 内部使用一个对象数组来存储元素。

2024-12-11 22:53:53 1288 4

原创 【Java从入门到放弃 之 GC】

首先我们要了解Java运行时内存,我们关注的点主要在堆区与方法区。栈区的内存基本是类结构确定的时候就确定下来了。那么我们说的垃圾回收,是回收这两个区域的不再使用的对象。那么如何确定对象是不再使用的,或者说是死对象?

2024-12-10 20:10:30 641

原创 【Java从入门到放弃 之 ConcurrentModificationException】

这种情况下,Java 的集合框架为了保证数据的一致性和安全性,会抛出 ConcurrentModificationException 来阻止潜在的并发修改问题。我们做foreach循环的时候,返回了Iterator对象,这个对象的modCount是新建立这个对象时候的modCount值。下面是Itr的源码,我们明显看到expectedModCount是取得新建这个对象的时候modCount的值,导致后面集合修改了modCount值之后,就出现不一致的问题。修改集合用的是Collection对象通信导致的。

2024-12-08 14:09:04 3163 4

原创 【Java从入门到放弃 之 关键字】

byte大小:8位(1字节)范围:-128 到 127用途:适合存储小整数值。默认值:0short大小:16位(2字节)范围:-32,768 到 32,767用途:适合存储较小的整数值。默认值:0int大小:32位(4字节)范围:-2³¹ (-2,147,483,648) 到 2³¹-1 (2,147,483,647)用途:最常用的整数类型。默认值:0long大小:64位(8字节)

2024-12-05 22:33:45 1253 1

原创 数据结构与算法(Java语言)之快速排序算法

它采用分治法(Divide and Conquer)策略,将一个列表分为两个子列表,递归地排序两个子列表,然后将它们合并成一个有序的列表。我们上面那种写法,固定是选取最左侧的元素,如果最左侧的元素不合适,快递会快速退化。上面的单路快排加随机化其实已经可以不错的处理排序,但是上面的算法如果遇到数组中有大量相同的元素的时候,性能下降。这里我们还是选择最左侧的元素为基准,但是我们先随机交换了一下,这样就可以提升部分性能。** 最后留一个小思考问题,你能仿照双路快排,写出一个三路快速排序算法吗**

2024-12-05 00:20:31 648

原创 【Java从入门到放弃 之 内存映射文件】

它将文件的内容映射到进程的虚拟地址空间,使得读写文件就像访问内存一样简单高效。内存映射的还有一个特点是,因为各个应用程序共用内存,这个多个程序映射一个文件到一个内存区域就可以很方便地实现程序之间的通信。内存映射也有局限性,因为它是按页分配内存的,所以如果是小文件的话,会造成浪费的情况。内存映射是一种按需加载的方式,这样使得我们可以通过内存映射更加方便高效地处理大文件。应用程序写到内存映射的区域,这个写完之后的结果取决于操作系统的调度,然后同步到硬盘文件上去。

2024-12-04 19:47:36 665

原创 【Java从入门到放弃 之 从字节码的角度异常处理】

如果大家对与java的异常使用还有问题或者还不太了解,建议先看一下我之前写的了解一下基本 的异常处理知识,再看这篇文章。

2024-12-04 13:04:27 1597 4

原创 【Java从入门到放弃 之 类加载器】

除了使用JVM提供的默认类加载器外,开发人员还可以根据需要自定义类加载器。自定义类加载器通常需要继承java.lang.ClassLoader类,并重写其中的findClass()方法或loadClass()方法。通过自定义类加载器,可以实现一些特殊的功能,如从网络加载类、从数据库加载类等。

2024-12-03 17:24:11 1399 2

原创 【Git教程 之 安装】

如果系统提示需要安装“命令行开发者工具”,表示尚未安装Git,此时可以点击“安装”并同意条款,即可安装Git及必要的开发工具。Homebrew是广受Mac用户欢迎的包管理器,它可以简化Git在macOS上的安装过程。打开“终端”:在Mac上,可以在“应用程序”文件夹中的“实用工具”文件夹中找到“终端”应用程序,并点击打开。安装完成后,要执行下面两条命令,配置自己的username与email,这个是用来标识你的身份的。下载完成后,双击安装包进行安装,后续都安装默认的配置一路点下去。

2024-12-01 22:53:37 772 3

【Java从入门到放弃 之 从字节码的角度异常处理】文章中的字节码

【Java从入门到放弃 之 从字节码的角度异常处理】文章中的字节码

2024-12-04

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除