<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[Double____C的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/Double____C</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; Double____C]]></copyright><item><title><![CDATA[算法系列--贪心算法]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/115287618</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/115287618</guid><author>Double____C</author><pubDate>Sun, 28 Mar 2021 22:45:38 +0800</pubDate><description><![CDATA[一、贪心算法
  上一节讲了动态规划，这里再讲一个和动态规划相似的算法，有时候也很容易搞混，即贪心算法。
  贪心算法和动态规划算法，都是用来求解最优化问题。但是在很多问题上，使用动态规划会有大炮打蚊子的感觉，而且使用贪心算法可以使问题更简单化。
  贪心算法，会做出局部最优的解，然后利用局部的解，得到全局的最优解。贪心算法的两个关键要素：

贪心选择性质
最优子结构

下面将介绍下这两个关键要素
二、贪心选择性质
  贪心选择性质，是贪心算法区别于动态规划的一个重要要素之一。贪心算法通常采用自顶向下，每做]]></description><category></category></item><item><title><![CDATA[算法系列--动态规划]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/115055826</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/115055826</guid><author>Double____C</author><pubDate>Sat, 27 Mar 2021 21:48:31 +0800</pubDate><description><![CDATA[一、动态规划
  动态规划，dynamic programming。其实还是蛮头疼的，写这句话的时候也还没有完全搞懂，写这篇希望自己也可以彻底搞懂动态规划的套路。
  动态规划，通常用来求解最优化问题，是通过组合子问题的解来求解原问题，与分治方法很相似。虽然都是将一个问题拆分为一堆更小的子问题，但动态规划更强调的是拆分出的子问题是否可以被重复调用。这样，对每一个子问题的计算结果保存起来，避免不必要的计算。
  所以，其实动态规划的本质是穷举法，求解最优化问题，必然会将所有结果都结算出来，比较最值。但动态规划]]></description><category></category></item><item><title><![CDATA[Java8新特性]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/110881426</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/110881426</guid><author>Double____C</author><pubDate>Sun, 13 Dec 2020 18:59:10 +0800</pubDate><description><![CDATA[Java8在平时工作中被普及的越来越多了，而且Java8也是Java的一次重大版本升级。平时工作中的项目都已经使用了jdk1.8版本，但是关于新特性基本没怎么用到，鉴于平时工作时开始慢慢推行Java8新特性编程，面试中有时候也会涉及到这方面的问题。在此做一个总结，希望自己能有所提高也能帮助别人。
一、Lambda表达式
先看一个lambda表达式的简单例子
//老版本
List&lt;String&gt; fruits = Arrays.asList("apple", "banana", "orange",]]></description><category></category></item><item><title><![CDATA[Spring Security实战--（五）认证和鉴权过程]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/105038001</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/105038001</guid><author>Double____C</author><pubDate>Thu, 02 Apr 2020 22:41:00 +0800</pubDate><description><![CDATA[标准的身份验证方案：

用户使用用户名和密码登录；
系统验证用户的额密码正确，成功登录；
获取该用户的上下文，即该用户的角色列表；
为用户建立安全的上下文
用户可能会继续执行某些操作，该操作可能会受到访问控制机制的保护，该访问控制机制会根据当前安全上下文信息检查该操作所需的权限

其中，前四个步骤构成了认证过程，在SpringSecurity中流程如下：

获取用户名和密码，并将其组合到一个Use...]]></description><category></category></item><item><title><![CDATA[Spring Security实战--（四）密码加密]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/104933777</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/104933777</guid><author>Double____C</author><pubDate>Sun, 22 Mar 2020 15:25:36 +0800</pubDate><description><![CDATA[一、密码安全的重要性
密码加密是一个很重要的安全性问题，当数据库存储密码时，应该使用可以安全存储用户密码的意识，防止数据库的明文密码泄露造成严重灾难
二、加密机制
PasswordEncoder接口
public interface PasswordEncoder {

	/**
	 * 加密过程
	String encode(CharSequence rawPassword);

	/**
	 ...]]></description><category></category></item><item><title><![CDATA[Spring Security实战--（三）图形验证实现]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/104808492</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/104808492</guid><author>Double____C</author><pubDate>Sun, 15 Mar 2020 19:07:18 +0800</pubDate><description><![CDATA[一、图形验证码
上一节实现了自定义数据库的验证，这里使用过滤器实现图形验证码。图形验证码也是登录时，常用的项目之一。
这里使用验证码(CAPTCHA)，验证码就是为了防止恶意用户暴力重试而设置的，防止恶意用户使用程序发起无限重试，使系统遭到破坏
二、图形验证码实现
2.1 图形验证码添加
这里使用kaptcha组件来获取验证码
添加依赖

...]]></description><category></category></item><item><title><![CDATA[Spring Security实战--（二）数据库实现]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/104643280</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/104643280</guid><author>Double____C</author><pubDate>Wed, 11 Mar 2020 21:55:17 +0800</pubDate><description><![CDATA[一、数据库的实现
Spring Security提供了默认数据库模板和自定义数据库两种方式
二、默认数据库
2.1 不同权限controller建立
建立下相关controller，为不同权限做准备

代码如下，注释已经解释清楚了，就不多说了
@RestController
@RequestMapping("admin/api")
public class AdminController {

 ...]]></description><category></category></item><item><title><![CDATA[Spring Security实战--（一）简单Security应用]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/104621345</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/104621345</guid><author>Double____C</author><pubDate>Tue, 03 Mar 2020 22:16:46 +0800</pubDate><description><![CDATA[123
一、Spring Security简介
应用程序的安全性通常体现在两个方面：认证和授权
认证是确认某主题在某系统中是否合法、可用的过程。这里的主题既可以是登录系统的用户，也可以是接入的设备或者其他系统
授权是指当主体通过认证后，是否允许其执行某项操作的过程，认证和授权是应用安全的基本关注点

...]]></description><category></category></item><item><title><![CDATA[并发源码解析（七）--Semaphore]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102629664</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102629664</guid><author>Double____C</author><pubDate>Sat, 19 Oct 2019 10:58:09 +0800</pubDate><description><![CDATA[一、Semaphore
Semaphore信号量–同CountDownLatch和CycleBarrier类似，但是它的计时器是递增的。
二、源码分析
2.1 继承关系

有3个内部类，实现了公平锁和非公平锁，关系如下。会不会有点眼熟，很像ReentrantLock的公平锁和非公平锁的实现。



2.2 属性
属性很简单
private static final long serialVersi...]]></description><category></category></item><item><title><![CDATA[并发源码解析（六）--CyclicBarrier]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102622255</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102622255</guid><author>Double____C</author><pubDate>Fri, 18 Oct 2019 16:01:49 +0800</pubDate><description><![CDATA[一、CyclicBarrier
CyclicBarrier–回环屏障：有点类似于CountDownLatch，但是比CountDownLatch更厉害一点。CountDownLatch是一次性的计数器，计数到0就会立刻返回。而CyclicBarrier的计数器达到0了之后可以重用。
二、源码分析
2.1 继承关系
无
2.2 属性
   /** 可以看出基于独占锁实现 */
    private...]]></description><category></category></item><item><title><![CDATA[并发源码解析（五）--CountDownLatch]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102618812</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102618812</guid><author>Double____C</author><pubDate>Fri, 18 Oct 2019 11:18:52 +0800</pubDate><description><![CDATA[一、CountDownLatch

]]></description><category></category></item><item><title><![CDATA[并发源码解析（四）--ReentrantLock]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102610950</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102610950</guid><author>Double____C</author><pubDate>Thu, 17 Oct 2019 20:08:42 +0800</pubDate><description><![CDATA[一、ReentrantLock
ReentrantLock是可重入的独立锁，同时只能有一个线程可以获取该锁，其他获取该锁的线程会被阻塞而被加入该锁的AQS阻塞队列里面。
可以实现公平锁和非公平锁
二、源码分析
2.1 继承关系

实现了lock接口和序列化接口

还有3个静态内部类
其中的关系如下：


其中Sync的lock方法为抽象方法，交给子类去实现
2.2 构造方法
无参构造方法
publ...]]></description><category></category></item><item><title><![CDATA[并发源码解析（三）--AQS条件队列]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102601576</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102601576</guid><author>Double____C</author><pubDate>Thu, 17 Oct 2019 15:22:26 +0800</pubDate><description><![CDATA[一、条件队列
AQS的一个锁可以对应多个条件变量。使用时先使用lock.newCondition()来new出来一个在AQS内部声明的ConditionObject对象，ConditionObject是AQS的内部类，可以访问AQS内部的变量和方法。而在每个条件变量内部都维护了一个条件队列，用来存放调用条件变量的await()方法时被阻塞的线程。
这个条件队列和AQS队列不是一样东西！
二、源码分...]]></description><category></category></item><item><title><![CDATA[并发源码解析（一）--抽象同步队列AQS]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102582421</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102582421</guid><author>Double____C</author><pubDate>Thu, 17 Oct 2019 09:05:15 +0800</pubDate><description><![CDATA[一、AQS
AQS，即AbstractQueuedSynchronizer抽象同步队列，是实现同步器的基础组件，并发包中锁的底层就是使用AQS实现的，因此这个类非常重要。
因此在谈到并发包的源码时，先讲一下AQS
二、源码分析
2.1


可以看到AQS继承了AbstractOwnableSynchronizer。由线程独占的同步器，这个类为创建锁和相关同步器提供了基础，这个类比较简单。
publ...]]></description><category></category></item><item><title><![CDATA[Java集合系列源码分析（八）-- TreeMap（红黑树）]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102572482</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102572482</guid><author>Double____C</author><pubDate>Tue, 15 Oct 2019 22:54:07 +0800</pubDate><description><![CDATA[一、TreeMap
TreeMap是有序的，可以实现自定义的比较器来决定升序还是降序。存储key-value，内部使用红黑树。
强烈建议先看之前的二叉搜索树和平衡二叉树，了解二叉搜索树和平衡二叉树再看这篇，否则红黑树有点难理解
二、TreeMap常用方法
2.1 属性


实现了NavigableMap接口，

而NavigableMap又继承于SortedMap，又此可知，这个map是有序的。因...]]></description><category></category></item><item><title><![CDATA[Java集合系列源码分析（七）-- 平衡二叉树]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102528209</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102528209</guid><author>Double____C</author><pubDate>Tue, 15 Oct 2019 17:01:28 +0800</pubDate><description><![CDATA[一、平衡二叉树
平衡二叉树（Balanced Binary Tree）是为了防止树的高度增长过快，出现类似于上一节最后举出的那种特殊情况，降低了二叉排序树的性能。
于是人们规定，保证任意节点的左、右子树高度差的绝对值不超过1，这样的二叉树成为平衡二叉树。

二、平衡二叉树的方法
首先，平衡二叉树操作中始终需要保持平衡，因此必须要准守平衡原则，平衡二叉树的平衡原则是：每次需要调整的都是最小不平衡二叉...]]></description><category></category></item><item><title><![CDATA[Java集合系列源码分析（六）-- 二叉查找树]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102524982</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102524982</guid><author>Double____C</author><pubDate>Sat, 12 Oct 2019 22:03:19 +0800</pubDate><description><![CDATA[之前讲了部分集合源码，有涉及到红黑树，一下就讲红黑树有点不好讲，先从简单点的树开始讲，以下就从二叉查找树开始讲
一、 二叉查找树
二叉查找树（Binar Search Tree），又称二叉搜索树，二叉排序树
二叉查找树特性：

若左子树非空，则左子树上所有的节点关键字值均小于根节点的关键字值
若右子树非空，则右子树上所有节点关键字值均大于根节点的关键字值
左右子树本身也分别是一颗二叉查找树

简单...]]></description><category></category></item><item><title><![CDATA[Java集合系列源码分析（四）--HashSet]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102500024</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102500024</guid><author>Double____C</author><pubDate>Fri, 11 Oct 2019 15:12:44 +0800</pubDate><description><![CDATA[一、HashSet
HashSet是基于HashMap实现的，他的方法比较简单，但是大部分方法都和HashMap有关。需要先了解HashMap在了解HashSet。关于HashMap在上一篇源码分析有介绍。
了解完HashMap再来看HashSet会发现其实HashSet会比较简单
二、源码分析
2.1 继承结构和分析


实现了Set接口，继承AbstractSet
2.2 HashSet属性
...]]></description><category></category></item><item><title><![CDATA[Java集合系列源码分析（三）--HashMap]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102475762</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102475762</guid><author>Double____C</author><pubDate>Thu, 10 Oct 2019 14:05:06 +0800</pubDate><description><![CDATA[一、HashMap
基于数组和链表实现的HashMap，当链表数据过多时，会转为红黑树提高查询效率。
实现采用了多种数据结构，所以HashMap在增删改查上的效率都很高，不考了哈希冲突时间复杂度可以达到O(1)
二、源码分析
2.1 继承结构和层次


实现了Map接口，克隆接口和序列化接口
2.2 HashMap属性
/**
 * 默认初始容量
 */
static final int DEFA...]]></description><category></category></item><item><title><![CDATA[Java集合系列源码分析（二）--LinkedList]]></title><link>https://blog.youkuaiyun.com/Double____C/article/details/102473821</link><guid>https://blog.youkuaiyun.com/Double____C/article/details/102473821</guid><author>Double____C</author><pubDate>Thu, 10 Oct 2019 10:06:58 +0800</pubDate><description><![CDATA[一、LinkedList
linkedlist底层是双向链表，插入和删除操作较快，查询和随机查询操作较慢。非线程安全。
二、源码分析
2.1 继承结构和层次


实现了序列化、克隆、list接口。
Deque：双端队列接口，扩展自Queue

2.2 LinkedList属性

//集合元素个数
transient int size = 0;

/**
 * 首节点指针
transient Nod...]]></description><category></category></item></channel></rss>