- 博客(492)
- 收藏
- 关注
原创 个人博客
主要使用的技术:Spring IOC 、DI、SpringBoot、Mybatis、AOP、Spring MVC整个项目分为 5 个板块:模块层:构建出 controller 控制层进行业务逻辑处理后返回的 model 模型,有 Article 文章模型、Category 分类模型、Comment 评论模型、User 用户模型数据访问层:构建 @Mapper 注释的接口以及对应的 mapper.xml 配置文件,两者共同形成 Sql Mapper 映射器,建立起对象和数据库之间的映射关系业务层:根据
2020-05-15 14:31:40 2488 1
原创 Awesome Java Crawler
在 https://github.com/akullpp/awesome-java/blob/master/README.md 我们可以看到许许多多好的 Java 项目,就如它的名字一样 Awesome Java 棒极了,那这么多的项目总有排名高低之分,所以我想用 Java 语言编写一项爬虫程序来给这里的项目按照规则进行排名,并最总将结果展示在网页上,让我们开始!整个项目分为四大模块:a) 抓...
2020-03-26 11:09:31 625
原创 C#-枚举
枚举概念:列举某种数据的所有值作用:增强代码的可读性,将简单的数据限制在某种范围内可供选择注意:枚举元素默认为 int ,准许使用枚举的数据类型有:byte、sbyte、short、ushort、uint、long 或者 ulong特点:每个枚举元素都有固定的枚举值,默认情况下,第一个枚举元素的枚举值为 0 ,接着后面的枚举元素的枚举值依次递增 1简单示例代码:using System;using System.Collections.Generic;using System.Linq;u
2021-02-01 15:38:03 282
原创 python-递归函数
什么是递归函数?定义:一个函数在其函数体内调用了函数本身,那么这个函数就称为递归函数递归函数的重要部分:递归的调用以及递归的终止条件递归的调用过程:(1)每调用完一次函数,会在栈上分配一个栈帧(2)每次执行完一个函数,就会释放其申请的内存空间例如:计算某个数字的阶乘def fun2(n): if n == 1: return 1 else: return n * fun2(n - 1)print fun2(4) #结果为:24斐波那契数
2020-12-30 21:06:33 415
原创 python-输出九九乘法口诀表
代码:for i in range(1, 10): for j in range(1, i + 1): print i, "*", j, "=", i * j, print #注意不要忘记换行结果如图所示:涉及知识点:(1)双层嵌套 for-in 循环(2)python2.7中如何不换行输出(在 print 后面加上一个逗号即可)...
2020-12-25 20:28:37 944
原创 ArrayLis和数组的区别
(1)首先,两者都是 Java 中重要的数据结构,经常会被使用到,数组是 Java 中当中的基础数据结构,而 ArrayList 是 Java Collection 框架下的 List 的接口的一个实现类,其内部实现原理就是依靠数组去实现的,只不过数组在构建的时候就确定的数组的长度,并且是不可变化的,而 ArrayList 可以根据情况自身进行数组的扩容,来达到动态数组的功能,所以 ArrayList 可以被理解为一种动态能够变化长度的数组,并且 ArrayList 当中还提供更多的方法来方便对于顺序表的操
2020-08-29 19:14:20 852
原创 == 和 equals
==(1)如果比较的是基础数据类型,那么 == 比较的是他们的值是否相同(2)如果比较的是引用数据类型,那么 == 比较的是他们的引用地址是否相同,也就是比较的栈中局部变量表里的 reference 引用是否相同equals(1)equals 是一个 Object 类中的方法,从源码可以知道,他比较的是两个对象的引用地址是否相同(2)但是其他类会重写 Object 类中的 equals 方法,重新定义比较的规则,像 String 中就重写了 equals 方法,他比较的是两个 String 对象
2020-08-22 10:08:00 143
原创 值传递和引用传递
首先要明确一点:在 Java 中只有值传递!只有值传递!值传递:当方法传入参数为基本数据类型这种值类型时,会将原来的基本数据类型进行一份拷贝作为方法的局部遍历传递到方法中,方法中对于局部遍历的操作仅仅是对这个拷贝的值进行修改操作,方法结束后该局部变量的任务也就完成,不会对原来变量造成任何影响引用传递:当方法传入的参数是一个对象类型,那么会对这个对象的引用地址进行一份拷贝然后传递到方法中,所以方法中的对象地址和本身的对象地址都共同指向堆上实例数据,那么这就会导致,当方法中使用拷贝对象,对其指向的堆上实例数
2020-08-08 11:51:10 170
原创 Java中锁的类型
Java中锁的类型思想上的锁:乐观锁/悲观锁悲观锁乐观锁应用场景独占锁(排他锁)/ 共享锁可重入锁公平锁/非公平锁分段锁自旋锁偏向锁/轻量级锁/重量级锁偏向锁轻量级锁重量级锁思想上的锁:乐观锁/悲观锁悲观锁总是假设资源的竞争十分激烈,每次访问数据的时候当前线程都会先加上一把锁,那么在该线程执行过程中,其他线程就不能访问数据并且处于阻塞状态,当该线程执行结束或者异常退出了,其他线程才可以去竞争锁,那么悲观锁就是采取一种保守的思想,提前上锁Java中的 synchronized 和 ReentrantL
2020-08-06 10:53:02 175
原创 ReentrantLock和Synchronized区别
前提背景:JDK1.5版本之前 lock 的性能比 synchronized 要好,但是之后 synchronized 做了很多的优化(例如加入偏向锁、轻量级锁)之后,synchronized 的性能也追了上来,但是 lock 依旧有它出彩的地方原因:在死锁问题的处理上,lock 显得更加灵活,采取的措施也更有效,而 synchronized 只能尽量的去避免死锁的产生,而 lock 可以通过内部的方法来解决死锁首先来看死锁产生的 4 个必要条件:(1) 互斥条件:当前线程获取到资源锁,那么其他线
2020-08-02 16:45:12 212
原创 JUC:并发工具类
CountDownLatch ,CyclicBarrier 和 Semaphore 工具类提供一种并发流程控制的手段Exchanger 工具类提供了在线程间交换数据的一种手段CountDownLatch主要作用是:允许一个或多个线程等待其他线程完成,然后再继续往下执行它的作用和 join 类似,但是功能比 join 更加强大,使用起来也更灵活join 的实现原理是,让当前线程等待 join 线程执行结束,在这个过程中会不停的检查 join 线程是否存活,如果还存活着,那么当前线程就会处于无限等待,
2020-07-27 11:08:00 198
原创 JUC:Atomic包
Atomic 包提供了一种用法简单、性能高效、线程安全的方式来更新一个变量变量的类型主要包括4中类型的原子更新方式:原子更新基本数据类型,原子更新数组,原子更新引用,原子更新属性(字段)其内部都是通过 CAS 机制来实现线程安全原子更新基本数据类型Atomic 包提供了三个类来更新基本数据类型:AtomicBoolean,AtomicInteger,AtomicLong,这三种方法实现的内部原理都是差不多的,就拿 AtomicInteger 来举例说明其内部原理其常用方法 getAndIncreme
2020-07-24 09:10:53 299
原创 五种IO模型
网络 IO 主要为以下两个步骤:(1)等待内核准备好数据(2)将数据从内核拷贝到用户空间一共有五种 IO 模型:阻塞 IO 、非阻塞 IO 、信号驱动 IO 、多路复用 IO 、异步 IO, 前四种是同步 IO阻塞 IO (Blocking I/O)描述:当用户线程发出 IO 请求后,内核查看数据是否准备好,没有准备好的话,用户线程就阻塞,只有当数据准备就绪,返回给用户线程后,才会解除阻塞状态例如: A 拿了一个鱼竿来到河边钓鱼,在鱼上钩之前,他一直专心致志的等待,其他什么事情也不做,只有鱼上
2020-07-19 13:12:54 148
原创 基础数据类型和包装类的区别
(1)初始值不同基本数据类型的初始值为数据本身的零值,例如 int 的初始值为 0,boolean 的初始值为 false,包装类的初始值为 null,正因为包装类的值可以为 null,所以包装类可以作为 POJO(也就是简单的无规则的 Java 对象,只有属性字段和getter以及setter方法),POJO 的属性必须使用包装类,而不能使用基本数据类型,因为数据库的查询结果可能为 null,如果使用基本数据类型的话,就需要将包装类拆箱成基本数据类型,就会抛出空指针异常(NullPointerExce
2020-07-17 16:57:31 953
原创 Redis持久化方案
Redis 持久化Redis 运行在内存上,所以数据也是保存在内存中,那么内存中的数据变化极快,可能会因为进程异常或者宕机导致数据丢失的情况,所以 Redis 提供了 RDB 和 AOF 这两种持久化方案,保证重启时还能恢复到之前数据RDB 持久化在指定的时间间隔中将内存的数据以快照的形式写入磁盘,快照:类似于将当前的数据拍成一张照片保存下来,RDB 持久化也是默认的持久化方式,默认的文件名时 dump.rdb,他有三种触发机制1. save 触发该命令会阻塞当前的 Redis 服务器,在执行 s
2020-07-16 15:41:53 201
原创 Redis内存回收策略
Redis也会因为内存不足造成一些错误,或者是因为回收内存时间太久造成系统停顿的情况,所以需要合理设置内存的回收策略,在 Redis 的配置文件 redis.conf 中有一个 maxmemory-policy 的配置项,其中有六种键值淘汰的策略volatile-lru:采用最近使用最少的淘汰策略,Redis 将回收那些超时的(仅仅是超时的)键值对,也就是它只淘汰那些超时的键值对allkeys-lru:采用淘汰最少使用的策略,Redis 将对所有的(不仅仅是超时的)键值对采用最近使用最少的淘汰策略vo
2020-07-15 09:55:22 276
原创 MyBatis
ORM 框架概念:ORM(Object Relational Mapping)对象关系映射,通过使用描述对象和关系型数据库之间映射的元数据,将面对对象语言的对象自动的持久化到数据库中元数据:用来描述数据的数据,通常指的是描述代码之间关系的数据,在 Java 中,元数据以标签的形式储存于 xml 配置文件中简单的说:ORM 的作用就是通过配置 xml 资源文件或者自动化配置 SQL 语句,然后方便的通过直接对 java 对象的方法调用或者数据调用等方式,将数据储存到数据库中常用的 ORM 框架有:My
2020-07-14 10:17:24 189
原创 MySQL:事务
事务概念:事务就是一组原子性的操作,这些操作要么全部发生,要么全部不发生。事务把数据库从一种一致性状态转换成另一种一致性状态事务的四大特性(也叫 ACID):(1)原子性事务的操作必须是具有原子性的,要么都执行成功,要么都执行失败,不能只完成部分,通过恢复机制实现(2)一致性事务执行之前后执行之后都必须处于一致性状态,例如 A 和 B 的银行账户中一共有1000,那么他俩相互转账,无论如何转账,总和加起来还是 1000(3)持久性事务完成了,就对数据做出的改变是永久的,即使修改的数据发生错误
2020-07-13 11:00:16 149
原创 MySQL中的锁
MySQL 中的锁分类锁粒度:也就是锁的级别高低锁的使用方式细分为:共享锁,独占锁(排他锁)按照锁粒度来划分:行锁,表锁,页锁思想上的锁:悲观锁,乐观锁InnoDB中的行锁又细分为:Record Lock(当前索引行记录锁)、Gap Lock(间隙锁)、Next-key Lock(行锁和间隙锁的结合)1.行锁MySQL中锁粒度最小的一种锁,只能针对当前操作行进行加锁,开销大,加锁慢,会出现死锁,锁冲突的概率低,并发度高共享锁用法(同一个时刻锁可以被多个线程获取):假设事务 A 对数据 B
2020-07-12 10:36:17 155
原创 MySQL:索引
通常的数据结构查找种类顺序查找就不用说了,时间复杂度为 O(n) ,这样查找的效率是很低效的,慢慢的就由了二分查找,二叉搜索树查找等等,有了许多高效率的查找方法,但是这些方法也有很明显的缺陷,因为它们对各自搜索的数据都有要求:例如二分查找,它就要求被查找的数据要是有序的它才能起作用,那么面对小量的数据还可以,那么大量的数据下就很难以这种方法查找,所以就由了一种新的数据结构,他能按照特定的算法来满足查找的要求,这就索引在 MySQL 中通常会使用两种方式来访问数据库的行数据:(1)顺序访问:顺序访问是在
2020-07-10 10:31:57 141
原创 Redis 六种基本数据类型
Key 命令(1)keys * 表示显示当前 redis 中插入的 key(2)exists key看一下这个 key 是否存在,存在则返回 1(3)DEL key删除 key 这个键值对(4)expire key设置 key 的过期时间和 String 操作类似也可以设置过期时间,但是 HASH 表的过期时间设置需要通过 expire 来设置,并且需要指定 HASH 表中的 key 对象,也可以通过 ttl + key对象来查看过期时间剩余(5)type key查看 key 的数据类
2020-07-09 10:23:32 544
原创 OSI七层协议
五层划分为:应用层、传输层、网络层、数据链路层、物理层物理层负责光/电信号的传递方式,例如以太网采用电缆、光纤,电磁波等这些物理硬件,物理层决定了最大传输速率、传输距离、抗干扰性等,集线器就工作在物理层例如:我现在想和朋友通过电脑聊天 ,那么我俩肯定需要接一根网线再有一个路由器,才能实现计算机和计算机之间的通信,也就是要有底层的物流硬件设施的支持那么底层传播的电信号,像01010101011011这些二进制要能够被识别和区别,那么才能正确的表达它的意思,那这些区分的工作就交给数据链路层来处理数
2020-07-08 19:44:33 221
原创 进程调度算法
一、先来先服务和短作业优先调度算法先来先服务调度算法(FCFS):简单的操作系统进程调度算法,既可以运用于作业调度,也可以运用于进程调度(1)在作业调度时:从作业队列中抽取一个或者多个先到的作业,将他们调入内存,分配资源,然后创建进程并且进入就绪队列。(2)在进程调度时:从就绪队列中抽取一个先到的进程,将处理机分配给它,等到它完成任务或者因为异常阻塞退出后,再将处理机分配给第二个先到的进程短作业优先调度算法:和先来先服务调度算法基本类似,就是在抽取作业或者进程时的规则不同,短作业算法是在队列中抽
2020-07-07 14:38:57 426
原创 快速排序的优化
(1)普通的快速排序每次找到数组中一个固定的值作为基准值(一般选举最左端或者最右端),然后采用双指针,左部分小于基准值的直接指针++,右部分大于基准值的直接指针–,直到不满足条件停下来,然后交换两者指针指向的数据,这样一趟排序下来,按照基准值所在位置的左边都是小于它的,基准值的右边都是大于它的,也就是将原本的数组分为了两个子数组,然后继续递归在子数组中排序递归版本普通快速排序:public static void quickSort(int[] array) { quickSortHe
2020-07-06 11:07:37 105
原创 JVM:垃圾回收过程
(1)创建一个新对象,判断该对象是否大于或者等于大对象的阈值(JVM用-XX:PretenureSizeThreshold来定义),如果判断为大对象,则直接进入堆上的老年代区域,此时如果老年代没有足够可用空间大小分配该对象所需的内存,则触发 Full GC(2)如果判断为小对象,则优先在堆上的新生代 Eden 区域分配内存,如果内存足够存放,则对象创建结束,不存在垃圾回收过程(3)如果Eden没有足够的内存空间分配,则JVM会进行一次 Minor GC (新生代垃圾回收)在进行 Minor GC 之前
2020-07-03 10:22:48 135 1
原创 线程池
线程池七大参数① corePoolSize:线程池的核心线程数,说白了就是,即便是线程池里没有任何任务,也会有corePoolSize个线程在候着等任务② maximumPoolSize:最大线程数,不管你提交多少任务,线程池里最多工作线程数就是maximumPoolSize③ keepAliveTime:线程的存活时间。当线程池里的线程数大于corePoolSize时,如果等了keepAliveTime时长还没有任务可执行,则线程退出⑤ unit:这个用来指定 keepAliveTime 的单位,
2020-06-27 16:45:03 468
原创 ThreadLocal
ThreadLocal用户线程局部变量,在多线程环境下可以保证线程里面的变量独立于其他线程里面的变量,也就是说,每个线程中设置的变量在其他线程里面不可以访问,类似于线程的 private static内部结构图:从图中就可以观察出 ThreadLocal 的核心机制:(1)每个线程内有一个本地私有的 ThreadLocals 变量,其是一个 ThreadLocalMap 类似(类似于 HashMap)(2)通过 ThreadLocal 来维护每个线程中设置的局部变量,设置的变量值以键值对形式储存
2020-06-24 14:33:53 147
原创 JVM:Java内存模型
Java 内存模型 (Java Memory Model)屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果JMM 定义程序中各种变量的访问规则,也就是关注在虚拟机中把变量储存在内存和从内存中取出变量值这样的底层细节Java内存模型主要是为了解决并发编程过程的原子性、可见性和有序性去建立的,解决了由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序等带来的问题这里所谓的变量和平常书写代码所涉及到的变量有所区别,它主要包
2020-06-19 21:13:33 133
原创 static 和 final
修饰成员变量,将这个修饰的成员变量变为类的成员变量也称为类静态成员变量,需要通过 类.变量名 来获取,所有该类实例对象共享该类成员变量,只要该静态成员发生一次变化,那么其他对象中的该静态变量也就改变修饰成员方法:修饰之后,该方法就成为类的方法,需要通过 类.方法名字 来获取,注意:在该静态方法中不能使用非静态的方法和成员变量,这也很好理解,static 修饰方法后就成为类的方法,由类来统一管理,如果在类中调用普通的成员变量,那么该变量是属于某个对象的,是在某个对象中设置,而类中自然无法管理到该对象..
2020-06-18 19:38:22 153
原创 JVM:触发Full Gc 的情况
一、System.gc()调用这个方法会增大触发FULL GC 的概率,但不是一定会触发 GC ,这个方法的执行只是建议 JVM 执行 GC,一般不会用到该方法,只是再观察 GC 现象的时候可能会用到二、老年代空间不足当把对象存放入老年代的时候,如果老年代空间不足,就会触发 Major GC四种种情况:a)当在新生代存活时间足够长时,要进入老年代b)当 Survivor 空间不足,存活的对象无法存入 Survivor 区,就需要老年代担保,将对象存入老年代c)大对象直接存入老年代,例如很长的字
2020-06-17 11:43:37 570
原创 Error和Exception
异常的结构在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)Throwable:Error(错误)和 Exception(异常)就是 Throwable 的子类Error 和 Exception 最大的区别是:Exception 可以被程序本身所处理,而 Error 程序本身无法所处理Error(错误)是程序本身无法处理的错误,是不可查异常,通常表示运行应用程序出现的严重问题,大多数都是和程序编写者执行的操作无关,通常表示 JVM 出现的问题,例如:Java虚拟机运行错
2020-06-16 10:11:43 370
原创 JVM:对象的创建过程以及对象的内存布局
探索在虚拟机中,创建一个普通 java 对象(也就是 new 一个实例)的过程当 java 虚拟机遇到一条 new 字节码指令的时候,首先会检查该类是否有被加载、解析和初始化(也就是类加载过),如果没有,那么先进行类加载过程当类加载完成后,接下来就要为对象分配内存,所需内存大小在类加载完成之后就可以完全的确定下来,所以只需在 java 堆中划分出足够大小的内存给该对象即可,这其中涉及到 java 堆内存是否规整(也就是说没有被使用的内存和使用的内存是分开存放还是杂乱交错在一起的),两种解决方法如
2020-06-15 09:31:21 178
原创 JVM:OutOfMemoryError
OutOfMemory概念:资源用完了,官方文档解释:当JVM 没有足够的内存来为对象分配内存空间并且垃圾回收也没有可以回收的空间时,就会抛出 OutOfMemory Error (已经不是 Exception 了,程序无法解决)出现 OOM 的原因(1)虚拟机分配的内存太少(一般通过VM参数设置)(2)申请的内存无法释放或者内存占用过多,无法申请新的内存,造成内存溢出或者内存泄漏内存溢出:内存可用空间太少,无法为对象分配足够的内存,申请的内存加上已使用的内存大小超过 JVM 提供的内存大小内
2020-06-14 13:36:03 334
原创 JVM:Java内存区域
线程私有(独享区域)1.程序计数器:当前字节码指令的指示器,因为线程之间进行切换后,再次回到本线程时,要知道进行到哪一步了,下一步应该执行那个指令,程序计数器的功能就是如此,此区域是唯一一个没有规定任何 OOM 情况的区域程序计数器记录的内容:(1)如果正在执行的是一个 java 方法,那么程序计数器记录的是正在执行的虚拟机字节码指令的地址(2)如果正在执行的是本地(Native)方法,那么程序计数器的值为空2.Java虚拟机栈通常所说的"栈" 就是指的是 虚拟机栈,虚拟机栈的生命周期和线程相
2020-06-12 20:35:05 99
原创 LeetCode:5. 最长回文子串
题目:代码:方法一:暴力解法class Solution { // 暴力解法 public String longestPalindrome(String s) { if (s == null || s.length() == 0) { return ""; } if (s.length() == 1) { return s; } String res = s
2020-06-10 19:04:30 83
原创 LeetCode:547. 朋友圈
题目:班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。示例 1:输入:[[1,1,0],[1,1,0],[0,0,1]]输出: 2说明:已知学生0和学生
2020-06-08 13:58:29 109
原创 LeetCode:445. 两数相加 II
题目:给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。你可以假设除了数字 0 之外,这两个数字都不会以零开头。进阶:如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。示例:输入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)输出:7 -> 8 -> 0 -> 7代码:方法一:链表逆序/** * Definition
2020-06-06 11:55:56 90
原创 LeetCode:56. 合并区间
题目:给出一个区间的集合,请合并所有重叠的区间。示例 1:输入: [[1,3],[2,6],[8,10],[15,18]]输出: [[1,6],[8,10],[15,18]]解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].示例 2:输入: [[1,4],[4,5]]输出: [[1,5]]解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。代码:class Solution { // 贪心算法 // 每次遍历到一个位置时,该位置之前的区
2020-06-04 17:52:17 106
原创 LeetCode:695.岛屿的最大面积
题目:给定一个包含了一些 0 和 1 的非空二维数组 grid 。一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)例子:[[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,
2020-05-31 14:43:31 194
原创 LeetCode:146.LRU缓存机制
题目:运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。代码:class LRU
2020-05-23 21:48:56 111
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人