0%

ElasticSearch

概念

Elasticsearch 是一个免费且开放的分布式搜索和分析引擎,适用于包括文本、数字、地理空间、结构化和非结构化数据等在内的所有类型的数据。

es基于Restful风格,用于全文搜索以及文档搜索等。

倒排索引&正排索引

正排索引: 根据主键索引,去查询相关信息。

ps:对于t_desc表两个字端: id(主键)、desc。对desc进行模糊查询,就需要通过主键去遍历,这样效率就不会很高。

倒排索引:根据关键字(keyword)来查询主键。

索引操作

索引:Index,对于结构化数据库,就相当于所选择的数据库一样。

阅读全文 »

Xxl-job 使用

用于做定时任务。通过后台管理系统进行配置。

定义配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.cloudwise.dosm.dosm_call_center.config;

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
*
*
* @author
*/
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
/** 后台管理系统的地址 */
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;

@Value("${xxl.job.accessToken}")
private String accessToken;
/** 执行器的名称 */
@Value("${xxl.job.executor.appname}")
private String appname;

@Value("${xxl.job.executor.address}")
private String address;

@Value("${xxl.job.executor.ip}")
private String ip;
/** 执行器执行任务时访问的端口号 */
@Value("${xxl.job.executor.port}")
private int port;

@Value("${xxl.job.executor.logpath}")
private String logPath;

@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;

@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

return xxlJobSpringExecutor;
}
}

配置文件中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
xxl:
job:
enabled: true
admin:
addresses: http://{ip}:{port}/xxl-job/
user:
name: admin
password: Rwdd@Yzh_123
executor:
appname: ${spring.application.name}
logpath: logs/xxl-job
logretentiondays: 30
ip:
address:
port: 28389
accessToken: xxljob

使用

直接使用注解 @XxlJob

1
2
3
4
5
6
@XxlJob("fixData")
public void myHandler() {
log.info("myHandler execute xxl-job ... start");
service.fixData();
log.info("myHandler execute xxl-job ... end");
}

在xxljob后台管理上,选择对应的执行器名称,添加任务,jobHandler必须与所使用的注解后面的fixData相同

阅读全文 »

easyexcel的使用

easyescel官方文档:

1
https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read#%E5%A4%9A%E8%A1%8C%E5%A4%B4

依赖

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.3</version>
</dependency>

导入excel

  1. 配置监听器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.cloudwise.entity.VO.AuthManageExcelVO;
import com.cloudwise.entity.VO.AuthManageVO;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
* 填写具体类的描述
*
* @author: turbo.wu
* @since: 2022-11-15 17:32
**/
public class EasyExcelListener extends AnalysisEventListener {
// 指定读取的数据
private List<AuthManageExcelVO> data = new ArrayList<>();

/**
* 每读取一行就会调用这个方法,
* @param o 是每一行的数据,LinkHashMap key: 列号,从0开始 value: 值
*/
@Override
public void invoke(Object o, AnalysisContext analysisContext) {
System.out.println(o);
@SuppressWarnings("unchecked")
Map<Integer, String> map = (LinkedHashMap<Integer, String>) o;
AuthManageExcelVO authManageExcelVO = new AuthManageExcelVO();
// 生成数据
authManageExcelVO.setUmAccountName(map.getOrDefault(1, ""));
authManageExcelVO.setUsername(map.getOrDefault(2, ""));
authManageExcelVO.setDepartmentName(map.getOrDefault(3, ""));
authManageExcelVO.setHrPosition(map.getOrDefault(4, ""));
authManageExcelVO.setDirectSuperiorsName(map.getOrDefault(5, ""));
authManageExcelVO.setRoleName(map.getOrDefault(6, ""));
authManageExcelVO.setActuatorName(map.getOrDefault(7, ""));
authManageExcelVO.setExpiredDate(map.getOrDefault(8, ""));
authManageExcelVO.setApplyExplain(map.getOrDefault(9, ""));
this.data.add(authManageExcelVO);

}

@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {

}

public void setData(List<AuthManageExcelVO> data) {
this.data = data;
}

public List<AuthManageExcelVO> getData() {
return data;
}
}
  1. 使用EasyExcelFactory读取excel文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void importExcel(MultipartFile file) {
Inputstream inputStream = file.getInputStream();
/**
* 读取excel数据
*/
// 创建监听器对象
EasyExcelListener listener = new EasyExcelListener();
// 构建easyExcel读对象。 headRowNumber,指定从excel文件中的哪一行开始读,从0开始,这里是8,则是从第9行开始读起
ExcelReader excelReader = EasyExcelFactory.read(inputStream, listener).headRowNumber(8).build();
// 读取excel的sheet, 可以传入多个sheet, 使用new ReadSheet("传入sheetNo,从0开始",@Nullable("可以不传") "传入sheetName")
excelReader.read(new ReadSheet(0));
// 从监听器中获取暂存的数据, 这里数据的数据类型由你自己指定
List<AuthManageExcelVO> data = listener.getData();
System.out.println(data);
}
阅读全文 »

滑动窗口

leetCode 第3题 无重复字符的最长子串长度

在字符串中找到不重复字符的最长子串长度。

保证当前窗口的子串都是无重复的。

使用一个set来存放无重复的子串,在遍历模式串的过程中,如果下一个字符在set中存在,则说明出现重复字符了,此时将记录子串开始下标的指针后移,直到不会出现重复字符为止,在每次遍历结束后,都更新最长长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public int lengthOfLongestSubstring(String s) {
// 空字符串判断
if (s.length() == 0) return 0;
// 定义存放最长子串的set集合
Set<Character> set = new HashSet<>();
// 最大长度
int maxLength = 0;
// 指向子串开始字符的索引
int left = 0;
// 指向子串结束字符的索引
int right = 0;
// 循环结束条件,right到达字符串结尾
while (right < s.length()) {
// 如果set中不存在字符,则让right后移
if (! set.contains(s.charAt(right))) {
set.add(s.charAt(right++));
} else {
// 如果存在,right不动,排除掉与right所指向字符相同的字符
set.remove(s.charAt(left++));
}
// 每次结束都更新最大长度
maxLength = Math.max(set.size(), maxLength);
}
return maxLength;
}

leetCode 第567题 字符串排列

给你两个字符串 s1s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false

换句话说,s1 的排列之一是 s2子串

例如: s1: “ab” s2: “eidbaooo” 则返回true, ab的排列之一ba是s2的子串。

阅读全文 »

779 香槟塔

注意点: 下标都是从0开始的。

第一行: row=0。将所有的酒都倒入第一个杯子;

第二行: row=1。用第一行的酒-1,然后分别倒入第二行的两个杯子;

第三行: row=2。第二行有两个杯子,把第一个杯子的酒分别倒入第三行的0、1两个杯子中,第二个杯子分别倒入第三行的1、2两个杯子中。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public double champagneTower(int poured, int query_row, int query_glass) {
// 全部倒入第一个杯子中
double[] row = {poured};
// 从第二行开始
for (int i = 1; i <= query_row; i++) {
// 新建当前行的数组,每一行的杯子数量都是行数+1
double[] nextRow = new double[1+i];
// 遍历上一行的杯子
for (int j = 0; j < i; j ++) {
double v = row[j];
if (v > 1){
nextRow[j] += (v - 1) / 2;
nextRow[j+1] += (v - 1) / 2;
}
}
row = nextRow;
}
// 由于多的酒会洒到地上,杯子里面最多是满的。
return Math.min(1, row[query_glass]);
}
阅读全文 »

LC 第116题

给定一个完美二叉树,填充每一个节点的next指针。节点定义

1
2
3
4
5
6
class Node {
public int val;
public Node left;
public Node right;
public Node next;
}

方法一

基于广度优先搜索,不同的是,每次都取出一层的所有节点。遍历当前层数节点,将每个节点的next都指向当前队列中的节点,而最后一个指向null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public Node connect(Node root) {
// 非空判断
if (root == null) return null;
Queue<Node> queue = new LinkedList<>();
queue.offer(root);
while (! queue.isEmpty()) {
// 获取当前层数的节点数
int size = queue.size();
// 遍历当前层数
for (int i = 0; i < size; i ++) {
// 取出队首的节点
Node n = queue.poll();
// 当当前遍历的元素不是倒数第一个时,即i此时要小于size-1,则查看队头节点,并且把当前节点的next指向它
if (i < size - 1) {
Node head = queue.peek();
n.next = head;
}
// 将左右子节点放入队列中
if (n.left != null) {
queue.offer(n.left);
}

if (n.right != null) {
queue.offer(n.right);
}
}
}
return root;
}

方法二

当前节点为根节点时,next = null;

next都是由left 指向right的,而对于第三层开始,除了left.next = right之外, right.next = 上一节点.next.left

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Node connect(Node root) {
// 出口
if (root == null) return null;
// 判断当前节点的左节点是否为空,如果不为空的话就将left.next = right
if (root.left != null) {
root.left.next = root.right.next;
// 如果当前节点的next不为空
if (root.next != null) {
root.right.next = root.next.left;
}
}
// 递归
connect(root.left);
connect(root.right);
return root;
}
阅读全文 »

MVCC

​ MVCC,多版本并发控制,主要是为了解决读写冲突不加锁。这里所指的读是快照读。

​ 快照读和当前读就不解释了。

​ MVCC是一种较为抽象的概念。其意义是为了维持一个数据的多个版本。这样可以在不加锁的情况下,实现读写不冲突。

​ MVCC实现了事务的隔离级别。在mysql中MVCC的实现使用到了三个隐式字段read viewundo日志

阅读全文 »

​ 问的问题大致如下:

  1. spring处理请求的流程?

    springMVC的执行流程客户端发送一次请求,springMVC都会经过dispatchServlet来进行分发,先根据mapper映射url,找到对应的处理器,然后返回给dispatchServlet,在交给适配器进行适配,并找到对应的控制器,进行业务的执行,最后由视图模型进行渲染,返回给页面。。。

​ 2.spring的bean创建过程?

​ 主要是四个方法, getBean() – 从IOC容器中获取正在创建的bean,如果获取不到,进入bean定义

​ doCreateBean() – 创建bean

​ populate() –具体方法名忘记了, 对属性进行注入

​ add() — 加入到容器中

​ 大致是这个流程。。。

  1. 循环依赖?

    spring三级缓存

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    /** 一级缓存,bean初始化完成存放*/
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** 三级缓存,bean实例化完成存放 */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    /** 二级缓存 */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    1. redis的持久化方式,已经两种方式的区别。。

      正常回答。。。 rdb和aof rdb的持久化频率,在redis.conf中有写到。aof指令追加。。

    2. hashmap的底层以及红黑树的最大高度差,红黑树既然查找和插入效率都为logN为什么还需要链表。

      红黑树的特点: 同一路径不允许出现连续红, 从叶子节点出发每一条路径上的黑色节点都必须相同,所以对于一颗高度为k的红黑树,最大高度差是k/2,可能考虑到红黑树需要自旋。但是第二个问题确实答得不好,

      当链表节点个数达到8时,就会转换成红黑树,而当节点到6之后,就会转变成链表,链表的平均时间复杂度是N/2, 当节点个数为8时,此时时间复杂度红黑树为3,链表为4, 而当节点为6时,前者为lg6,后者为3,但是考虑到红黑树需要通过自旋来保证左右子树的节点相对平衡,并且为了防止红黑树和链表一直频繁转换

阅读全文 »

最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

这个和三数之和思路差不多。

​ 首先是数组进行排序

​ 不同的是,三个数之和靠近某一个值,并且直接返回最近的和。

​ 思路:

​ 还是通过三个指针,定义一个变量distance,表示三数之和sum与target的最小差。同样通过left和right指针,

left指向i+1,right指向数组尾。判断sum与target的差是否小于当前distance,如果是,则让distance等于当前差

​ 代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public int threeSumClosest(int[] nums, int target) {
//数组排序
Arrays.sort(nums);

//返回结果
int result = 0;
//表示当前最小差
int distance = Integer.MAX_VALUE;
for (int i=0; i < nums.length; i++) {
//两个指针
int left = i + 1;
int right = nums.length - 1;

while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum < target) { //说明left需要后移
if (target - sum < distance) {
distance = target - sum;
result = sum;
}
//left右移
left ++;
} else if (sum > target) {
if (sum - target < distance) {
distance = sum - target;
result = sum;
}
right --;
} else {
return target;
}
}
}

return result;
}
}
阅读全文 »

三数之和

​ leetcode上面的一道排序算法题。

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

思路:

​ 先将数组进行升序排序。。。

​ 一个数组中三个元素相加为0,可以通过三个指针来进行判断。一个指针i从数组第一个元素开始自增。另外两个指针分别为left、right。

​ 让left最开始指向i的下一个元素,即left=i+1。right指向最后,即right=nums.length-1

​ 判断此时 result = nums[i] + nums[right] + nums[left] 的值。如果result>0,由于数组是升序排序,那么说明要让result变小,则让right前移。如果result<0, 则让left右移,让值变大。 总而言之,就是让和趋近于0,直至等于0。一次循环中,直到left>=right,则循环结束。这就是为什么要让数组排序

​ 还有一个问题就是需要去重复,因为有可能会得到重复的结果。那么在下标不越界的情况下,让当前指针与前一个或者后一个值进行比较,如果相同,则结束本次循环。

​ 大概就是这个思路。代码如下

阅读全文 »