能力说明:
精通JVM运行机制,包括类生命、内存模型、垃圾回收及JVM常见参数;能够熟练使用Runnable接口创建线程和使用ExecutorService并发执行任务、识别潜在的死锁线程问题;能够使用Synchronized关键字和atomic包控制线程的执行顺序,使用并行Fork/Join框架;能过开发使用原始版本函数式接口的代码。
暂无个人介绍
如何理解“递归”? 递归是一种应用非常广泛的算法(或者编程技巧)。之后我们要讲的很多数据结构和算法的编码实现都要用到递归,比如 DFS 深度优先搜索、前中后序二叉树遍历等等。所以,搞懂递归非常重要,否则,后面复杂一些的数据结构和算法学起来就会比较吃力。
排序对于任何一个程序员来说,可能都不会陌生。你学的第一个算法,可能就是排序。大部分编程语言中,也都提供了排序函数。 排序算法太多了,有很多可能你连名字都没听说过,比如猴子排序、睡眠排序、面条排序等。我只讲众多排序算法中的一小撮,也是最经典的、最常用的:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。 思考题:插入排序和冒泡排序的时间复杂度相同,都是 ,在实际的软件开发里,为什么我们更倾向于使用插入排序算法而不是冒泡排序算法呢?
今天,我讲两种时间复杂度为 的排序算法,归并排序和快速排序。这两种排序算法适合大规模的数据排序,比上一节讲的那三种排序算法要更常用。 归并排序和快速排序都用到了分治思想,非常巧妙。我们可以借鉴这个思想,来解决非排序的问题,比如:如何在 O(n) 的时间复杂度内查找一个无序数组中的第 K 大元素? 这就要用到我们今天要讲的内容。
上两节中,我带你着重分析了几种常用排序算法的原理、时间复杂度、空间复杂度、稳定性等。今天,我会讲三种时间复杂度是 的排序算法:桶排序、计数排序、基数排序。因为这些排序算法的时间复杂度是线性的,所以我们把这类排序算法叫作线性排序(Linear sort)。之所以能做到线性的时间复杂度,主要原因是,这三个算法是非基于比较的排序算法,都不涉及元素之间的比较操作。 按照惯例,我先给你出一道思考题:如何根据年龄给 100 万用户排序? 你可能会说,我用上一节课讲的归并、快排就可以搞定啊!是的,它们也可以完成功能,但是时间复杂度最低也是 O(nlogn)。有没有更快的排序方法呢?让我们一起进入今天的内
如何选择合适的排序算法? 如果要实现一个通用的、高效率的排序函数,我们应该选择哪种排序算法?我们先回顾一下前面讲过的几种排序算法。
今天我们讲一种针对有序数据集合的查找算法:二分查找(Binary Search)算法,也叫折半查找算法。 老规矩,我们还是来看一道思考题。假设我们有 1000 万个整数数据,每个数据占 8 个字节,如何设计数据结构和算法,快速判断某个整数是否出现在这 1000 万数据中? 我们希望这个功能不要占用太多的内存空间,最多不要超过 100MB,你会怎么做呢?带着这个问题,让我们进入今天的内容吧!带着这个问题,让我们进入今天的内容吧!
跳表这种数据结构对你来说,可能会比较陌生,因为一般的数据结构和算法书籍里都不怎么会讲。但是它确实是一种各方面性能都比较优秀的动态数据结构,可以支持快速地插入、删除、查找操作,写起来也不复杂,甚至可以替代红黑树(Red-black tree)。 Redis 中的有序集合(Sorted Set)就是用跳表来实现的。如果你有一定基础,应该知道红黑树也可以实现快速地插入、删除和查找操作。那 Redis 为什么会选择用跳表来实现有序集合呢? 为什么不用红黑树呢?学完今天的内容,你就知道答案了。
Word 这种文本编辑器你平时应该经常用吧,那你有没有留意过它的拼写检查功能呢?一旦我们在 Word 里输入一个错误的英文单词,它就会用标红的方式提示“拼写错误”。Word 的这个单词拼写检查功能,虽然很小但却非常实用。你有没有想过,这个功能是如何实现的呢?
为什么散列表和链表经常会一起使用? 今天,我们就来看看,在这几个问题中,散列表和链表都是如何组合起来使用的,以及为什么散列表和链表会经常放到一块使用。
哈希算法历史悠久,业界著名的哈希算法也有很多,比如 MD5、SHA 等。在我们平时的开发中,基本上都是拿现成的直接用。所以,我今天不会重点剖析哈希算法的原理,也不会教你如何设计一个哈希算法,而是从实战的角度告诉你,在实际的开发中,我们该如何用哈希算法解决问题。
树(Tree) 我们首先来看,什么是“树”?再完备的定义,都没有图直观。所以我在图中画了几棵“树”。你来看看,这些“树”都有什么特征?
二叉查找树是最常用的一种二叉树,它支持快速插入、删除、查找操作,各个操作的时间复杂度跟树的高度成正比,理想情况下,时间复杂度是 。 不过,二叉查找树在频繁的动态更新过程中,可能会出现树的高度远大于 的情况,从而导致各个操作的效率下降。极端情况下,二叉树会退化为链表,时间复杂度会退化到 O(n)。要解决这个复杂度退化的问题,我们需要设计一种平衡二叉查找树,也就是今天要讲的这种数据结构。 很多书籍里,但凡讲到平衡二叉查找树,就会拿红黑树作为例子。不仅如此,如果你有一定的开发经验,你会发现,在工程中,很多用到平衡二叉查找树的地方都会用红黑树。你有没有想过,为什么工程中都喜欢用红黑树,而不是其他
递归树与时间复杂度分析 我们前面讲过,递归的思想就是,将大问题分解为小问题来求解,然后再将小问题分解为小小问题。这样一层一层地分解,直到问题的数据规模被分解得足够小,不用继续递归分解为止。 如果我们把这个一层一层的分解过程画成图,它其实就是一棵树。我们给这棵树起一个名字,叫作递归树。我这里画了一棵斐波那契数列的递归树,你可以看看。节点里的数字表示数据的规模,一个节点的求解可以分解为左右子节点两个问题的求解。
我们今天讲另外一种特殊的树,“堆”(Heap)。堆这种数据结构的应用场景非常多,最经典的莫过于堆排序了。堆排序是一种原地的、时间复杂度为 的排序算法。 前面我们学过快速排序,平均情况下,它的时间复杂度为 。尽管这两种排序算法的时间复杂度都是 ,甚至堆排序比快速排序的时间复杂度还要稳定,但是,在实际的软件开发中,快速排序的性能要比堆排序好,这是为什么呢? 现在,你可能还无法回答,甚至对问题本身还有点疑惑。没关系,带着这个问题,我们来学习今天的内容。等你学完之后,或许就能回答出来了。如何理解“堆”?
Spring Boot 使用 Commons Logging 记录所有内部日志,但开放日志的底层实现。其为 Java Util Logging 、Log4J2 和 Logback 提供了默认配置。在每种情况下,日志记录器都预先配置为使用控制台输出,并且还提供可选的文件输出。 默认情况下,如果您使用了 Starter,则使用 Logback 进行日志记录。还包括合适的 Logback 路由,以确保在使用 Java Util Logging、Commons Logging、Log4J 或 SLF4J 的依赖库都能正常工作。
介绍 VuePress V2 是一个以 Markdown 为中心的静态网站生成器。你可以使用 Markdown在新窗口打开 来书写内容(如文档、博客等),然后 VuePress 会帮助你生成一个静态网站来展示它们。
本地分支 和 branch 命令 Git 鼓励开发者频繁使用分支,正是因为有着这些特性作保障。Git 是如何知道你当前在哪个分支上工作的呢?其实答案也很简单,它保存着一个名为 HEAD 的特别指针。(译注:将 HEAD 想象为当前分支的别名。)
Git 安装 Linux 上安装 Git 首先,你可以试着输入 Git,看看系统有没有安装 Git。有很多 Linux 系统会友好地告诉你 Git 没有安装,还会告诉你如何安装 Git。如果你碰巧用 Debian 或 Ubuntu,通过一条 sudo apt-get install git 就可以直接完成 Git 的安装。 如果使用的是 centos 或 reahat, 通过这条命令
.gitignore 介绍 在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。 虽然 gitignore 文件对Git有特殊的意义,但是它和版本库中任何其他普通文件都是同样管理的。除非把 gitignore 添加到索引中,否则 Git 仍会把它当成未追踪的文件。
问题分析 : could not lock config file %HOMEDRIVE%%HOMEPATH%/.gitconfig 的问题 在我的电脑上 HOME 的值是 %HOMEDRIVE%%HOMEPATH% 竟然不识别。已知 %homedrive% 指操作系统所在盘默认为C:,%HOMEPATH% 指的是用户所在目录,举例说明\Users\zhangsan。 所以手动改成 C:\Users\hp 即可。
Spring 框架的功能被有组织的分散到约 20 个模块中。这些模块分布在核心容器,数据访问/集成,Web,AOP(面向切面的编程),植入(Instrumentation),消息传输和测试,如下面的图所示。
Spring 配置的三种方案 在XML中进行显式配置。 隐式的 bean 发现机制和自动装配。 在 Java 中进行显式配置。
文字特效 <script type="text/javascript"> var a_idx = 0; jQuery(document).ready(function($) { $("body").click(function(e) { var a = new Array("❤学习","❤奥利给","❤干就完事","❤一giao我里giaogiao"); var $i = $("<span></span>").text(a[a_idx]); a_idx = (a_idx + 1) % a.length; var x =
个性化 settings.xml 配置 Settings.xml中包含类似本地仓储位置、修改远程仓储服务器、认证信息等配置。 settings.xml文件位置 settings.xml文件一般存在于两个位置: 全局配置: ${M2_HOME}/conf/settings.xml 用户配置: 𝑢𝑠𝑒𝑟.ℎ𝑜𝑚𝑒/.𝑚2/𝑠𝑒𝑡𝑡𝑖𝑛𝑔𝑠.𝑥𝑚𝑙𝑛𝑜𝑡𝑒:用户配置优先于全局配置。{user.home} 和和所有其他系统属性只能在3.0+版本上使用。请注意 windows 和 Linux 使用变量的区别。
构建配置文件的类型 全局(Global) 定义在 Maven 全局的设置 xml 文件中 (%MAVEN_HOME%/conf/settings.xml) 用户级 (Per User) 定义在Maven的设置 xml 文件中 项目级(Per Project) 定义在项目的POM文件 pom.xml 中
POM 参考 Maven – POM Reference http://maven.apache.org/pom.html <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</model
依赖管理是 Maven 的一个核心特性。管理单个项目的依赖关系非常简单。管理由数百个模块组成的多模块项目和应用程序的依赖关系是可能的。Maven 使用定义良好的类路径和库版本在定义、创建和维护可重复的构建方面帮助很大。
Maven 构建生命周期定义了一个项目构建跟发布的过程。 Maven defines 3 lifecycles in META-INF/plexus/components.xml。 一个典型的 Maven 构建(build)生命周期是由以下几个阶段的序列组成的: 。
核心 Plugin Clean Plugin The Clean Plugin is used when you want to remove files generated at build-time in a project's directory. 跳过 Clean
自动化构建和发布 项目开发过程中,部署的过程包含需如下步骤: 将所的项目代码提交到 SVN 或者代码库中并打上标签。 从 SVN 上下载完整的源代码。 构建应用。 存储构建输出的 WAR 或者 EAR 文件到一个常用的网络位置下。 从网络上获取文件并且部署文件到生产站点上。 更新文档并且更新应用的版本号。
遇到的问题 Maven 错误:was cached in the local repository, resolution will not be reattempted until the update
Create the directory structure mkdir -p src/main/java/hello on *nix systems └── src └── main └── java └── hello create these two classes: HelloWorld.java and Greeter.java. src/main/java/hello/HelloWorld.java
Java中 Character、String、StringBuilder 等类用于文本处理,它们的基础都是 char。 字符编码基础 ASCII 码 最高位设置为 0,用剩下的 7 位表示字符。这 7 位可以看作数字 0~127。 数字 32~126 表示的字符都是可打印字符,0~31 和 127 表示不可以打印的字符,这些字符一般用于控制目的,这些字符中大部分都是不常用的。数字 32~126 的含义,如图2-1所示,除了中文之外,我们平常用的字符基本都涵盖了,键盘上的字符大部分也都涵盖了。
我们先来看一些基本概念,然后再介绍 Java 的日期和时间 API。关于日期和时间,有一些基本概念,包括时区、时刻、纪元时、年历等。 全球一共有 24 个时区,英国格林尼治是 0 时区,北京是东八区,也就是说格林尼治凌晨 1 点,北京是早上 9 点。0 时区的时间也称为 GMT+0 时间,GMT 是格林尼治标准时间,北京的时间就是 GMT+8:00。 所有计算机系统内部都用一个整数表示时刻,这个整数是距离格林尼治标准时间1970年1月1日0时0分0秒的毫秒数。为什么要用这个时间呢?更多的是历史原因。 格林尼治标准时间 1970年1月1日0时0分0秒也被称为 Epoch Time(纪元时)
DTD 教程 文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
背景 使用哪种 Shell Bash 是唯一允许可执行程序使用的 shell / 脚本语言。 可执行文件必须以 #!/bin/bash 开头和最少数量的标志。 使用 set 设置 shell 选项,以便将脚本调用为 bash 脚本名称不会破坏其功能。
Bitmap 的使用 高效加载大位图 解码大的 bitmap,然后加载一个较小的图片到内存中去,从而避免超出程序的内存限制。
MariaDB Community Server 是一个开源的关系数据库服务器,深受全世界开发者的喜爱。由 MySQL 的原始开发者创建,MariaDB 与 MySQL 兼容,并保证永远保持开源。为一些世界上最受欢迎的网站提供动力,比如维基百科和 WordPress.com。它也是全球很多银行、社交媒体、移动和电子商务网站背后的核心引擎。
包含视图、函数知识、防止 SQL 注入攻击等内容。 SQL 函数 简介 大多数 SQL 实现支持以下类型的函数。 ❑ 用于处理文本字符串(如删除或填充值,转换值为大写或小写)的文本函数。❑ 用于在数值数据上进行算术操作(如返回绝对值,进行代数运算)的数值函数。 ❑ 用于处理日期和时间值并从这些值中提取特定成分(如返回两个日期之差,检查日期有效性)的日期和时间函数。 ❑ 用于生成美观好懂的输出内容的格式化函数(如用语言形式表达出日期,用货币符号和千分位表示金额)。 ❑ 返回 DBMS 正使用的特殊信息(如返回用户登录信息)的系统函数 SQL 函数不区分大小写。随你的喜好,不过注意保持风格一致
Windows 上安装 MySQL MySQL 下载地址为: MySQL 下载 。 这里我们挑选 MySQL Community Server。拿到压缩包后我们将进行解压后配置启动。这里我将解压后的文件夹放在 C:\web\mysql-8.0.11 下。 打开刚刚解压的文件夹 C:\web\mysql-8.0.11 ,在该文件夹下创建 my.ini 配置文件,编辑 my.ini 配置以下基本信息:
DQL:(Data QueryLanguage)数据查询语言(操作数据) select ... from ... where DML:(Data Manipulation Language)数据操纵语言(可以控制事务的提交、操作数据) insert、update、delete DDL:(Data Definition Language)数据库模式定义语言(隐式提交事务、操作数据库、表) create databse、create table、create view、create index、alter table、alter view、drop table、drop view、trunca
TwelveMonkeys ImageIO 通过 javax.imageio.* 包的插件为 Java 平台提供扩展图像文件格式支持。 注意,GIF、 PNG 和 WBMP 格式已经通过 ImageIO API 支持,使用的是 JDK 标准插件。对于 BMP、 JPEG 和 TIFF 格式,TwelveMonkeys 插件提供了扩展格式支持和其他特性。
全量查询语句 SELECT column_name, function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name HAVING xxx ORDER BY column_name1; LIMIT 5
AUTO_INCREMENT 详解 MySQL 中最简单使用序列的方法就是使用 AUTO_INCREMENT 来定义序列。 CREATE TABLE insect -> ( -> id INT UNSIGNED NOT NULL AUTO_INCREMENT, -> PRIMARY KEY (id), ...
由于项目组规定每次发布版本需要记录文件变动差异,于是乎自学了一些 Windows 批处理内容,写了个批处理脚本方便统计。
前提:在一台已经安装了 docker 的机器上,即可使用 docker + 子命令的方式。 通过运行 hello-world 映像来验证是否正确安装了 Docker Engine-Community 。 sudo docker run hello-world Docker 允许你在容器内运行应用程序, 使用 docker run 命令来在容器内运行一个应用程序。 输出 Hello world
redis 键操作 keys key-pattern:返回匹配的 key 列表,比如:keys foo* 表示查找 foo 开头的 keys。 keys my* 查看所有键 keys* 其中,pattern 可以用 “?” 来代替一位字符,用“*”来匹配零个、一个或多个字符,还可以用正则表达式的方式来匹配(模式匹配)。keys *命令虽然可以返回所有的键,但是在项目里键的数量一般会很多,全部返回没有意义,所以一般不怎么使用。 返回当前数据库的 key 的总数。
客户端设置 通过 redis-cli 命令连接到 Redis 服务器以后,可以通过本节给出的命令来管理该连接对应的客户端,具体包括获取并设置客户端的名字、获取客户端的信息、暂停执行客户端的命令以及关闭该客户端的连接。
约束 约束(constraint)管理如何插入或处理数据库数据的规则。 主键约束 表中任意列只要满足以下条件,都可以用于主键。 ❑ 任意两行的主键值都不相同。 ❑ 每行都具有一个主键值(即列中不允许NULL值)。 ❑ 包含主键值的列从不修改或更新。(大多数 DBMS 不允许这么做,但如果你使用的 DBMS 允许这样做,好吧,千万别!) ❑ 主键值不能重用。如果从表中删除某一行,其主键值不分配给新行。
docker 镜像 查找镜像 search 我们可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为: https://hub.docker.com/ 我们也可以使用 docker search 命令来搜索镜像。比如我们需要一个 httpd 的镜像来作为我们的 web 服务。我们可以通过 docker search 命令搜索 httpd 来寻找适合我们的镜像。 搜索镜像