Compare commits
43 Commits
dev
...
fe1d9d913c
| Author | SHA1 | Date | |
|---|---|---|---|
| fe1d9d913c | |||
| 166fe7fe9a | |||
| aaccb2114b | |||
| b7da6e9537 | |||
| 1b2a33d72d | |||
| bbd5275855 | |||
| b254db3bc0 | |||
| e575b8b94b | |||
| 850c0d3dc3 | |||
| 10e6dbf415 | |||
| 497732614d | |||
| f1a6584fcd | |||
| db57411ca1 | |||
| 09d2c4899b | |||
| 19d4bf9dee | |||
| 4cd72cd4f2 | |||
| 6cfb4fd37e | |||
| 4c3ee5fcf4 | |||
| 3c8752be70 | |||
| 226c572e59 | |||
| 4a6bd38732 | |||
| beb3a22fdd | |||
| 0f081ad1db | |||
| de07e89bb8 | |||
| e230636a54 | |||
| 83d334356b | |||
| f69a0267c4 | |||
| 987e56909c | |||
| 3aaabd8b6d | |||
| 1b10985030 | |||
| c72ced990f | |||
| 9107b0c4ba | |||
| 4bacec63a3 | |||
| 78d8ad252b | |||
| d51106271e | |||
| 947d81a5b5 | |||
| af2221682c | |||
| 8f2e5d0b62 | |||
| dba3de0be2 | |||
| 42da65cf47 | |||
| aa73622a34 | |||
| f601c051d4 | |||
| 9d6a001b85 |
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2020 xrv <xrg@live.com>
|
||||
Copyright © 2022 xrv <xrv@live.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -6,3 +6,7 @@
|
||||
[](https://github.com/ehlxr/budd/releases)
|
||||
|
||||
常用的一些 Java 代码
|
||||
|
||||
## Thanks to the following organizations for providing open source licenses
|
||||
|
||||
[<img src="https://cdn.ehlxr.top/jetbrains.png" width = "200" height = "217" alt="jetbrains" align=center />](https://jb.gg/OpenSource)
|
||||
21
SECURITY.md
21
SECURITY.md
@@ -1,21 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 5.1.x | :white_check_mark: |
|
||||
| 5.0.x | :x: |
|
||||
| 4.0.x | :white_check_mark: |
|
||||
| < 4.0 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Use this section to tell people how to report a vulnerability.
|
||||
|
||||
Tell them where to go, how often they can expect to get an update on a
|
||||
reported vulnerability, what to expect if the vulnerability is accepted or
|
||||
declined, etc.
|
||||
43
budd-common/pom.xml
Normal file
43
budd-common/pom.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>budd-common</artifactId>
|
||||
<name>budd-common</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-12-28 23:16.
|
||||
*/
|
||||
public class FindKthLargest {
|
||||
public static void main(String[] args) {
|
||||
int[] nums = new int[]{3, 2, 1, 5, 6, 4};
|
||||
System.out.println(findKthLargest(nums, 2));
|
||||
}
|
||||
|
||||
public static int findKthLargest2(int[] nums, int k) {
|
||||
for (int i = nums.length / 2 - 1; i >= 0; i--) {
|
||||
// 从第一个非叶子结点从下至上,从右至左调整结构
|
||||
adjustHeap(nums, i, nums.length);
|
||||
}
|
||||
|
||||
for (int j = nums.length - 1; j >= 0; j--) {
|
||||
k--;
|
||||
|
||||
if (k == 0) {
|
||||
return nums[0];
|
||||
}
|
||||
|
||||
swap(nums, 0, j);
|
||||
adjustHeap(nums, 0, j);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void adjustHeap(int[] arr, int i, int length) {
|
||||
// 先取出当前元素 i
|
||||
int temp = arr[i];
|
||||
// 从 i 结点的左子结点开始,也就是 2i+1 处开始
|
||||
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
|
||||
// 如果左子结点小于右子结点,k 指向右子结点
|
||||
if (k + 1 < length && arr[k] < arr[k + 1]) {
|
||||
k++;
|
||||
}
|
||||
// 如果子节点大于父节点,将子节点和父节点交换
|
||||
// if (arr[k] > arr[i]) {
|
||||
// swap(arr, k, i);
|
||||
if (arr[k] > temp) {
|
||||
// 不用进行交换
|
||||
arr[i] = arr[k];
|
||||
|
||||
i = k;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 将 temp 值放到最终的位置
|
||||
arr[i] = temp;
|
||||
}
|
||||
|
||||
|
||||
public static int findKthLargest(int[] nums, int k) {
|
||||
if (nums == null || nums.length < k) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int q = partition(nums, 0, nums.length - 1);
|
||||
while (q + 1 != k) {
|
||||
if (k < q + 1) {
|
||||
q = partition(nums, 0, q - 1);
|
||||
} else {
|
||||
q = partition(nums, q + 1, nums.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return nums[q];
|
||||
}
|
||||
|
||||
|
||||
public static int partition(int[] a, int p, int r) {
|
||||
int pivot = a[r];
|
||||
int i = p;
|
||||
for (int j = p; j < r; j++) {
|
||||
if (a[j] >= pivot) {
|
||||
swap(a, i++, j);
|
||||
}
|
||||
}
|
||||
|
||||
swap(a, i, r);
|
||||
return i;
|
||||
}
|
||||
|
||||
private static void swap(int[] a, int i, int j) {
|
||||
if (i == j) {
|
||||
return;
|
||||
}
|
||||
int temp = a[i];
|
||||
a[i] = a[j];
|
||||
a[j] = temp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.binarytree.heap;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2022-03-15 07:40.
|
||||
*/
|
||||
public class Heap {
|
||||
private static void createHeap(int[] a) {
|
||||
int n = a.length - 1; // 最后一个叶子节点下标
|
||||
buildHeap(a, n);
|
||||
}
|
||||
|
||||
private static void buildHeap(int[] a, int n) {
|
||||
// (n - 1) / 2 表示最后一个叶子节点父节点,即为最后一个非叶子节点
|
||||
for (int i = (n - 1) / 2; i >= 0; --i) {
|
||||
heapify(a, n, i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 堆化
|
||||
*
|
||||
* @param a 数组
|
||||
* @param n 最后一个元素下标
|
||||
* @param i 需要调整的父节点下标
|
||||
*/
|
||||
private static void heapify(int[] a, int n, int i) {
|
||||
while (true) {
|
||||
int max = i;
|
||||
|
||||
// 从当前节点和左右叶子节点中找出最大的
|
||||
int l = 2 * i + 1;
|
||||
if (l <= n && a[l] > a[max]) {
|
||||
max = l;
|
||||
}
|
||||
|
||||
int r = 2 * i + 2;
|
||||
if (r <= n && a[r] > a[max]) {
|
||||
max = r;
|
||||
}
|
||||
|
||||
// 当前节点最大时退出
|
||||
if (max == i) {
|
||||
break;
|
||||
}
|
||||
|
||||
swap(a, i, max);
|
||||
|
||||
// 最大节点和当前节点交换后,继续以当前节点为父节点堆化
|
||||
i = max;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 堆排序
|
||||
*/
|
||||
private static void sort(int[] a) {
|
||||
for (int i = a.length - 1; i > 0; i--) {
|
||||
buildHeap(a, i);
|
||||
// 堆顶元素和最后一个元素交换,除过最后一个元素外其它元素再次构建大顶堆
|
||||
swap(a, 0, i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] arr = new int[]{1, 2, 3, 4, 5, 6};
|
||||
createHeap(arr);
|
||||
System.out.println(Arrays.toString(arr));
|
||||
|
||||
sort(arr);
|
||||
System.out.println(Arrays.toString(arr));
|
||||
|
||||
}
|
||||
|
||||
private static void swap(int[] arr, int i, int j) {
|
||||
int tmp = arr[i];
|
||||
arr[i] = arr[j];
|
||||
arr[j] = tmp;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,42 +22,44 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.leetcode;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.PriorityQueue;
|
||||
package io.github.ehlxr.algorithm.dp;
|
||||
|
||||
/**
|
||||
* 在一个数组 arr 中,找出一组不相邻的数字,使得最后的和最大
|
||||
* <p>
|
||||
* 图解 https://cdn.jsdelivr.net/gh/0vo/oss/images/dp.jpg
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2020-10-20 17:54.
|
||||
* @since 2021-10-31 22:46.
|
||||
*/
|
||||
public class Solution5 {
|
||||
|
||||
public int findKthLargest(int[] nums, int k) {
|
||||
PriorityQueue<Integer> queue = new PriorityQueue<>();
|
||||
for (int val : nums) {
|
||||
queue.add(val);
|
||||
if (queue.size() > k) {
|
||||
queue.poll();
|
||||
}
|
||||
public class FindMaxSum {
|
||||
public static int recOpt(int[] arr, int i) {
|
||||
if (i == 0) {
|
||||
return arr[0];
|
||||
} else if (i == 1) {
|
||||
return Math.max(arr[0], arr[1]);
|
||||
} else {
|
||||
int a = recOpt(arr, i - 2) + arr[i];
|
||||
int b = recOpt(arr, i - 1);
|
||||
return Math.max(a, b);
|
||||
}
|
||||
return queue.peek();
|
||||
}
|
||||
|
||||
public static int dpOpt(int[] arr) {
|
||||
int[] opt = new int[arr.length];
|
||||
opt[0] = arr[0];
|
||||
opt[1] = Math.max(arr[0], arr[1]);
|
||||
for (int i = 2; i < opt.length; i++) {
|
||||
int a = opt[i - 2] + arr[i];
|
||||
int b = opt[i - 1];
|
||||
opt[i] = Math.max(a, b);
|
||||
}
|
||||
return opt[arr.length - 1];
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] arr = {4, 6, 8, 5, 9};
|
||||
// PriorityQueue<Integer> queue = new PriorityQueue<>();
|
||||
// for (int val : arr) {
|
||||
// queue.add(val);
|
||||
// }
|
||||
// System.out.println(Arrays.toString(queue.toArray()));
|
||||
//
|
||||
//
|
||||
// arr = new int[]{4, 6, 8, 5, 9};
|
||||
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(arr.length, (o1, o2) -> o2 - o1);
|
||||
for (int val : arr) {
|
||||
maxHeap.add(val);
|
||||
}
|
||||
System.out.println(Arrays.toString(maxHeap.toArray()));
|
||||
int[] arr = {4, 1, 1, 9, 1};
|
||||
System.out.println(dpOpt(arr));
|
||||
System.out.println(recOpt(arr, arr.length - 1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.dp;
|
||||
|
||||
/**
|
||||
* 对于一组不同重量、不同价值、不可分割的物品,我们选择将某些物品装入背包,在满足背包最大重量限制的前提下,背包中可装入物品的总价值最大是多少呢?
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2022-03-05 14:31.
|
||||
*/
|
||||
public class KnapSack {
|
||||
private final int[] weight = {2, 2, 4, 6, 3}; // 物品的重量
|
||||
private final int[] value = {3, 4, 8, 9, 6}; // 物品的价值
|
||||
private final int n = 5; // 物品个数
|
||||
private final int w = 9; // 背包承受的最大重量
|
||||
private int maxV = Integer.MIN_VALUE; // 结果放到 maxV 中
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(knapsack3(new int[]{2, 2, 4, 6, 3}, new int[]{3, 4, 8, 9, 6}, 5, 9));
|
||||
System.out.println(knapsack(new int[]{2, 2, 4, 6, 3}, new int[]{3, 4, 8, 9, 6}, 5, 9));
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态规划方式
|
||||
*
|
||||
* @param weight 物品重量
|
||||
* @param value 物品的价值
|
||||
* @param n 物品个数
|
||||
* @param w 背包可承载重量
|
||||
* @return 最大价值
|
||||
*/
|
||||
public static int knapsack(int[] weight, int[] value, int n, int w) {
|
||||
int[][] dp = new int[][];
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态规划方式
|
||||
*
|
||||
* @param weight 物品重量
|
||||
* @param value 物品的价值
|
||||
* @param n 物品个数
|
||||
* @param w 背包可承载重量
|
||||
* @return 最大价值
|
||||
*/
|
||||
public static int knapsack3(int[] weight, int[] value, int n, int w) {
|
||||
int[][] states = new int[n][w + 1];
|
||||
for (int i = 0; i < n; ++i) { // 初始化 states,默认 -1
|
||||
for (int j = 0; j < w + 1; ++j) {
|
||||
states[i][j] = -1;
|
||||
}
|
||||
}
|
||||
states[0][0] = 0;
|
||||
if (weight[0] <= w) {
|
||||
states[0][weight[0]] = value[0];
|
||||
}
|
||||
for (int i = 1; i < n; ++i) { // 动态规划,状态转移
|
||||
for (int j = 0; j <= w; ++j) { // 不选择第 i 个物品
|
||||
if (states[i - 1][j] >= 0) {
|
||||
// 复制上一层状态
|
||||
states[i][j] = states[i - 1][j];
|
||||
}
|
||||
}
|
||||
// 下面的 j 表示重量
|
||||
for (int j = 0; j <= w - weight[i]; ++j) { // 选择第 i 个物品
|
||||
if (states[i - 1][j] >= 0) { // 表示上一层存在重量为 j 的状态
|
||||
int v = states[i - 1][j] + value[i]; // 上一层重量为 j 的价值 + i 物品的价值
|
||||
if (v > states[i][j + weight[i]]) { // states[i][j + weight[i]]:存储当前重量 j + 物品 i 的重量所在位置的价值
|
||||
states[i][j + weight[i]] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 找出最大值
|
||||
int maxvalue = -1;
|
||||
for (int j = 0; j <= w; ++j) {
|
||||
if (states[n - 1][j] > maxvalue) {
|
||||
maxvalue = states[n - 1][j];
|
||||
}
|
||||
}
|
||||
return maxvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回溯方式
|
||||
*
|
||||
* @param i 第几个物品
|
||||
* @param cw 物品的重量
|
||||
* @param cv 物品的价值
|
||||
*/
|
||||
public void f(int i, int cw, int cv) { // 调用 f (0, 0, 0)
|
||||
if (cw == w || i == n) { //cw==w 表示装满了,i==n 表示物品都考察完了
|
||||
if (cv > maxV) {
|
||||
maxV = cv;
|
||||
}
|
||||
return;
|
||||
}
|
||||
f(i + 1, cw, cv); // 选择不装第 i 个物品
|
||||
if (cw + weight[i] <= w) {
|
||||
f(i + 1, cw + weight[i], cv + value[i]); // 选择装第 i 个物品
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.dp;
|
||||
|
||||
/**
|
||||
* 假设我们有一个 n 乘以 n 的矩阵 w [n][n]。矩阵存储的都是正整数。棋子起始位置在左上角,终止位置在右下角。
|
||||
* 我们将棋子从左上角移动到右下角。每次只能向右或者向下移动一位。从左上角到右下角,会有很多不同的路径可以走。
|
||||
* 我们把每条路径经过的数字加起来看作路径的长度。那从左上角移动到右下角的最短路径长度是多少呢?
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2022-03-05 16:46.
|
||||
*/
|
||||
public class MinDist {
|
||||
|
||||
private final int[][] matrix = {{1, 3, 5, 9}, {2, 1, 3, 4}, {5, 2, 6, 7}, {6, 8, 4, 3}};
|
||||
private final int[][] mem = new int[4][4];
|
||||
private int minDist = Integer.MAX_VALUE; // 全局变量或者成员变量
|
||||
|
||||
/**
|
||||
* 动态规划:状态转移表法
|
||||
*/
|
||||
public int minDistDP(int[][] matrix, int n) {
|
||||
int[][] states = new int[n][n];
|
||||
int sum = 0;
|
||||
for (int j = 0; j < n; ++j) { // 初始化states的第一行数据
|
||||
sum += matrix[0][j];
|
||||
states[0][j] = sum;
|
||||
}
|
||||
sum = 0;
|
||||
for (int i = 0; i < n; ++i) { // 初始化states的第一列数据
|
||||
sum += matrix[i][0];
|
||||
states[i][0] = sum;
|
||||
}
|
||||
for (int i = 1; i < n; ++i) {
|
||||
for (int j = 1; j < n; ++j) {
|
||||
states[i][j] = matrix[i][j] + Math.min(states[i][j - 1], states[i - 1][j]);
|
||||
}
|
||||
}
|
||||
return states[n - 1][n - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态规划:状态转移方程法
|
||||
*/
|
||||
public int minDist(int i, int j) { // 调用minDist(n-1, n-1);
|
||||
if (i == 0 && j == 0) {
|
||||
return matrix[0][0];
|
||||
}
|
||||
// 备忘录,如果计算过,即有数字存在,则直接返回
|
||||
if (mem[i][j] > 0) {
|
||||
return mem[i][j];
|
||||
}
|
||||
int minLeft = Integer.MAX_VALUE;
|
||||
if (j - 1 >= 0) {
|
||||
minLeft = minDist(i, j - 1);
|
||||
}
|
||||
int minUp = Integer.MAX_VALUE;
|
||||
if (i - 1 >= 0) {
|
||||
minUp = minDist(i - 1, j);
|
||||
}
|
||||
|
||||
int currMinDist = matrix[i][j] + Math.min(minLeft, minUp);
|
||||
mem[i][j] = currMinDist;
|
||||
return currMinDist;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回溯方式
|
||||
*/
|
||||
public void minDistBacktracing(int i, int j, int dist, int[][] w, int n) {
|
||||
// 到达了n-1, n-1这个位置了,这里看着有点奇怪哈,你自己举个例子看下
|
||||
if (i == n && j == n) {
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (i < n) { // 往下走,更新i=i+1, j=j
|
||||
minDistBacktracing(i + 1, j, dist + w[i][j], w, n);
|
||||
}
|
||||
if (j < n) { // 往右走,更新i=i, j=j+1
|
||||
minDistBacktracing(i, j + 1, dist + w[i][j], w, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.linkedlist;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2022-04-15 08:41.
|
||||
*/
|
||||
public class Leecode21 {
|
||||
public static class ListNode {
|
||||
int val;
|
||||
ListNode next;
|
||||
|
||||
ListNode() {
|
||||
}
|
||||
|
||||
ListNode(int val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
ListNode(int val, ListNode next) {
|
||||
this.val = val;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ListNode list1 = new ListNode(1);
|
||||
ListNode list2 = new ListNode(2);
|
||||
ListNode list3 = new ListNode(4);
|
||||
list1.next = list2;
|
||||
list2.next = list3;
|
||||
ListNode list4 = new ListNode(1);
|
||||
ListNode list5 = new ListNode(3);
|
||||
ListNode list6 = new ListNode(4);
|
||||
list4.next = list5;
|
||||
list5.next = list6;
|
||||
ListNode list7 = mergeTwoLists(list1, list4);
|
||||
while (list7 != null) {
|
||||
System.out.println(list7.val);
|
||||
list7 = list7.next;
|
||||
}
|
||||
}
|
||||
|
||||
public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
|
||||
ListNode res = new ListNode();
|
||||
ListNode tmp = res;
|
||||
|
||||
while (list1 != null || list2 != null) {
|
||||
if (list1 == null) {
|
||||
tmp.next = list2;
|
||||
break;
|
||||
}
|
||||
if (list2 == null) {
|
||||
tmp.next = list1;
|
||||
break;
|
||||
}
|
||||
if (list1.val < list2.val) {
|
||||
tmp.next = list1;
|
||||
list1 = list1.next;
|
||||
} else {
|
||||
tmp.next = list2;
|
||||
list2 = list2.next;
|
||||
}
|
||||
tmp = tmp.next;
|
||||
}
|
||||
|
||||
return res.next;
|
||||
}
|
||||
|
||||
public static ListNode mergeTwoLists2(ListNode l1, ListNode l2) {
|
||||
// 虚拟头结点
|
||||
ListNode dummy = new ListNode(-1), p = dummy;
|
||||
ListNode p1 = l1, p2 = l2;
|
||||
|
||||
while (p1 != null && p2 != null) {
|
||||
// 比较 p1 和 p2 两个指针
|
||||
// 将值较小的的节点接到 p 指针
|
||||
if (p1.val > p2.val) {
|
||||
p.next = p2;
|
||||
p2 = p2.next;
|
||||
} else {
|
||||
p.next = p1;
|
||||
p1 = p1.next;
|
||||
}
|
||||
// p 指针不断前进
|
||||
p = p.next;
|
||||
}
|
||||
|
||||
if (p1 != null) {
|
||||
p.next = p1;
|
||||
}
|
||||
|
||||
if (p2 != null) {
|
||||
p.next = p2;
|
||||
}
|
||||
|
||||
return dummy.next;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.linkedlist;
|
||||
|
||||
/**
|
||||
* 反转单链表
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2022-03-14 07:05.
|
||||
*/
|
||||
public class ReverseLinkedList {
|
||||
public static void main(String[] args) {
|
||||
Node node5 = new Node(5, null);
|
||||
Node node4 = new Node(4, node5);
|
||||
Node node3 = new Node(3, node4);
|
||||
Node node2 = new Node(2, node3);
|
||||
Node node1 = new Node(1, node2);
|
||||
Node node0 = new Node(0, node1);
|
||||
Node root = new Node(null, node0);
|
||||
|
||||
Node reverse = reverse(root);
|
||||
// root.print();
|
||||
|
||||
reverse.print();
|
||||
|
||||
}
|
||||
|
||||
public static Node reverse(Node root) {
|
||||
|
||||
Node pre = null;
|
||||
Node cur = root;
|
||||
while (cur != null) {
|
||||
Node tmp = cur.next;
|
||||
|
||||
cur.next = pre;
|
||||
pre = cur;
|
||||
cur = tmp;
|
||||
// tmp = cur.next;
|
||||
}
|
||||
|
||||
return pre;
|
||||
}
|
||||
}
|
||||
|
||||
class Node {
|
||||
public Integer value;
|
||||
public Node next;
|
||||
|
||||
public Node(Integer value, Node next) {
|
||||
this.next = next;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void print() {
|
||||
System.out.println(this);
|
||||
Node tmp = this.next;
|
||||
while (tmp != null) {
|
||||
System.out.println(tmp);
|
||||
tmp = tmp.next;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node[value=" + this.value + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,36 +22,40 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
package io.github.ehlxr.algorithm.match;
|
||||
|
||||
/**
|
||||
* -Xms600m -Xmx600m -XX:SurvivorRatio=8 -XX:+PrintGCDetails
|
||||
* -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/ehlxr/Downloads/hprof/1.hprof
|
||||
* 字符串匹配:暴力匹配
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-08 21:26.
|
||||
* @since 2022-03-12 13:36.
|
||||
*/
|
||||
public class OOMTest {
|
||||
public class BruteForce {
|
||||
public static void main(String[] args) {
|
||||
ArrayList<Picture> list = new ArrayList<>();
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(5);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
String s = "abdcfhjudfadf";
|
||||
String p = "dcf";
|
||||
|
||||
System.out.println(bf(s, p));
|
||||
}
|
||||
|
||||
public static int bf(String s, String p) {
|
||||
int sl = s.length();
|
||||
int pl = p.length();
|
||||
|
||||
for (int i = 0; i <= sl - pl; i++) {
|
||||
int j = 0;
|
||||
for (; j < pl; j++) {
|
||||
if (s.charAt(i) == p.charAt(j)) {
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == pl) {
|
||||
return i - pl;
|
||||
}
|
||||
list.add(new Picture(new Random().nextInt(100 * 50)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Picture {
|
||||
private final byte[] pixels;
|
||||
|
||||
public Picture(int length) {
|
||||
this.pixels = new byte[length];
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.match;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 字符串匹配算法 KPM
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2022-03-13 10:06.
|
||||
*/
|
||||
public class Kmp {
|
||||
public static void main(String[] args) {
|
||||
String s = "bacbababaabcbab";
|
||||
String p = "abab";
|
||||
|
||||
System.out.println(Arrays.toString(getNexts(p)));
|
||||
System.out.println(kmp(s, p));
|
||||
}
|
||||
|
||||
public static int kmp(String s, String p) {
|
||||
char[] scs = s.toCharArray();
|
||||
char[] pcs = p.toCharArray();
|
||||
|
||||
int m = s.length();
|
||||
int n = p.length();
|
||||
|
||||
int[] next = getNexts(p);
|
||||
|
||||
for (int i = 0; i <= m - n; i++) {
|
||||
int j = 0;
|
||||
while (j < n) {
|
||||
if (scs[i] == pcs[j]) {
|
||||
i++;
|
||||
j++;
|
||||
} else {
|
||||
// 当模式串与主串不匹配时,如果**不匹配字符**对应模式串下标大于 j > 0 (非首个模式串字符),
|
||||
// 并且此字符前一个字符对应字符串部分匹配表中的值 next[j - 1] 也大于 0,
|
||||
// j - next[j - 1] 即模式串为后移的位数,等价于 j 置为 next[j - 1]
|
||||
if (j > 0 && next[j - 1] > 0) {
|
||||
j = next[j - 1];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == n) {
|
||||
return i - n;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int[] getNexts(String p) {
|
||||
int m = p.length();
|
||||
char[] b = p.toCharArray();
|
||||
int[] next = new int[m];
|
||||
|
||||
next[0] = 0;
|
||||
int k = 0; // 表示前后缀相匹配的最大长度
|
||||
|
||||
for (int i = 1; i < m; ++i) {
|
||||
// k 为 b[0, i-1] 子串最大匹配前、后缀长度
|
||||
// b[0, k] 为 b[0, i-1] 子串最大匹配前缀子串
|
||||
while (k != 0 && b[k] != b[i]) {
|
||||
// 若:b[k] != b[i],则求 b[0, i] 子串最大匹配前、后缀长度问题转换成了求 b[0, k] 子串最大匹配前、后缀长度问题
|
||||
k = next[k];
|
||||
}
|
||||
if (b[k] == b[i]) {
|
||||
// 若:b[k] == b[i],则 b[0, i] 子串最大匹配前、后缀长度为 k + 1
|
||||
++k;
|
||||
}
|
||||
next[i] = k;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.search;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2022-01-01 17:06.
|
||||
*/
|
||||
public class BinarySearch {
|
||||
public static void main(String[] args) {
|
||||
int[] a = new int[]{1, 3, 5, 6, 7, 8, 9};
|
||||
System.out.println(search(a, a.length, 3));
|
||||
System.out.println(searchRec(a, a.length, 3));
|
||||
a = new int[]{1, 2, 2, 2, 2, 5, 6, 7, 8, 9};
|
||||
System.out.println(searchFirst(a, a.length, 2));
|
||||
a = new int[]{1, 3, 4, 5, 6, 8, 8, 8, 9};
|
||||
System.out.println(searchLast(a, a.length, 8));
|
||||
a = new int[]{1, 2, 2, 3, 4, 5, 6, 7, 8, 8, 9};
|
||||
System.out.println(searchFirstGreater(a, a.length, 7));
|
||||
a = new int[]{1, 2, 3, 4, 5, 6, 8, 9};
|
||||
System.out.println(searchLastLess(a, a.length, 7));
|
||||
}
|
||||
|
||||
/**
|
||||
* 非递归二分查找
|
||||
*
|
||||
* @param a 要查找的数组
|
||||
* @param n 数组的长度
|
||||
* @param v 要查找的值
|
||||
* @return 要查找值在数组中的索引
|
||||
*/
|
||||
public static int search(int[] a, int n, int v) {
|
||||
int low = 0;
|
||||
int high = n - 1;
|
||||
while (low <= high) {
|
||||
int mid = low + ((high - low) >> 1);
|
||||
if (a[mid] == v) {
|
||||
return mid;
|
||||
} else if (a[mid] < v) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归二分查找
|
||||
*
|
||||
* @param a 要查找的数组
|
||||
* @param n 数组的长度
|
||||
* @param v 要查找的值
|
||||
* @return 要查找值在数组中的索引
|
||||
*/
|
||||
public static int searchRec(int[] a, int n, int v) {
|
||||
return searchRec(a, 0, n - 1, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归二分查找
|
||||
*/
|
||||
public static int searchRec(int[] a, int low, int high, int v) {
|
||||
if (low > high) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mid = low + ((high - low) >> 1);
|
||||
if (a[mid] == v) {
|
||||
return mid;
|
||||
} else if (a[mid] < v) {
|
||||
return searchRec(a, mid + 1, high, v);
|
||||
} else {
|
||||
return searchRec(a, low, mid - 1, v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找第一个值等于给定值的元素
|
||||
*
|
||||
* @param a 要查找的数组
|
||||
* @param n 数组的长度
|
||||
* @param v 要查找的值
|
||||
* @return 要查找值在数组中的索引
|
||||
*/
|
||||
public static int searchFirst(int[] a, int n, int v) {
|
||||
int low = 0;
|
||||
int high = n - 1;
|
||||
while (low <= high) {
|
||||
int mid = low + ((high - low) >> 1);
|
||||
if (a[mid] == v) {
|
||||
if (mid == 0 || a[mid - 1] != v) {
|
||||
return mid;
|
||||
} else {
|
||||
high = mid - 1;
|
||||
}
|
||||
} else if (a[mid] < v) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找最后一个值等于给定值的元素
|
||||
*
|
||||
* @param a 要查找的数组
|
||||
* @param n 数组的长度
|
||||
* @param v 要查找的值
|
||||
* @return 要查找值在数组中的索引
|
||||
*/
|
||||
public static int searchLast(int[] a, int n, int v) {
|
||||
int low = 0;
|
||||
int high = n - 1;
|
||||
while (low <= high) {
|
||||
int mid = low + ((high - low) >> 1);
|
||||
if (a[mid] == v) {
|
||||
if (mid == n - 1 || a[mid + 1] != v) {
|
||||
return mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
} else if (a[mid] < v) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找第一个大于等于给定值的元素
|
||||
*
|
||||
* @param a 要查找的数组
|
||||
* @param n 数组的长度
|
||||
* @param v 要查找的值
|
||||
* @return 要查找值在数组中的索引
|
||||
*/
|
||||
public static int searchFirstGreater(int[] a, int n, int v) {
|
||||
int low = 0;
|
||||
int high = n - 1;
|
||||
while (low <= high) {
|
||||
int mid = low + ((high - low) >> 1);
|
||||
if (a[mid] < v) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
if (mid == 0 || a[mid - 1] < v) {
|
||||
return mid;
|
||||
} else {
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找最后一个小于等于给定值的元素
|
||||
*
|
||||
* @param a 要查找的数组
|
||||
* @param n 数组的长度
|
||||
* @param v 要查找的值
|
||||
* @return 要查找值在数组中的索引
|
||||
*/
|
||||
public static int searchLastLess(int[] a, int n, int v) {
|
||||
int low = 0;
|
||||
int high = n - 1;
|
||||
while (low <= high) {
|
||||
int mid = low + ((high - low) >> 1);
|
||||
if (a[mid] > v) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
if (mid == n - 1 || a[mid + 1] > v) {
|
||||
return mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.sort;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-12-27 19:06.
|
||||
*/
|
||||
public class MergeSort {
|
||||
public static void main(String[] args) {
|
||||
int[] arrs = new int[]{3, 2, 5, 7, 1, 9};
|
||||
System.out.println(Arrays.toString(sort(arrs)));
|
||||
System.out.println(Arrays.toString(sort2(arrs)));
|
||||
}
|
||||
|
||||
public static int[] sort(int[] arrs) {
|
||||
if (arrs.length <= 1) {
|
||||
return arrs;
|
||||
}
|
||||
int[] a1 = sort(Arrays.copyOfRange(arrs, 0, arrs.length / 2));
|
||||
int[] a2 = sort(Arrays.copyOfRange(arrs, arrs.length / 2, arrs.length));
|
||||
|
||||
return merge(a1, a2);
|
||||
}
|
||||
|
||||
public static int[] merge(int[] a1, int[] a2) {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int[] result = new int[a1.length + a2.length];
|
||||
int k = 0;
|
||||
while (i < a1.length || j < a2.length) {
|
||||
int temp;
|
||||
if (i >= a1.length) {
|
||||
temp = a2[j++];
|
||||
} else if (j >= a2.length) {
|
||||
temp = a1[i++];
|
||||
} else if (a1[i] <= a2[j]) {// 为了保证算法的稳定性,如果 a1、a2 有相同的元素,保证 a1 的元素在前面
|
||||
temp = a1[i++];
|
||||
} else {
|
||||
temp = a2[j++];
|
||||
}
|
||||
|
||||
result[k] = temp;
|
||||
k++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static int[] sort2(int[] a) {
|
||||
if (a == null || a.length <= 1) {
|
||||
return a;
|
||||
}
|
||||
|
||||
return merge2(sort2(Arrays.copyOfRange(a, 0, a.length / 2)),
|
||||
sort2(Arrays.copyOfRange(a, a.length / 2, a.length)));
|
||||
}
|
||||
|
||||
public static int[] merge2(int[] a, int[] b) {
|
||||
int[] r = new int[a.length + b.length];
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int m = 0;
|
||||
while (i < a.length || j < b.length) {
|
||||
if (i >= a.length) {
|
||||
r[m++] = b[j++];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (j >= b.length) {
|
||||
r[m++] = a[i++];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a[i] < b[j]) {
|
||||
r[m++] = a[i++];
|
||||
} else {
|
||||
r[m++] = b[j++];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.algorithm.sort;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-12-28 19:57.
|
||||
*/
|
||||
public class QuickSort {
|
||||
public static void main(String[] args) {
|
||||
int[] a = new int[]{3, 9, 5, 7, 1, 2};
|
||||
sort2(a, 0, a.length - 1);
|
||||
|
||||
System.out.println(Arrays.toString(a));
|
||||
}
|
||||
|
||||
public static void sort(int[] a, int p, int r) {
|
||||
if (p >= r) {
|
||||
return;
|
||||
}
|
||||
|
||||
int q = partition(a, p, r);
|
||||
|
||||
sort(a, p, q - 1);
|
||||
sort(a, q + 1, r);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分区点
|
||||
* <p>
|
||||
* 图示:https://cdn.jsdelivr.net/gh/0vo/oss/images/quick_sort.jpg
|
||||
* <p>
|
||||
* 通过游标 i 把 a[p...r] 分成两部分。
|
||||
* a[p...i-1] 的元素都是小于 pivot 的,我们暂且叫它 “已处理区间”,a[i...r] 是 “未处理区间”。
|
||||
* 我们每次都从未处理的区间 a[i...r] 中取一个元素 a[j],与 pivot 对比,
|
||||
* 如果小于 pivot,则将其加入到已处理区间的尾部,也就是 a[i] 的位置
|
||||
* <p>
|
||||
* 只需要将 a[i] 与 a[j] 交换,就可以在 O(1) 时间复杂度内将 a[j] 放到下标为 i 的位置。
|
||||
*/
|
||||
public static int partition(int[] a, int p, int r) {
|
||||
int i = p;
|
||||
int pivot = a[r];
|
||||
for (int j = p; j < r; j++) {
|
||||
if (a[j] < pivot) {
|
||||
swap(a, i++, j);
|
||||
}
|
||||
}
|
||||
|
||||
swap(a, i, r);
|
||||
System.out.println("i=" + i + " " + Arrays.toString(a));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public static void swap(int[] a, int i, int j) {
|
||||
if (i == j) {
|
||||
return;
|
||||
}
|
||||
int temp = a[i];
|
||||
a[i] = a[j];
|
||||
a[j] = temp;
|
||||
}
|
||||
|
||||
public static void sort2(int[] a, int l, int r) {
|
||||
if (a == null || l >= r) {
|
||||
return;
|
||||
}
|
||||
|
||||
int i = l, j = r;
|
||||
int p = l; // 选择最左边的元素为 pivot
|
||||
while (l < r) {
|
||||
// 如果选择 p = l 必须先从右边找到小于 a[p] 的第一个元素
|
||||
while (l < r && a[r] >= a[p]) {
|
||||
r--;
|
||||
}
|
||||
swap(a, r, p);
|
||||
p = r;
|
||||
|
||||
// 从左边找到大于 a[p] 的第一个元素
|
||||
while (l < r && a[l] <= a[p]) {
|
||||
l++;
|
||||
}
|
||||
swap(a, l, p);
|
||||
p = l;
|
||||
System.out.println(Arrays.toString(a));
|
||||
|
||||
}
|
||||
|
||||
sort2(a, i, p - 1);
|
||||
sort2(a, p + 1, j);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,10 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.github.ehlxr.annotation;
|
||||
package io.github.ehlxr.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -33,11 +30,12 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* 请求日志排除注解
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-18 14:03.
|
||||
*/
|
||||
@Target(ElementType.PACKAGE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface PkgAnnotation {
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface NoRequestLog {
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,28 +22,26 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.common;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
*/
|
||||
/**
|
||||
* @author ehlxr
|
||||
* 常量
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 18:32.
|
||||
*/
|
||||
@PkgAnnotation
|
||||
package io.github.ehlxr.annotation;
|
||||
public interface Constant {
|
||||
/**
|
||||
* traceID
|
||||
*/
|
||||
String LOG_TRACE_ID = "logTraceId";
|
||||
|
||||
/**
|
||||
* 包内方法
|
||||
*/
|
||||
class MyPackageMethod {
|
||||
public void myPackageMethod() {
|
||||
System.out.println("MyPackageMethod...");
|
||||
}
|
||||
/**
|
||||
* 接口请求开始时间戳
|
||||
*/
|
||||
String REQUEST_START_TIME = "request_start_time";
|
||||
|
||||
int SUCCESS_CODE = 0;
|
||||
|
||||
String SUCCESS_MSG = "success";
|
||||
}
|
||||
|
||||
/**
|
||||
* 包内常量
|
||||
*/
|
||||
class MyPackageConst {
|
||||
static final java.lang.String PACKAGE_STRING = "myPackageConst";
|
||||
}
|
||||
@@ -1,28 +1,4 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.utils;
|
||||
package io.github.ehlxr.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@@ -30,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
import io.github.ehlxr.enums.CodeEnum;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -67,7 +44,7 @@ public class Result<T> implements Serializable {
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(T data, String message) {
|
||||
return new Result<>(Code.SUCCESSFUL.getCode(), data, message);
|
||||
return new Result<>(CodeEnum.SUCCESSFUL.getCode(), data, message);
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(T data) {
|
||||
@@ -82,35 +59,35 @@ public class Result<T> implements Serializable {
|
||||
return new Result<>(c, d, m);
|
||||
}
|
||||
|
||||
public static <T> Result<T> of(Code c, T d, String m) {
|
||||
public static <T> Result<T> of(CodeEnum c, T d, String m) {
|
||||
return new Result<>(c.getCode(), d, m);
|
||||
}
|
||||
|
||||
public static <T> Result<T> fail(Code code, String message) {
|
||||
return of(code.getCode(), null, message);
|
||||
public static <T> Result<T> fail(CodeEnum codeEnum, String message) {
|
||||
return of(codeEnum.getCode(), null, message);
|
||||
}
|
||||
|
||||
public static <T> Result<T> fail(Code code) {
|
||||
return fail(code, code.getMessage());
|
||||
public static <T> Result<T> fail(CodeEnum codeEnum) {
|
||||
return fail(codeEnum, codeEnum.getMessage());
|
||||
}
|
||||
|
||||
public static <T> Result<T> fail(Throwable e) {
|
||||
// 格式化异常消息,防止输出异常栈信息到结果集
|
||||
e = Throwables.getRootCause(e);
|
||||
return of(Code.UNKNOWN_EXCEPTION.getCode(), null, String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()));
|
||||
return of(CodeEnum.UNKNOWN_EXCEPTION.getCode(), null, String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()));
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
// return Strings.isNullOrEmpty(m) ? c.getMessage() : m;
|
||||
if (Strings.isNullOrEmpty(message)) {
|
||||
Code code;
|
||||
CodeEnum codeEnum;
|
||||
try {
|
||||
code = Code.code(this.code);
|
||||
codeEnum = CodeEnum.code(this.code);
|
||||
} catch (Exception e) {
|
||||
return message;
|
||||
}
|
||||
|
||||
return Objects.isNull(code) ? "" : code.getMessage();
|
||||
return Objects.isNull(codeEnum) ? "" : codeEnum.getMessage();
|
||||
}
|
||||
return message;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 18:32.
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisTemplateConfig {
|
||||
@Bean(name = "redisTemplate")
|
||||
public RedisTemplate<String, String> getRedisTemplate(RedisConnectionFactory factory) {
|
||||
return buildRedisTemplateByString(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 redisTemplate 使用 string序列化
|
||||
*/
|
||||
public RedisTemplate<String, String> buildRedisTemplateByString(RedisConnectionFactory factory) {
|
||||
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(factory);
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,35 +22,51 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.proxy;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
package io.github.ehlxr.datastructure;
|
||||
|
||||
/**
|
||||
* 链表节点数据结构
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2019-06-28.
|
||||
* @since 2021-12-23 14:41.
|
||||
*/
|
||||
public class MyInvocationHandler implements InvocationHandler {
|
||||
private final Bird bird;
|
||||
public class Node<T> {
|
||||
private T val;
|
||||
private Node<T> next;
|
||||
|
||||
public MyInvocationHandler(Bird bird) {
|
||||
this.bird = bird;
|
||||
public Node(T val, Node<T> next) {
|
||||
this.val = val;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public T getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
public void setVal(T val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public Node<T> getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public void setNext(Node<T> next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public void print() {
|
||||
Node<T> n = this;
|
||||
while (n != null) {
|
||||
System.out.printf("%s -> ", n.getVal());
|
||||
n = n.getNext();
|
||||
}
|
||||
System.out.print("null");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
method.invoke(bird, args);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("Fly time = " + (end - start));
|
||||
return null;
|
||||
public String toString() {
|
||||
return "Node{" + val + '}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.linkedlist;
|
||||
|
||||
import io.github.ehlxr.datastructure.Node;
|
||||
|
||||
/**
|
||||
* 反转链表
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-12-23 14:40.
|
||||
*/
|
||||
public class ReverseLinkedList<T> {
|
||||
public static void main(String[] args) {
|
||||
ReverseLinkedList<Integer> reverseLinkedList = new ReverseLinkedList<>();
|
||||
Node<Integer> n5 = new Node<>(5, null);
|
||||
Node<Integer> n4 = new Node<>(4, n5);
|
||||
Node<Integer> n3 = new Node<>(3, n4);
|
||||
Node<Integer> n2 = new Node<>(2, n3);
|
||||
Node<Integer> n1 = new Node<>(1, n2);
|
||||
Node<Integer> head = new Node<>(0, n1);
|
||||
|
||||
head.print();
|
||||
|
||||
System.out.println("-------------");
|
||||
// head = reverse(head);
|
||||
head = reverseLinkedList.reverse2(head);
|
||||
// head = reverse3(head, null);
|
||||
head.print();
|
||||
}
|
||||
|
||||
|
||||
// 循环方式
|
||||
public Node<T> reverse(Node<T> head) {
|
||||
if (head == null || head.getNext() == null) {
|
||||
return head;
|
||||
}
|
||||
Node<T> pre = null;
|
||||
|
||||
Node<T> cur = head;
|
||||
while (cur != null) {
|
||||
Node<T> next = cur.getNext();
|
||||
cur.setNext(pre);
|
||||
pre = cur;
|
||||
|
||||
cur = next;
|
||||
}
|
||||
|
||||
return pre;
|
||||
}
|
||||
|
||||
// 递归一
|
||||
public Node<T> reverse2(Node<T> head) {
|
||||
if (head == null || head.getNext() == null) {
|
||||
return head;
|
||||
}
|
||||
|
||||
Node<T> next = head.getNext();
|
||||
Node<T> node = reverse2(next);
|
||||
|
||||
head.getNext().setNext(head);
|
||||
head.setNext(null);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// 递归二
|
||||
public Node<T> reverse3(Node<T> head, Node<T> pre) {
|
||||
if (head == null) {
|
||||
return pre;
|
||||
}
|
||||
|
||||
Node<T> next = head.getNext();
|
||||
Node<T> node = reverse3(next, head);
|
||||
|
||||
head.setNext(pre);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.queue;
|
||||
|
||||
/**
|
||||
* 数组实现循环队列
|
||||
* <p>
|
||||
* 一般情况下只需要 tail + 1 == head 即可判定队列已满,结合特殊情况(head == 0,tail == n - 1)
|
||||
* 可使用公式 (tail + 1) % size == head 判定队列已满,head == tail 判断队列为空,
|
||||
* 但这种公式判断循环队列会浪费一个数组的存储空间。
|
||||
* <p>
|
||||
* 另也可使用一个变量 n 记录当前队列中的数量(入队 +1,出队 -1),当 head == tail 时,
|
||||
* 如果 n == size,则队列已满,如果 n == 0 则队列为空。
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-12-25 21:01.
|
||||
*/
|
||||
public class CircularQueue {
|
||||
private final Integer[] data;
|
||||
private int head = 0;
|
||||
private int tail = 0;
|
||||
private final int size;
|
||||
|
||||
public CircularQueue(int size) {
|
||||
data = new Integer[size];
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
CircularQueue queue = new CircularQueue(5);
|
||||
|
||||
// 循环队列会浪费一个数组的存储空间。队列容量为 5,入队 5 个最后一个失败
|
||||
for (int i = 0; i < 5; i++) {
|
||||
System.out.println(queue.enqueue(i));
|
||||
}
|
||||
|
||||
// 出队 2 个,然后还可以入队 2 个
|
||||
for (int i = 0; i < 2; i++) {
|
||||
System.out.println(queue.dequeue());
|
||||
}
|
||||
System.out.println(queue.enqueue(7));
|
||||
System.out.println(queue.enqueue(8));
|
||||
System.out.println(queue.enqueue(9));
|
||||
|
||||
// 出队 6 个,最后一个失败
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.println(queue.dequeue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 入队(从队尾添加元素)
|
||||
*/
|
||||
public boolean enqueue(Integer item) {
|
||||
// 判断队列是否已满
|
||||
if ((tail + 1) % size == head) {
|
||||
return false;
|
||||
}
|
||||
data[tail] = item;
|
||||
tail = (tail + 1) % size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出队(从队首取出元素)
|
||||
*/
|
||||
public Integer dequeue() {
|
||||
// 判断队列是否为空
|
||||
if (head == tail) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Integer no = data[head];
|
||||
head = (head + 1) % size;
|
||||
|
||||
return no;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.queue;
|
||||
|
||||
/**
|
||||
* 数组实现动态扩容队列
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-12-25 15:19.
|
||||
*/
|
||||
public class DynamicArrayQueue {
|
||||
private final String[] data;
|
||||
private final int size;
|
||||
private int head = 0;
|
||||
private int tail = 0;
|
||||
|
||||
public DynamicArrayQueue(int size) {
|
||||
data = new String[size];
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
DynamicArrayQueue queue = new DynamicArrayQueue(5);
|
||||
|
||||
// 队列容量为 5,入队 6 个最后一个失败
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.println(queue.enqueue("" + i));
|
||||
}
|
||||
|
||||
// 出队 2 个,然后还可以入队 2 个
|
||||
for (int i = 0; i < 2; i++) {
|
||||
System.out.println(queue.dequeue());
|
||||
}
|
||||
System.out.println(queue.enqueue("a"));
|
||||
System.out.println(queue.enqueue("b"));
|
||||
System.out.println(queue.enqueue("c"));
|
||||
|
||||
// 出队 6 个,最后一个失败
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.println(queue.dequeue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 入队(从队尾添加元素)
|
||||
*/
|
||||
public boolean enqueue(String item) {
|
||||
// 判断队列是否已满
|
||||
if (tail == size) {
|
||||
if (head == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果 tail == size,而 head != 0,0 与 head 之间还有空位,向前移动 head 与 tail 之间的数据
|
||||
// for (int i = head; i < tail; i++) {
|
||||
// data[i - head] = data[i];
|
||||
// }
|
||||
if (tail - head >= 0) {
|
||||
System.arraycopy(data, head, data, 0, tail - head);
|
||||
}
|
||||
|
||||
tail -= head;
|
||||
head = 0;
|
||||
}
|
||||
|
||||
data[tail++] = item;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出队(从队首取出元素)
|
||||
*/
|
||||
public String dequeue() {
|
||||
// 判断队列是否为空
|
||||
if (head == tail) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return data[head++];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.queue;
|
||||
|
||||
import io.github.ehlxr.datastructure.Node;
|
||||
|
||||
/**
|
||||
* 基于链表实现的队列
|
||||
* <p>
|
||||
* 入队时间复杂度 O(n)
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-12-25 16:02.
|
||||
*/
|
||||
public class LinkedListQueue<T> {
|
||||
private Node<T> head;
|
||||
|
||||
public static void main(String[] args) {
|
||||
LinkedListQueue<Integer> queue = new LinkedListQueue<>();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.println(queue.enqueue(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
queue.getData().print();
|
||||
System.out.println(queue.dequeue());
|
||||
}
|
||||
|
||||
System.out.println(queue.dequeue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 入队(从队尾添加元素)
|
||||
* 时间复杂度 O(n)
|
||||
*/
|
||||
public boolean enqueue(T item) {
|
||||
Node<T> node = new Node<T>(item, null);
|
||||
if (head == null) {
|
||||
head = node;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 找到队尾
|
||||
Node<T> tail = head;
|
||||
while (tail.getNext() != null) {
|
||||
tail = tail.getNext();
|
||||
}
|
||||
|
||||
tail.setNext(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出队(从队首取出元素)
|
||||
*/
|
||||
public T dequeue() {
|
||||
if (head == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
T val = head.getVal();
|
||||
head = head.getNext();
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
public Node<T> getData() {
|
||||
return head;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.queue;
|
||||
|
||||
import io.github.ehlxr.datastructure.Node;
|
||||
|
||||
/**
|
||||
* 基于链表实现的队列
|
||||
* <p>
|
||||
* 多一个变量 tail,换取入队时间复杂度为 O(1)
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-12-25 16:48.
|
||||
*/
|
||||
public class LinkedListQueue2<T> {
|
||||
private Node<T> head = null;
|
||||
private Node<T> tail = null;
|
||||
|
||||
public static void main(String[] args) {
|
||||
LinkedListQueue2<Integer> queue = new LinkedListQueue2<>();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.println(queue.enqueue(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
queue.getData().print();
|
||||
System.out.println(queue.dequeue());
|
||||
}
|
||||
|
||||
System.out.println(queue.dequeue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 入队(从队尾添加元素)
|
||||
* 时间复杂度 O(1)
|
||||
*/
|
||||
public boolean enqueue(T item) {
|
||||
Node<T> node = new Node<>(item, null);
|
||||
|
||||
if (tail == null) {
|
||||
head = node;
|
||||
tail = node;
|
||||
return true;
|
||||
}
|
||||
|
||||
tail.setNext(node);
|
||||
tail = node;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出队(从队首取出元素)
|
||||
*/
|
||||
public T dequeue() {
|
||||
if (head == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
T val = head.getVal();
|
||||
head = head.getNext();
|
||||
// 如果队列为空了,需要把 tail 置空
|
||||
if (head == null) {
|
||||
tail = null;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
public Node<T> getData() {
|
||||
return head;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,44 +22,56 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.hashing.consistent;
|
||||
package io.github.ehlxr.datastructure.stack;
|
||||
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-12-25 22:10.
|
||||
*/
|
||||
public class ArrayStack {
|
||||
private final Integer[] data;
|
||||
private final int size;
|
||||
// 栈顶下标
|
||||
private int top = 0;
|
||||
|
||||
public class Cluster {
|
||||
private static final int SERVER_SIZE_MAX = 1024;
|
||||
|
||||
private final SortedMap<Integer, Server> servers = new TreeMap<>();
|
||||
private int size = 0;
|
||||
|
||||
public void put(Entry e) {
|
||||
routeServer(e.hashCode()).put(e);
|
||||
}
|
||||
|
||||
public Entry get(Entry e) {
|
||||
return routeServer(e.hashCode()).get(e);
|
||||
}
|
||||
|
||||
public Server routeServer(int hash) {
|
||||
if (servers.isEmpty())
|
||||
return null;
|
||||
|
||||
if (!servers.containsKey(hash)) {
|
||||
SortedMap<Integer, Server> tailMap = servers.tailMap(hash);
|
||||
hash = tailMap.isEmpty() ? servers.firstKey() : tailMap.firstKey();
|
||||
// hash = servers.firstKey();
|
||||
public static void main(String[] args) {
|
||||
ArrayStack stack = new ArrayStack(5);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.println(stack.push(i));
|
||||
}
|
||||
return servers.get(hash);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.println(stack.pop());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean addServer(Server s) {
|
||||
if (size >= SERVER_SIZE_MAX)
|
||||
public ArrayStack(int size) {
|
||||
data = new Integer[size];
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 入栈
|
||||
*/
|
||||
public boolean push(Integer item) {
|
||||
// 判断栈是否已满
|
||||
if (top == size) {
|
||||
return false;
|
||||
}
|
||||
data[top++] = item;
|
||||
|
||||
servers.put(s.hashCode(), s);
|
||||
|
||||
size++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出栈
|
||||
*/
|
||||
public Integer pop() {
|
||||
// 判断栈是否为空
|
||||
if (top == 0) {
|
||||
return null;
|
||||
}
|
||||
return data[--top];
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,55 +22,63 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.test;
|
||||
package io.github.ehlxr.datastructure.stack;
|
||||
|
||||
import io.github.ehlxr.datastructure.Node;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2017/4/14.
|
||||
* @author ehlxr
|
||||
* @since 2021-12-25 22:28.
|
||||
*/
|
||||
public class TestReference {
|
||||
public class LinkedListStack<T> {
|
||||
private Node<T> head;
|
||||
|
||||
public Node<T> getData() {
|
||||
return head;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Person person = new Person();
|
||||
LinkedListStack<Integer> stack = new LinkedListStack<>();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
System.out.println(stack.push(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
stack.getData().print();
|
||||
System.out.println(stack.pop());
|
||||
}
|
||||
|
||||
person.age = 20;
|
||||
person.name = "test20";
|
||||
System.out.println(person);
|
||||
TestReference testReference = new TestReference();
|
||||
testReference.test(person);
|
||||
System.out.println(person);
|
||||
}
|
||||
|
||||
public void test(Person person) {
|
||||
person = new Person();
|
||||
person.age = 21;
|
||||
person.name = "test21";
|
||||
/**
|
||||
* 入栈
|
||||
*/
|
||||
public boolean push(T item) {
|
||||
Node<T> node = new Node<>(item, null);
|
||||
if (head == null) {
|
||||
head = node;
|
||||
return true;
|
||||
}
|
||||
|
||||
node.setNext(head);
|
||||
head = node;
|
||||
return true;
|
||||
}
|
||||
|
||||
static class Person {
|
||||
String name;
|
||||
int age;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person{" +
|
||||
"name='" + name + '\'' +
|
||||
", age=" + age +
|
||||
'}';
|
||||
/**
|
||||
* 出栈
|
||||
*/
|
||||
public T pop() {
|
||||
if (head == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
T val = head.getVal();
|
||||
head = head.getNext();
|
||||
return val;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void clear() {
|
||||
head = null;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.utils;
|
||||
package io.github.ehlxr.enums;
|
||||
|
||||
/**
|
||||
* 自定义状态码
|
||||
@@ -30,7 +30,7 @@ package io.github.ehlxr.utils;
|
||||
* @author ehlxr
|
||||
* @since 2020/3/18.
|
||||
*/
|
||||
public enum Code {
|
||||
public enum CodeEnum {
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
@@ -55,7 +55,7 @@ public enum Code {
|
||||
private final int code;
|
||||
private final String message;
|
||||
|
||||
Code(int code, String message) {
|
||||
CodeEnum(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
@@ -76,10 +76,10 @@ public enum Code {
|
||||
'}';
|
||||
}
|
||||
|
||||
private static final Code[] CODES = Code.values();
|
||||
private static final CodeEnum[] CODE_ENUMS = CodeEnum.values();
|
||||
|
||||
public static Code code(int code) {
|
||||
for (Code c : CODES) {
|
||||
public static CodeEnum code(int code) {
|
||||
for (CodeEnum c : CODE_ENUMS) {
|
||||
if (code == c.getCode()) {
|
||||
return c;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.utils;
|
||||
package io.github.ehlxr.enums;
|
||||
|
||||
/**
|
||||
* FORM 表单提交类型
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.utils;
|
||||
package io.github.ehlxr.enums;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,27 +22,30 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.proxy;
|
||||
|
||||
import java.util.Random;
|
||||
package io.github.ehlxr.exception;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2019-06-28.
|
||||
* @since 2020-05-06.
|
||||
*/
|
||||
public class Bird implements Flyable {
|
||||
@Override
|
||||
public void fly() {
|
||||
System.out.println("Bird is flying...");
|
||||
try {
|
||||
Thread.sleep(new Random().nextInt(1000));
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
public class JsonParseException extends RuntimeException {
|
||||
private static final long serialVersionUID = -2626765995683345473L;
|
||||
|
||||
public JsonParseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void run() {
|
||||
// System.out.println("Bird is running...");
|
||||
// }
|
||||
public JsonParseException(String msg, Throwable e) {
|
||||
super(msg, e);
|
||||
}
|
||||
|
||||
public JsonParseException(Throwable e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
// 不拷贝栈信息
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,28 +22,46 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.singleton;
|
||||
package io.github.ehlxr.exception;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
import io.github.ehlxr.enums.CodeEnum;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-02-18 11:23.
|
||||
* @since 2021-08-29 19:18.
|
||||
*/
|
||||
public class SingleTonStaticInnerClass {
|
||||
private SingleTonStaticInnerClass() {
|
||||
public class ServiceDataException extends RuntimeException {
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private int code;
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
private static class HandlerInstance {
|
||||
private static SingleTonStaticInnerClass instance = new SingleTonStaticInnerClass();
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static SingleTonStaticInnerClass getInstance() {
|
||||
return HandlerInstance.instance;
|
||||
|
||||
public ServiceDataException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
IntStream.range(0, 5).parallel().forEach(i -> System.out.println(Thread.currentThread().getName() + " => " + SingleTonStaticInnerClass.getInstance()));
|
||||
public ServiceDataException(CodeEnum codeEnum) {
|
||||
this.code = codeEnum.getCode();
|
||||
this.msg = codeEnum.getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
public ServiceDataException(int code, String msg) {
|
||||
super(msg);
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.function;
|
||||
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.RecursiveAction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-09-06 10:48.
|
||||
*/
|
||||
public class BlockerActionConsumer<T> extends RecursiveAction {
|
||||
private static final long serialVersionUID = 4942349095463615123L;
|
||||
private final MyManagedBlockerImpl<T> blocker;
|
||||
|
||||
public BlockerActionConsumer(Consumer<T> consumer, T t) {
|
||||
this.blocker = new MyManagedBlockerImpl<>(consumer, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute() {
|
||||
try {
|
||||
ForkJoinPool.managedBlock(blocker);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static class MyManagedBlockerImpl<T> implements ForkJoinPool.ManagedBlocker {
|
||||
private final Consumer<T> consumer;
|
||||
private final T t;
|
||||
private boolean done = false;
|
||||
|
||||
public MyManagedBlockerImpl(Consumer<T> consumer, T t) {
|
||||
this.consumer = consumer;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean block() {
|
||||
consumer.accept(t);
|
||||
done = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReleasable() {
|
||||
return done;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.function;
|
||||
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.RecursiveTask;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-09-06 10:39.
|
||||
*/
|
||||
public class BlockerTaskFunction<T, R> extends RecursiveTask<R> {
|
||||
private static final long serialVersionUID = -4114798302790287199L;
|
||||
private final MyManagedBlockerImpl<T, R> blocker;
|
||||
|
||||
public BlockerTaskFunction(Function<T, R> function, T t) {
|
||||
this.blocker = new MyManagedBlockerImpl<>(function, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected R compute() {
|
||||
try {
|
||||
ForkJoinPool.managedBlock(blocker);
|
||||
setRawResult(blocker.r);
|
||||
return getRawResult();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static class MyManagedBlockerImpl<T, R> implements ForkJoinPool.ManagedBlocker {
|
||||
private final Function<T, R> function;
|
||||
private final T t;
|
||||
private R r;
|
||||
private boolean done = false;
|
||||
|
||||
public MyManagedBlockerImpl(Function<T, R> function, T t) {
|
||||
this.function = function;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean block() {
|
||||
r = function.apply(t);
|
||||
done = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReleasable() {
|
||||
return done;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,35 +22,26 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.leetcode;
|
||||
package io.github.ehlxr.function;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 链表结构
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-02-27 21:09.
|
||||
* @since 2021-09-06 10:40.
|
||||
*/
|
||||
public class ListNode {
|
||||
int val;
|
||||
ListNode next;
|
||||
public class CallableFunction<T, R> implements Callable<R> {
|
||||
private final T t;
|
||||
private final Function<T, R> function;
|
||||
|
||||
ListNode() {
|
||||
}
|
||||
|
||||
ListNode(int val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
ListNode(int val, ListNode next) {
|
||||
this.val = val;
|
||||
this.next = next;
|
||||
public CallableFunction(Function<T, R> function, T t) {
|
||||
this.function = function;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ListNode{" +
|
||||
"val=" + val +
|
||||
", next=" + next +
|
||||
'}';
|
||||
public R call() {
|
||||
return function.apply(t);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,31 +22,27 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.singleton;
|
||||
package io.github.ehlxr.function;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.concurrent.RecursiveTask;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 枚举单例模式
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-02-18 10:28.
|
||||
* @since 2021-09-06 10:41.
|
||||
*/
|
||||
public enum SingleEnum {
|
||||
/**
|
||||
* 唯一实例
|
||||
*/
|
||||
INSTANCE;
|
||||
public class RecursiveTaskFunction<T, R> extends RecursiveTask<R> {
|
||||
private static final long serialVersionUID = 4451027118600634633L;
|
||||
private final T t;
|
||||
private final Function<T, R> function;
|
||||
|
||||
public static SingleEnum getInstance() {
|
||||
return INSTANCE;
|
||||
public RecursiveTaskFunction(Function<T, R> function, T t) {
|
||||
this.function = function;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
public String hello(String str) {
|
||||
return "hello " + str;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
IntStream.range(0, 5).parallel().forEach(i -> System.out.println(Thread.currentThread().getName() + " => " + SingleEnum.getInstance()));
|
||||
@Override
|
||||
protected R compute() {
|
||||
return function.apply(t);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,26 +22,25 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.lock;
|
||||
package io.github.ehlxr.function;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-02-15 18:11.
|
||||
* @since 2021-09-06 10:40.
|
||||
*/
|
||||
public class Locker {
|
||||
public class RunnableConsumer<T> implements Runnable {
|
||||
private final T t;
|
||||
private final Consumer<T> consumer;
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
lock.lock(); // block until condition holds
|
||||
try {
|
||||
// ... method body
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
public RunnableConsumer(Consumer<T> consumer, T t) {
|
||||
this.consumer = consumer;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
consumer.accept(t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.queue;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2022-02-24 20:00.
|
||||
*/
|
||||
@Component
|
||||
public class RedisDelayQueue {
|
||||
private static final Logger log = LoggerFactory.getLogger(RedisDelayQueue.class);
|
||||
/**
|
||||
* 延迟队列名称
|
||||
*/
|
||||
private static final String DELAY_QUEUE_NAME = "budd:delayQueue";
|
||||
private static final ExecutorService POOL = new ThreadPoolExecutor(5, 200,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<>(1024), new ThreadFactoryBuilder()
|
||||
.setNameFormat("RedisDelayQueue-pool-%d").build(),
|
||||
new ThreadPoolExecutor.AbortPolicy());
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
public RedisDelayQueue(RedisTemplate<String, String> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加延迟任务
|
||||
*
|
||||
* @param msg 延迟任务消息
|
||||
* @param delayTime 延迟时间(毫秒)
|
||||
*/
|
||||
public void addDelayTasks(String msg, long delayTime) {
|
||||
Boolean result = redisTemplate.opsForZSet()
|
||||
.add(DELAY_QUEUE_NAME, msg, System.currentTimeMillis() + delayTime);
|
||||
log.debug("add task {} result {} ", msg, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听延迟消息
|
||||
*/
|
||||
@PostConstruct
|
||||
public void listenDelayLoop() {
|
||||
//noinspection AlibabaAvoidManuallyCreateThread
|
||||
new Thread(() -> {
|
||||
while (true) {
|
||||
// 获取一个到点的消息
|
||||
Set<String> taskSet = redisTemplate.opsForZSet()
|
||||
.rangeByScore(DELAY_QUEUE_NAME, 0, System.currentTimeMillis(), 0, 1);
|
||||
|
||||
// 如果没有,就等等
|
||||
if (taskSet == null || taskSet.isEmpty()) {
|
||||
try {
|
||||
// log.debug("there is no task will sleep 1s.");
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("listen delay loop error.", e);
|
||||
}
|
||||
// 继续执行
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String task : taskSet) {
|
||||
// 任务认领成功
|
||||
Long isRemove = redisTemplate.opsForZSet().remove(DELAY_QUEUE_NAME, task);
|
||||
if (isRemove != null && isRemove > 0) {
|
||||
log.info("will deal task {}", task);
|
||||
// 拿到任务 后续处理
|
||||
POOL.execute(() -> log.info("task {} deal done.", task));
|
||||
} else {
|
||||
log.warn("task {} has been handled by another instance", task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,26 +22,23 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.jvm.stack;
|
||||
package io.github.ehlxr.semaphore;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-07-11 15:19.
|
||||
* @since 2022-03-03 11:25.
|
||||
*/
|
||||
public class ReturnAddressTest {
|
||||
|
||||
public void methodA() {
|
||||
int k = 10;
|
||||
int l = 20;
|
||||
|
||||
methodB();
|
||||
}
|
||||
|
||||
public void methodB() {
|
||||
int i = 10;
|
||||
int j = 20;
|
||||
|
||||
int a = i + j;
|
||||
}
|
||||
public interface DistributedSemaphore {
|
||||
/**
|
||||
* 尝试获取一个信号量
|
||||
*
|
||||
* @return true 获取成功,false 获取失败
|
||||
*/
|
||||
boolean tryAcquire();
|
||||
|
||||
/**
|
||||
* 释放自己持有的信号量
|
||||
*/
|
||||
void release();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.semaphore;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.SessionCallback;
|
||||
import org.springframework.data.redis.core.ZSetOperations;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2022-03-03 11:25.
|
||||
*/
|
||||
public class RedisSemaphore implements DistributedSemaphore {
|
||||
private static final String SEMAPHORE_TIME_KEY = "budd:semaphore:time:";
|
||||
private static final String SEMAPHORE_OWNER_KEY = "budd:semaphore:owner:";
|
||||
private static final String SEMAPHORE_COUNTER_KEY = "budd:semaphore:counter:";
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
private final String timeKey;
|
||||
private final String ownerKey;
|
||||
private final String counterKey;
|
||||
// 信号量的信息
|
||||
private final SemaphoreInfo info;
|
||||
// 信号量实体
|
||||
private final DistributedSemaphore semaphore;
|
||||
// 身份证明
|
||||
private final String identification;
|
||||
|
||||
public RedisSemaphore(SemaphoreInfo info, RedisTemplate<String, String> redisTemplate,
|
||||
String identification) {
|
||||
this.info = info;
|
||||
this.redisTemplate = redisTemplate;
|
||||
this.timeKey = SEMAPHORE_TIME_KEY.concat(info.getSemaphoreName());
|
||||
this.ownerKey = SEMAPHORE_OWNER_KEY.concat(info.getSemaphoreName());
|
||||
this.counterKey = SEMAPHORE_COUNTER_KEY.concat(info.getSemaphoreName());
|
||||
this.semaphore = info.isFair() ? new FairSemaphore() : new NonfairSemaphore();
|
||||
this.identification = identification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAcquire() {
|
||||
return semaphore.tryAcquire();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
semaphore.release();
|
||||
}
|
||||
|
||||
private class NonfairSemaphore implements DistributedSemaphore {
|
||||
@Override
|
||||
public boolean tryAcquire() {
|
||||
ZSetOperations<String, String> zsetOps = redisTemplate.opsForZSet();
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
// 先清除过期的信号量
|
||||
zsetOps.removeRangeByScore(timeKey, 0, timeMillis - TimeUnit.SECONDS.toMillis(info.getExpire()));
|
||||
// 尝试获取信号量并比较自身的排名,如果小于许可证的数量则表示获取成功 (redis rank 指令从 0 开始计数)
|
||||
zsetOps.add(timeKey, identification, timeMillis);
|
||||
Long rank = zsetOps.rank(timeKey, identification);
|
||||
if (rank != null && rank < info.getPermits()) {
|
||||
return true;
|
||||
}
|
||||
// 获取失败,删除掉上边添加的标识
|
||||
release();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
redisTemplate.opsForZSet().remove(timeKey, identification);
|
||||
}
|
||||
}
|
||||
|
||||
private class FairSemaphore implements DistributedSemaphore {
|
||||
@Override
|
||||
public boolean tryAcquire() {
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
// 用于获取信号量的计数
|
||||
Long counter = redisTemplate.opsForValue().increment(counterKey, 1);
|
||||
if (counter == null) {
|
||||
return false;
|
||||
}
|
||||
// 用流水线把这一堆命令用一次 IO 全部发过去
|
||||
redisTemplate.executePipelined(new SessionCallback<>() {
|
||||
@Override
|
||||
public Object execute(@Nonnull RedisOperations operations) throws DataAccessException {
|
||||
ZSetOperations<String, Object> zsetOps = operations.opsForZSet();
|
||||
// 利用 timeKey 来控制是否过期,ownerKey 控制是否超配额,
|
||||
// 使用 zset 的 intersectAndStore 在获取信号量之前清理过期数据,同时清理排名集合中的数据
|
||||
// 清除过期的信号量
|
||||
zsetOps.removeRangeByScore(timeKey, 0, timeMillis - TimeUnit.SECONDS.toMillis(info.getExpire()));
|
||||
zsetOps.intersectAndStore(timeKey, ownerKey, ownerKey);
|
||||
// 尝试获取信号量
|
||||
zsetOps.add(timeKey, identification, timeMillis);
|
||||
zsetOps.add(ownerKey, identification, counter);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
// 这里根据 持有者集合 的分数来进行判断
|
||||
Long ownerRank = redisTemplate.opsForZSet().rank(ownerKey, identification);
|
||||
if (ownerRank != null && ownerRank < info.getPermits()) {
|
||||
return true;
|
||||
}
|
||||
release();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
redisTemplate.executePipelined(new SessionCallback<>() {
|
||||
@Override
|
||||
public Object execute(@Nonnull RedisOperations operations) throws DataAccessException {
|
||||
ZSetOperations<String, Object> zetOps = operations.opsForZSet();
|
||||
zetOps.remove(timeKey, identification);
|
||||
zetOps.remove(ownerKey, identification);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.semaphore;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2022-03-03 11:24.
|
||||
*/
|
||||
public final class SemaphoreInfo {
|
||||
// 信号量的名称
|
||||
private final String semaphoreName;
|
||||
// 许可证的数量
|
||||
private final int permits;
|
||||
// 信号量最大持有时间 (过期时间) 单位 s
|
||||
private final long expire;
|
||||
// 公平 or 非公平
|
||||
private final boolean fair;
|
||||
|
||||
public SemaphoreInfo(String semaphoreName, int permits, long expire) {
|
||||
this(semaphoreName, permits, expire, false);
|
||||
}
|
||||
|
||||
public SemaphoreInfo(String semaphoreName, int permits, long expire, boolean fair) {
|
||||
this.semaphoreName = semaphoreName;
|
||||
this.permits = permits;
|
||||
this.expire = expire;
|
||||
this.fair = fair;
|
||||
}
|
||||
|
||||
public String getSemaphoreName() {
|
||||
return semaphoreName;
|
||||
}
|
||||
|
||||
public int getPermits() {
|
||||
return permits;
|
||||
}
|
||||
|
||||
public long getExpire() {
|
||||
return expire;
|
||||
}
|
||||
|
||||
public boolean isFair() {
|
||||
return fair;
|
||||
}
|
||||
}
|
||||
323
budd-common/src/main/java/io/github/ehlxr/util/DateUtil.java
Normal file
323
budd-common/src/main/java/io/github/ehlxr/util/DateUtil.java
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.util;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
|
||||
import java.time.*;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* 日期操作
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 18:32.
|
||||
*/
|
||||
public class DateUtil {
|
||||
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
|
||||
public static final String YYYY_MM_DD = "yyyy-MM-dd";
|
||||
public static final String MM_DD = "MM-dd";
|
||||
public static final String HH_MM_SS = "HH:mm:ss";
|
||||
|
||||
// private static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
|
||||
// private static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern(YYYY_MM_DD);
|
||||
// private static final DateTimeFormatter DEFAULT_DATE_NO_YEAR_FORMATTER = DateTimeFormatter.ofPattern(MM_DD);
|
||||
// private static final DateTimeFormatter DEFAULT_TIME_FORMATTER = DateTimeFormatter.ofPattern(HH_MM_SS);
|
||||
private static final Map<String, DateTimeFormatter> PATTEN_FORMATTER_MAPPER = Collections.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
// static {
|
||||
// PATTEN_FORMATTER_MAPPER.put(YYYY_MM_DD_HH_MM_SS, DEFAULT_DATE_TIME_FORMATTER);
|
||||
// PATTEN_FORMATTER_MAPPER.put(YYYY_MM_DD, DEFAULT_DATE_FORMATTER);
|
||||
// PATTEN_FORMATTER_MAPPER.put(MM_DD, DEFAULT_DATE_NO_YEAR_FORMATTER);
|
||||
// PATTEN_FORMATTER_MAPPER.put(HH_MM_SS, DEFAULT_TIME_FORMATTER);
|
||||
// }
|
||||
|
||||
private static DateTimeFormatter cacheFormatterAndGet(String patten) {
|
||||
DateTimeFormatter dateTimeFormatter = PATTEN_FORMATTER_MAPPER.get(patten);
|
||||
if (dateTimeFormatter == null) {
|
||||
dateTimeFormatter = DateTimeFormatter.ofPattern(patten).withZone(ZoneId.of("+8"));
|
||||
PATTEN_FORMATTER_MAPPER.put(patten, dateTimeFormatter);
|
||||
}
|
||||
return dateTimeFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param localDateTime date time
|
||||
* @return yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String formatLocalDateTime(LocalDateTime localDateTime) {
|
||||
return localDateTime.format(cacheFormatterAndGet(YYYY_MM_DD_HH_MM_SS));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param localDateTime time
|
||||
* @param patten yyyy-MM-dd HH:mm:ss
|
||||
* @return yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String formatLocalDateTime(LocalDateTime localDateTime, String patten) {
|
||||
DateTimeFormatter dateTimeFormatter = cacheFormatterAndGet(patten);
|
||||
return localDateTime.format(dateTimeFormatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param localDate date
|
||||
* @param patten only date patten
|
||||
* @return yyyy-MM-dd
|
||||
*/
|
||||
public static String formatLocalDate(LocalDate localDate, String patten) {
|
||||
DateTimeFormatter dateTimeFormatter = cacheFormatterAndGet(patten);
|
||||
return localDate.format(dateTimeFormatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param localDate localDate
|
||||
* @return yyyy-MM-dd
|
||||
*/
|
||||
public static String formatLocalDate(LocalDate localDate) {
|
||||
return localDate.format(cacheFormatterAndGet(YYYY_MM_DD));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param localTime localTime
|
||||
* @param patten patten
|
||||
* @return HH:mm:ss
|
||||
*/
|
||||
public static String formatLocalTime(LocalTime localTime, String patten) {
|
||||
DateTimeFormatter dateTimeFormatter = cacheFormatterAndGet(patten);
|
||||
return localTime.format(dateTimeFormatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param localTime localTime
|
||||
* @return HH:mm:ss
|
||||
*/
|
||||
public static String formatLocalTime(LocalTime localTime) {
|
||||
return localTime.format(cacheFormatterAndGet(HH_MM_SS));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date date time
|
||||
* @param patten patten
|
||||
* @return yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String format(Date date, String patten) {
|
||||
Instant instant = date.toInstant();
|
||||
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("+8"));
|
||||
return localDateTime.format(cacheFormatterAndGet(patten));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date date
|
||||
* @return yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String format(Date date) {
|
||||
return format(date, YYYY_MM_DD_HH_MM_SS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date date
|
||||
* @return yyyy-MM-dd
|
||||
*/
|
||||
public static String formatDate(Date date) {
|
||||
return format(date, YYYY_MM_DD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date date
|
||||
* @return HH:mm:ss
|
||||
*/
|
||||
public static String formatTime(Date date) {
|
||||
return format(date, HH_MM_SS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mills mills
|
||||
* @return yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String formatMills(long mills, String patten) {
|
||||
Instant instant = Instant.ofEpochMilli(mills);
|
||||
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("+8"));
|
||||
return formatLocalDateTime(localDateTime, patten);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mills mills
|
||||
* @return yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String formatMills(long mills) {
|
||||
return formatMills(mills, YYYY_MM_DD_HH_MM_SS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mills mills
|
||||
* @return yyyy-MM-dd
|
||||
*/
|
||||
public static String formatMillsDate(long mills) {
|
||||
return formatMills(mills, YYYY_MM_DD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date date
|
||||
* @return HH:mm:ss
|
||||
*/
|
||||
public static String formatMillsTime(long date) {
|
||||
return formatMills(date, HH_MM_SS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date yyyy-MM-dd HH:mm:ss
|
||||
* @return Date
|
||||
*/
|
||||
public static Date parse(String date) {
|
||||
LocalDateTime localDateTime = parseToLocalDateTime(date);
|
||||
Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
|
||||
return Date.from(instant);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date string date
|
||||
* @param patten formatter patten
|
||||
* @return LocalDateTime
|
||||
*/
|
||||
public static LocalDateTime parseToLocalDateTime(String date, String patten) {
|
||||
return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(patten));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date yyyy-MM-dd HH:mm:ss
|
||||
* @return LocalDateTime
|
||||
*/
|
||||
public static LocalDateTime parseToLocalDateTime(String date) {
|
||||
return LocalDateTime.parse(date, cacheFormatterAndGet(YYYY_MM_DD_HH_MM_SS));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date yyyy-MM-dd HH:mm:ss
|
||||
* @return milliseconds
|
||||
*/
|
||||
public static Long parseToMillis(String date) {
|
||||
return parseToMillis(date, YYYY_MM_DD_HH_MM_SS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date string date
|
||||
* @param patten formatter patten
|
||||
* @return milliseconds
|
||||
*/
|
||||
public static Long parseToMillis(String date, String patten) {
|
||||
return toInstant(LocalDateTime.parse(date, cacheFormatterAndGet(patten))).toEpochMilli();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date yyyy-MM-dd
|
||||
* @return LocalDate
|
||||
*/
|
||||
public static LocalDate parseToLocalDate(String date) {
|
||||
return LocalDate.parse(date, cacheFormatterAndGet(YYYY_MM_DD));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date HH:mm:ss
|
||||
* @return LocalTime
|
||||
*/
|
||||
public static LocalTime parseToLocalTime(String date) {
|
||||
return LocalTime.parse(date, cacheFormatterAndGet(HH_MM_SS));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dayStart date
|
||||
* @param dayEnd date
|
||||
*/
|
||||
public static Period betweenDays(Date dayStart, Date dayEnd) {
|
||||
LocalDateTime localDateTimeStart = LocalDateTime.ofInstant(dayStart.toInstant(), OffsetDateTime.now().getOffset());
|
||||
LocalDateTime localDateTimeEnd = LocalDateTime.ofInstant(dayEnd.toInstant(), OffsetDateTime.now().getOffset());
|
||||
return Period.between(localDateTimeStart.toLocalDate(), localDateTimeEnd.toLocalDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dayStart date
|
||||
* @param dayEnd date
|
||||
*/
|
||||
public static Duration betweenTimes(Date dayStart, Date dayEnd) {
|
||||
LocalDateTime localDateTimeStart = LocalDateTime.ofInstant(dayStart.toInstant(), OffsetDateTime.now().getOffset());
|
||||
LocalDateTime localDateTimeEnd = LocalDateTime.ofInstant(dayEnd.toInstant(), OffsetDateTime.now().getOffset());
|
||||
return Duration.between(localDateTimeStart, localDateTimeEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dayStart date
|
||||
* @param dayEnd date
|
||||
*/
|
||||
public static Period betweenDays(String dayStart, String dayEnd) {
|
||||
return Period.between(parseToLocalDate(dayStart), parseToLocalDate(dayEnd));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dayStart date
|
||||
* @param dayEnd date
|
||||
*/
|
||||
public static Duration betweenTimes(String dayStart, String dayEnd) {
|
||||
return Duration.between(parseToLocalDateTime(dayStart), parseToLocalDateTime(dayEnd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 每月开始、结束毫秒时间戳
|
||||
*/
|
||||
public static ImmutablePair<Long, Long> firstAndLastMillisOfMonth() {
|
||||
LocalDate today = LocalDate.now();
|
||||
Long firstDay = toInstant(LocalDateTime.of(today.with(TemporalAdjusters.firstDayOfMonth()), LocalTime.MIN)).toEpochMilli();
|
||||
Long lastDay = toInstant(LocalDateTime.of(today.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX)).toEpochMilli();
|
||||
return ImmutablePair.of(firstDay, lastDay);
|
||||
}
|
||||
|
||||
public static Instant toInstant(ChronoLocalDateTime<?> d) {
|
||||
return d.toInstant(ZoneOffset.of("+8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前秒级别时间戳
|
||||
*
|
||||
* @return 10 位时间戳
|
||||
*/
|
||||
public static Long currentTimeSecond() {
|
||||
return toInstant(LocalDateTime.now()).getEpochSecond();
|
||||
}
|
||||
|
||||
/**
|
||||
* 之前的多少天
|
||||
*
|
||||
* @param days 之前的天数
|
||||
* @return yyyy-MM-dd
|
||||
*/
|
||||
public static String beforeDay(long days) {
|
||||
return formatLocalDate(LocalDate.now().minusDays(days));
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,25 +22,62 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.utils;
|
||||
package io.github.ehlxr.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.github.ehlxr.enums.FormType;
|
||||
import io.github.ehlxr.enums.HttpContentType;
|
||||
import okhttp3.*;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.File;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2020/4/20.
|
||||
*/
|
||||
public class HttpUtil {
|
||||
private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient.Builder()
|
||||
private static OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(1, TimeUnit.MINUTES)
|
||||
.readTimeout(1, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
public static void trustAllClient() {
|
||||
Try.of(() -> {
|
||||
X509TrustManager x509TrustManager = new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[]{};
|
||||
}
|
||||
};
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
|
||||
|
||||
client = new OkHttpClient.Builder()
|
||||
.connectTimeout(1, TimeUnit.MINUTES)
|
||||
.readTimeout(1, TimeUnit.MINUTES)
|
||||
.sslSocketFactory(sslContext.getSocketFactory(), x509TrustManager)
|
||||
.hostnameVerifier((s, sslSession) -> true)
|
||||
.build();
|
||||
}).trap(Throwable::printStackTrace).run();
|
||||
}
|
||||
|
||||
public static String get(String url, Map<String, String> headers) {
|
||||
String resp;
|
||||
try {
|
||||
@@ -48,7 +85,7 @@ public class HttpUtil {
|
||||
.url(url)
|
||||
.headers(Headers.of(headers))
|
||||
.build();
|
||||
Response response = OK_HTTP_CLIENT.newCall(request).execute();
|
||||
Response response = client.newCall(request).execute();
|
||||
if (response.isSuccessful()) {
|
||||
resp = response.body() != null ? response.body().string() : "";
|
||||
} else {
|
||||
@@ -75,7 +112,7 @@ public class HttpUtil {
|
||||
.post(RequestBody.create(mediaType, body))
|
||||
.build();
|
||||
|
||||
Response response = OK_HTTP_CLIENT.newCall(request).execute();
|
||||
Response response = client.newCall(request).execute();
|
||||
if (response.isSuccessful()) {
|
||||
resp = response.body() != null ? response.body().string() : "";
|
||||
} else {
|
||||
@@ -117,7 +154,7 @@ public class HttpUtil {
|
||||
.post(builder.build())
|
||||
.headers(Headers.of(header))
|
||||
.build();
|
||||
Response response = OK_HTTP_CLIENT.newCall(request).execute();
|
||||
Response response = client.newCall(request).execute();
|
||||
if (response.isSuccessful()) {
|
||||
resp = response.body() != null ? response.body().string() : "";
|
||||
} else {
|
||||
@@ -136,5 +173,9 @@ public class HttpUtil {
|
||||
|
||||
return sb.substring(0, sb.length() - 1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
HttpUtil.trustAllClient();
|
||||
}
|
||||
}
|
||||
|
||||
108
budd-common/src/main/java/io/github/ehlxr/util/IdUtil.java
Normal file
108
budd-common/src/main/java/io/github/ehlxr/util/IdUtil.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.util;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 自增 id 生成工具类
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 18:32.
|
||||
*/
|
||||
@Component
|
||||
public class IdUtil {
|
||||
private final static String REDIS_ID_KEY = "com.tzld.piaoquan.incentive_";
|
||||
/**
|
||||
* 每一毫秒生成的最大数
|
||||
*/
|
||||
private static final int MAX_NUN = 99;
|
||||
private static final AtomicInteger ATOMIC_NUM = new AtomicInteger();
|
||||
private static RedisTemplate<String, String> redisTemplate;
|
||||
private static String cur_date;
|
||||
|
||||
public static long redisId() {
|
||||
// 生成 17 位的时间戳(每毫秒使用新的时间戳当key)
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
|
||||
String timeStamp = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
|
||||
// 获得 redis-key
|
||||
String newKey = String.format("%s:%s", REDIS_ID_KEY, timeStamp);
|
||||
// 获取自增值(时间戳 + 自定义 key)
|
||||
Long increment = redisTemplate.opsForValue().increment(newKey, 1);
|
||||
// 设置时间戳生成的 key 的有效期为 1 秒
|
||||
redisTemplate.expire(newKey, 1, TimeUnit.SECONDS);
|
||||
// 获取订单号,时间戳 + 唯一自增 Id(2 位数,不过前方补 0)
|
||||
return Long.parseLong(String.format("%s%02d", timeStamp, increment));
|
||||
}
|
||||
|
||||
// @Autowired
|
||||
// public IdUtil(RedisTemplate<String, Object> redisTemplate) {
|
||||
// IdUtil.redisTemplate = redisTemplate;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 生成 19 位数 id
|
||||
* <p>
|
||||
* 17 位日期 + 2 位自增数<br>
|
||||
* 一毫秒最多生成 MAX_NUN 个 id,同一毫秒 id 有序自增
|
||||
*/
|
||||
public static long localId() {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
|
||||
String nowStr = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
|
||||
|
||||
// 如果当前时间不是 cur_date 时间 设置 cur_date 为当前时间 重新开始计数
|
||||
if (!nowStr.equals(cur_date)) {
|
||||
cur_date = nowStr;
|
||||
|
||||
ATOMIC_NUM.set(0);
|
||||
}
|
||||
// 如果同一毫秒最大数大于 最大数 MAX_NUN 则等待 1 毫秒 重新计算
|
||||
if (ATOMIC_NUM.get() >= MAX_NUN) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
|
||||
nowStr = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
|
||||
ATOMIC_NUM.set(0);
|
||||
}
|
||||
|
||||
// 线程安全的原子操作,所以此方法无需同步 调用 incrementAndGet 函数来进行自增操作
|
||||
return Long.parseLong(String.format("%s%02d", nowStr, ATOMIC_NUM.incrementAndGet()));
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
|
||||
IdUtil.redisTemplate = redisTemplate;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.utils;
|
||||
package io.github.ehlxr.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@@ -30,6 +30,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.github.ehlxr.exception.JsonParseException;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
@@ -75,7 +76,7 @@ public class JsonUtils {
|
||||
try {
|
||||
return OBJECT_MAPPER.readTree(obj2String(obj));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +94,7 @@ public class JsonUtils {
|
||||
try {
|
||||
return obj instanceof String ? (String) obj : OBJECT_MAPPER.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ public class JsonUtils {
|
||||
try {
|
||||
return obj instanceof String ? (String) obj : OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +131,7 @@ public class JsonUtils {
|
||||
try {
|
||||
return clazz.equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, clazz);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +150,7 @@ public class JsonUtils {
|
||||
try {
|
||||
return typeReference.getType().equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, typeReference);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +168,7 @@ public class JsonUtils {
|
||||
try {
|
||||
return OBJECT_MAPPER.readValue(str, javaType);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,4 +247,3 @@ public class JsonUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.util;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-12-16 09:36.
|
||||
*/
|
||||
public class MyBloomFilter {
|
||||
/**
|
||||
* 一个长度为10 亿的比特位
|
||||
*/
|
||||
private static final int DEFAULT_SIZE = 256 << 22;
|
||||
|
||||
/**
|
||||
* 为了降低错误率,使用加法hash算法,所以定义一个8个元素的质数数组
|
||||
*/
|
||||
private static final int[] SEEDS = {3, 5, 7, 11, 13, 31, 37, 61};
|
||||
|
||||
/**
|
||||
* 相当于构建 8 个不同的hash算法
|
||||
*/
|
||||
private static final HashFunction[] HASH_FUNCS = new HashFunction[SEEDS.length];
|
||||
|
||||
/**
|
||||
* 初始化布隆过滤器的 bitmap
|
||||
*/
|
||||
private static final BitSet BIT_SET = new BitSet(DEFAULT_SIZE);
|
||||
|
||||
/**
|
||||
* 添加数据
|
||||
*
|
||||
* @param value 需要加入的值
|
||||
*/
|
||||
public static void add(String value) {
|
||||
if (value != null) {
|
||||
for (HashFunction f : HASH_FUNCS) {
|
||||
//计算 hash 值并修改 bitmap 中相应位置为 true
|
||||
BIT_SET.set(f.hash(value), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断相应元素是否存在
|
||||
*
|
||||
* @param value 需要判断的元素
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean contains(String value) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
boolean ret = true;
|
||||
for (HashFunction f : HASH_FUNCS) {
|
||||
ret = BIT_SET.get(f.hash(value));
|
||||
//一个 hash 函数返回 false 则跳出循环
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟用户是不是会员,或用户在不在线。。。
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < SEEDS.length; i++) {
|
||||
HASH_FUNCS[i] = new HashFunction(DEFAULT_SIZE, SEEDS[i]);
|
||||
}
|
||||
|
||||
// 添加1亿数据
|
||||
for (int i = 0; i < 1_0000_0000; i++) {
|
||||
add(String.valueOf(i));
|
||||
}
|
||||
String id = "123456789";
|
||||
add(id);
|
||||
|
||||
System.out.println(contains(id)); // true
|
||||
System.out.println("" + contains("234567890")); //false
|
||||
}
|
||||
}
|
||||
|
||||
class HashFunction {
|
||||
private final int size;
|
||||
private final int seed;
|
||||
|
||||
public HashFunction(int size, int seed) {
|
||||
this.size = size;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
public int hash(String value) {
|
||||
int result = 0;
|
||||
int len = value.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
result = seed * result + value.charAt(i);
|
||||
}
|
||||
int r = (size - 1) & result;
|
||||
return (size - 1) & result;
|
||||
}
|
||||
}
|
||||
312
budd-common/src/main/java/io/github/ehlxr/util/RedisUtil.java
Normal file
312
budd-common/src/main/java/io/github/ehlxr/util/RedisUtil.java
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.ListOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.data.redis.core.script.RedisScript;
|
||||
import org.springframework.scripting.support.StaticScriptSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* redis 操作
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 18:32.
|
||||
*/
|
||||
@Component
|
||||
public class RedisUtil {
|
||||
private static final Logger log = LoggerFactory.getLogger(RedisUtil.class);
|
||||
|
||||
/**
|
||||
* 解锁 lua 脚本
|
||||
*/
|
||||
private static final String UNLOCK = "if (redis.call('hexists', KEYS[1], ARGV[1]) == 0) then " +
|
||||
"return nil; " +
|
||||
"end; " +
|
||||
"local counter = redis.call('hincrby', KEYS[1], ARGV[1], -1); " +
|
||||
"if (counter > 0) then " +
|
||||
"return 0; " +
|
||||
"else " +
|
||||
"redis.call('del', KEYS[1]); " +
|
||||
"return 1; " +
|
||||
"end; " +
|
||||
"return nil;";
|
||||
/**
|
||||
* 锁前缀
|
||||
*/
|
||||
private static final String LOCK_PREFIX = "LOCK_";
|
||||
/**
|
||||
* 默认重试次数
|
||||
*/
|
||||
private static final Integer DEFAULT_RETRIES = 1;
|
||||
/**
|
||||
* 默认 10毫秒
|
||||
*/
|
||||
private static final Long DEFAULT_INTERVAL = 10L;
|
||||
/**
|
||||
* 加锁 lua 脚本
|
||||
*/
|
||||
private static final String LOCK = "if (redis.call('exists', KEYS[1]) == 0) then " +
|
||||
"redis.call('hset', KEYS[1], ARGV[2], 1); " +
|
||||
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
|
||||
"return 1; " +
|
||||
"end; " +
|
||||
"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
|
||||
"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
|
||||
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
|
||||
"return 1; " +
|
||||
"end; " +
|
||||
"return 0;";
|
||||
private static RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
/**
|
||||
* 释放分布式锁时使用的 lua 脚本,保证原子性
|
||||
* <p>
|
||||
* if (redis.call('get', KEYS[1]) == ARGV[1])
|
||||
* then
|
||||
* return redis.call('del', KEYS[1])
|
||||
* else
|
||||
* return 0
|
||||
* end
|
||||
*/
|
||||
private static final String RELEASE_LOCK_LUA = "if (redis.call('get', KEYS[1]) == ARGV[1]) then return redis.call('del', KEYS[1]) else return 0 end";
|
||||
|
||||
/**
|
||||
* 滑动窗口限流使用的 lua 脚本,保证原子性
|
||||
* <p>
|
||||
* local key = KEYS[1];
|
||||
* local index = tonumber(ARGV[1]);
|
||||
* local time_window = tonumber(ARGV[2]);
|
||||
* local now_time = tonumber(ARGV[3]);
|
||||
* local far_time = redis.call('lindex', key, index);
|
||||
* if (not far_time)
|
||||
* then
|
||||
* redis.call('lpush', key, now_time);
|
||||
* redis.call('pexpire', key, time_window+1000);
|
||||
* return 1;
|
||||
* end
|
||||
* if (now_time - far_time > time_window)
|
||||
* then
|
||||
* redis.call('rpop', key);
|
||||
* redis.call('lpush', key, now_time);
|
||||
* redis.call('pexpire', key, time_window+1000);
|
||||
* return 1;
|
||||
* else
|
||||
* return 0;
|
||||
* end
|
||||
*/
|
||||
private static final String SLIDE_WINDOW_LUA = "local key = KEYS[1];\n" + "local index = tonumber(ARGV[1]);\n" + "local time_window = tonumber(ARGV[2]);\n" + "local now_time = tonumber(ARGV[3]);\n" + "local far_time = redis.call('lindex', key, index);\n" + "if (not far_time)\n" + "then\n" + " redis.call('lpush', key, now_time);\n" + " redis.call('pexpire', key, time_window+1000);\n" + " return 1;\n" + "end\n" + "\n" + "if (now_time - far_time > time_window)\n" + "then\n" + " redis.call('rpop', key);\n" + " redis.call('lpush', key, now_time);\n" + " redis.call('pexpire', key, time_window+1000);\n" + " return 1;\n" + "else\n" + " return 0;\n" + "end";
|
||||
|
||||
/**
|
||||
* 获取分布式锁
|
||||
*
|
||||
* @param key key
|
||||
* @param value value,需要保证全局唯一,用来删除分布式锁时判断身份使用
|
||||
* @param expireTime 锁过期时间,毫秒,防止业务崩溃未删除锁,导致死锁
|
||||
* @return 是否获取成功锁
|
||||
*/
|
||||
public static boolean getDistributedLock(String key, String value, long expireTime) {
|
||||
boolean result = false;
|
||||
try {
|
||||
Boolean set = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS);
|
||||
result = set == null || set;
|
||||
log.info("getLock redis key: {}, value: {}, expireTime: {}, result: {}", key, value, expireTime, result);
|
||||
} catch (Exception e) {
|
||||
log.error("getLock redis key: {}, value: {}, expireTime: {}", key, value, expireTime, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放分布式锁
|
||||
*
|
||||
* @param key key
|
||||
* @param value value,需要和获取锁时传入的一致
|
||||
* @return 是否释放成功锁
|
||||
*/
|
||||
public static boolean releaseDistributedLock(String key, String value) {
|
||||
Long execute = null;
|
||||
try {
|
||||
RedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA, Long.class);
|
||||
execute = redisTemplate.execute(redisScript, Collections.singletonList(key), value);
|
||||
log.debug("releaseLock redis key: {}, value: {}, result: {}", key, value, execute);
|
||||
} catch (Exception e) {
|
||||
log.error("releaseLock redis key: {}, value: {}", key, value, e);
|
||||
}
|
||||
return Long.valueOf(1L).equals(execute);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分布式限流队列,在时间窗口内(包含该时间点),判断是否达到限流的阀值
|
||||
* 本接口实现的方法通过加锁避免并发问题,性能不高。只是为了说明限流逻辑如何实现
|
||||
*
|
||||
* @param key key
|
||||
* @param count 限流阀值
|
||||
* @param timeWindow 限流时间窗口
|
||||
* @return 是否允许通过(通过即不进行限流)
|
||||
*/
|
||||
public static synchronized boolean slideWindow(String key, int count, long timeWindow) {
|
||||
try {
|
||||
long nowTime = System.currentTimeMillis();
|
||||
ListOperations<String, String> list = redisTemplate.opsForList();
|
||||
String farTime = list.index(key, count - 1);
|
||||
if (farTime == null) {
|
||||
list.leftPush(key, String.valueOf(nowTime));
|
||||
redisTemplate.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS);
|
||||
return true;
|
||||
}
|
||||
if (nowTime - Long.parseLong(farTime) > timeWindow) {
|
||||
list.rightPop(key);
|
||||
list.leftPush(key, String.valueOf(nowTime));
|
||||
redisTemplate.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分布式限流队列,在时间窗口内(包含该时间点),判断是否达到限流的阀值
|
||||
* 本接口实现的方法通过 Lua 脚本避免并发问题,性能较高。
|
||||
*
|
||||
* @param key key
|
||||
* @param count 限流阀值
|
||||
* @param timeWindow 限流时间窗口
|
||||
* @return 是否允许通过(通过即不进行限流)
|
||||
*/
|
||||
public static boolean slideWindowLua(String key, int count, long timeWindow) {
|
||||
if (count <= 0 || timeWindow <= 0) {
|
||||
return false;
|
||||
}
|
||||
Long execute = null;
|
||||
try {
|
||||
RedisScript<Long> redisScript = new DefaultRedisScript<>(SLIDE_WINDOW_LUA, Long.class);
|
||||
execute = redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(count - 1), String.valueOf(timeWindow), String.valueOf(System.currentTimeMillis()));
|
||||
log.debug("slideWindowLua redis key: {}, count: {}, timeWindow: {}, result: {}", key, count, timeWindow, execute);
|
||||
} catch (Exception e) {
|
||||
log.error("slideWindowLua redis key: {}, count: {}, timeWindow: {}", key, count, timeWindow, e);
|
||||
}
|
||||
return Long.valueOf(1L).equals(execute);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加锁 不可重入
|
||||
*
|
||||
* @param timeout 毫秒
|
||||
*/
|
||||
public static Boolean lock(String key, long timeout) {
|
||||
return redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + key, "1", timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解锁 不可重入
|
||||
*/
|
||||
public static Boolean unlock(String key) {
|
||||
return redisTemplate.delete(LOCK_PREFIX + key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加锁
|
||||
*
|
||||
* @param reentrantId 重入Id
|
||||
* 超时时间 毫秒ms
|
||||
*/
|
||||
public static Boolean lock(String key, String reentrantId, long timeout) {
|
||||
return lock(key, reentrantId, timeout, DEFAULT_RETRIES);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加锁
|
||||
*
|
||||
* @param reentrantId 重入Id
|
||||
* 超时时间 毫秒ms
|
||||
* @param retries 重试次数
|
||||
*/
|
||||
public static Boolean lock(String key, String reentrantId, long timeout, int retries) {
|
||||
return lock(key, reentrantId, timeout, retries, DEFAULT_INTERVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加锁
|
||||
*
|
||||
* @param reentrantId 重入Id
|
||||
* 超时时间 毫秒ms
|
||||
* @param retries 重试次数
|
||||
* @param interval 每次重试间隔时间 毫秒
|
||||
*/
|
||||
public static Boolean lock(String key, String reentrantId, long timeout, int retries, long interval) {
|
||||
String lockKey = LOCK_PREFIX + key;
|
||||
DefaultRedisScript<Long> script = new DefaultRedisScript<>();
|
||||
script.setResultType(Long.class);
|
||||
script.setScriptSource(new StaticScriptSource(LOCK));
|
||||
for (int i = 0; i < retries; i++) {
|
||||
Object result = redisTemplate.execute(script, Collections.singletonList(lockKey), String.valueOf(timeout), reentrantId);
|
||||
if (Objects.nonNull(result) && Objects.equals(1L, Long.valueOf(result.toString()))) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解锁
|
||||
*
|
||||
* @param reentrantId 重入ID
|
||||
*/
|
||||
public static Boolean unlock(String key, String reentrantId) {
|
||||
String lockKey = LOCK_PREFIX + key;
|
||||
DefaultRedisScript<Long> script = new DefaultRedisScript<>();
|
||||
script.setResultType(Long.class);
|
||||
script.setScriptSource(new StaticScriptSource(UNLOCK));
|
||||
Object result = redisTemplate.execute(script, Collections.singletonList(lockKey), reentrantId);
|
||||
if (Objects.isNull(result)) {
|
||||
return null;
|
||||
}
|
||||
return Objects.equals(1L, Long.valueOf(result.toString()));
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
|
||||
RedisUtil.redisTemplate = redisTemplate;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,9 +22,11 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.utils;
|
||||
package io.github.ehlxr.util;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -48,11 +50,11 @@ public class SendAlarmUtil {
|
||||
/**
|
||||
* 异步发送预警信息
|
||||
*
|
||||
* @param msg 预警信息
|
||||
* @param action {@link BiConsumer} 完成后回调函数式接口
|
||||
* @param message 预警信息
|
||||
* @param action {@link BiConsumer} 完成后回调函数式接口
|
||||
*/
|
||||
public static void send(String msg, BiConsumer<? super String, ? super Throwable> action) {
|
||||
// String msg = String.format("%s\ntraceid: %s", msg, MDC.get(Constants.LOG_TRACE_ID));
|
||||
public static void send(String message, BiConsumer<? super String, ? super Throwable> action) {
|
||||
String msg = String.format("%s\ntraceid: %s", message, MDC.get(Constant.LOG_TRACE_ID));
|
||||
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
Objects.requireNonNull(dingtalkUrl, "SendAlarmUtil not init.");
|
||||
@@ -79,10 +81,10 @@ public class SendAlarmUtil {
|
||||
.trap(System.out::println)
|
||||
.run();
|
||||
|
||||
send("dsfsdf",
|
||||
send("hello",
|
||||
(t, u) -> System.out.println("send exception message to dingtalk result " + t + ". " + u));
|
||||
|
||||
System.out.println("000000");
|
||||
System.out.println("do other something....");
|
||||
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.utils;
|
||||
package io.github.ehlxr.util;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -84,6 +84,163 @@ public interface Try {
|
||||
return new TryRunnable(runnable);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ConstantConditions", "Convert2MethodRef"})
|
||||
static void main(String[] args) {
|
||||
System.out.println("------------有返回值,无入参----------------");
|
||||
// 有返回值,无入参
|
||||
String param = "hello";
|
||||
Long result = Try.of(() -> Long.valueOf(param)).get(0L);
|
||||
System.out.println("Long.valueOf 1: " + result);
|
||||
|
||||
result = Try.of(() -> Long.valueOf(param)).get();
|
||||
System.out.println("Long.valueOf 2: " + result);
|
||||
|
||||
System.out.println("------------有返回值,有入参----------------");
|
||||
// 有返回值,有入参
|
||||
result = Try.<Map<String, String>, Long>of(s -> Long.valueOf(s.get("k1")))
|
||||
.apply(ImmutableMap.of("k1", param))
|
||||
.trap(e -> System.out.println("Long.valueOf exception: " + e.getMessage()))
|
||||
.andFinally(() -> System.out.println("This message will ignore."))
|
||||
.andFinally(s -> {
|
||||
Map<String, Object> returnMap = JsonUtils.string2Obj(JsonUtils.obj2String(s), new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
System.out.println("Long.valueOf finally run code." + s);
|
||||
// 演示抛异常
|
||||
String k2 = returnMap.get("k2").toString();
|
||||
System.out.println(k2);
|
||||
})
|
||||
.finallyTrap(e -> System.out.println("Long.valueOf finally exception: " + e.getMessage()))
|
||||
.get();
|
||||
System.out.println("Long.valueOf 3: " + result);
|
||||
|
||||
ArrayList<String> list = null;
|
||||
|
||||
System.out.println("-----------无返回值,无入参-----------------");
|
||||
// 无返回值,无入参
|
||||
Try.of(() -> Thread.sleep(-1L))
|
||||
.andFinally(() -> list.clear())
|
||||
// .andFinally(list::clear) //https://stackoverflow.com/questions/37413106/java-lang-nullpointerexception-is-thrown-using-a-method-reference-but-not-a-lamb
|
||||
.run();
|
||||
|
||||
System.out.println("--------------无返回值,有入参--------------");
|
||||
// 无返回值,有入参
|
||||
Try.<String>of(v -> list.add(0, v))
|
||||
.andFinally(s -> System.out.println(s))
|
||||
.accept("hello");
|
||||
}
|
||||
|
||||
class TryRunnable extends Tryable<TryRunnable> {
|
||||
private final ThrowableRunnable runnable;
|
||||
|
||||
protected TryRunnable(ThrowableRunnable runnable) {
|
||||
Objects.requireNonNull(runnable, "No runnable present");
|
||||
this.runnable = runnable;
|
||||
|
||||
super.c = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算结果
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (final Throwable e) {
|
||||
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
|
||||
} finally {
|
||||
doFinally();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TrySupplier<R> extends Tryable<TrySupplier<R>> {
|
||||
private final ThrowableSupplier<? extends R> supplier;
|
||||
|
||||
protected TrySupplier(ThrowableSupplier<? extends R> supplier) {
|
||||
Objects.requireNonNull(supplier, "No supplier present");
|
||||
this.supplier = supplier;
|
||||
|
||||
super.c = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果有异常返回默认值,否则返回计算结果
|
||||
*
|
||||
* @param r 指定默认值
|
||||
* @return 实际值或默认值
|
||||
*/
|
||||
public R get(R r) {
|
||||
try {
|
||||
return supplier.get();
|
||||
} catch (final Throwable e) {
|
||||
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
|
||||
return r;
|
||||
} finally {
|
||||
doFinally();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果有异常返回 null,否则返回计算结果
|
||||
*
|
||||
* @return 实际值或 null
|
||||
*/
|
||||
public R get() {
|
||||
try {
|
||||
return supplier.get();
|
||||
} catch (final Throwable e) {
|
||||
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
|
||||
return null;
|
||||
} finally {
|
||||
doFinally();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowableConsumer<P> {
|
||||
/**
|
||||
* Performs this operation on the given argument.
|
||||
*
|
||||
* @param p the input argument
|
||||
* @throws Throwable throwable
|
||||
*/
|
||||
void accept(P p) throws Throwable;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowableSupplier<R> {
|
||||
/**
|
||||
* Gets a result.
|
||||
*
|
||||
* @return a result
|
||||
* @throws Throwable throwable
|
||||
*/
|
||||
R get() throws Throwable;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowableRunnable {
|
||||
/**
|
||||
* Performs this operation
|
||||
*
|
||||
* @throws Throwable throwable
|
||||
*/
|
||||
void run() throws Throwable;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowableFunction<P, R> {
|
||||
/**
|
||||
* Applies this function to the given argument.
|
||||
*
|
||||
* @param p the function argument
|
||||
* @return the function result
|
||||
* @throws Throwable throwable
|
||||
*/
|
||||
R apply(P p) throws Throwable;
|
||||
}
|
||||
|
||||
abstract class Tryable<C> {
|
||||
Consumer<? super Throwable> throwConsumer;
|
||||
ThrowableRunnable finallyRunnable;
|
||||
@@ -175,74 +332,6 @@ public interface Try {
|
||||
}
|
||||
}
|
||||
|
||||
class TryRunnable extends Tryable<TryRunnable> {
|
||||
private final ThrowableRunnable runnable;
|
||||
|
||||
protected TryRunnable(ThrowableRunnable runnable) {
|
||||
Objects.requireNonNull(runnable, "No runnable present");
|
||||
this.runnable = runnable;
|
||||
|
||||
super.c = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算结果
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (final Throwable e) {
|
||||
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
|
||||
} finally {
|
||||
doFinally();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TrySupplier<R> extends Tryable<TrySupplier<R>> {
|
||||
private final ThrowableSupplier<? extends R> supplier;
|
||||
|
||||
protected TrySupplier(ThrowableSupplier<? extends R> supplier) {
|
||||
Objects.requireNonNull(supplier, "No supplier present");
|
||||
this.supplier = supplier;
|
||||
|
||||
super.c = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果有异常返回默认值,否则返回计算结果
|
||||
*
|
||||
* @param r 指定默认值
|
||||
* @return 实际值或默认值
|
||||
*/
|
||||
public R get(R r) {
|
||||
try {
|
||||
return supplier.get();
|
||||
} catch (final Throwable e) {
|
||||
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
|
||||
return r;
|
||||
} finally {
|
||||
doFinally();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果有异常返回 null,否则返回计算结果
|
||||
*
|
||||
* @return 实际值或 null
|
||||
*/
|
||||
public R get() {
|
||||
try {
|
||||
return supplier.get();
|
||||
} catch (final Throwable e) {
|
||||
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
|
||||
return null;
|
||||
} finally {
|
||||
doFinally();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TryConsumer<P> extends Tryable<TryConsumer<P>> {
|
||||
private final ThrowableConsumer<? super P> consumer;
|
||||
|
||||
@@ -335,93 +424,4 @@ public interface Try {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowableConsumer<P> {
|
||||
/**
|
||||
* Performs this operation on the given argument.
|
||||
*
|
||||
* @param p the input argument
|
||||
* @throws Throwable throwable
|
||||
*/
|
||||
void accept(P p) throws Throwable;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowableSupplier<R> {
|
||||
/**
|
||||
* Gets a result.
|
||||
*
|
||||
* @return a result
|
||||
* @throws Throwable throwable
|
||||
*/
|
||||
R get() throws Throwable;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowableRunnable {
|
||||
/**
|
||||
* Performs this operation
|
||||
*
|
||||
* @throws Throwable throwable
|
||||
*/
|
||||
void run() throws Throwable;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowableFunction<P, R> {
|
||||
/**
|
||||
* Applies this function to the given argument.
|
||||
*
|
||||
* @param p the function argument
|
||||
* @return the function result
|
||||
* @throws Throwable throwable
|
||||
*/
|
||||
R apply(P p) throws Throwable;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ConstantConditions", "Convert2MethodRef"})
|
||||
static void main(String[] args) {
|
||||
System.out.println("------------有返回值,无入参----------------");
|
||||
// 有返回值,无入参
|
||||
String param = "hello";
|
||||
Long result = Try.of(() -> Long.valueOf(param)).get(0L);
|
||||
System.out.println("Long.valueOf 1: " + result);
|
||||
|
||||
result = Try.of(() -> Long.valueOf(param)).get();
|
||||
System.out.println("Long.valueOf 2: " + result);
|
||||
|
||||
System.out.println("------------有返回值,有入参----------------");
|
||||
// 有返回值,有入参
|
||||
result = Try.<Map<String, String>, Long>of(s -> Long.valueOf(s.get("k1")))
|
||||
.apply(ImmutableMap.of("k1", param))
|
||||
.trap(e -> System.out.println("Long.valueOf exception: " + e.getMessage()))
|
||||
.andFinally(() -> System.out.println("This message will ignore."))
|
||||
.andFinally(s -> {
|
||||
Map<String, Object> returnMap = JsonUtils.string2Obj(JsonUtils.obj2String(s), new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
System.out.println("Long.valueOf finally run code." + s);
|
||||
// 演示抛异常
|
||||
String k2 = returnMap.get("k2").toString();
|
||||
System.out.println(k2);
|
||||
})
|
||||
.finallyTrap(e -> System.out.println("Long.valueOf finally exception: " + e.getMessage()))
|
||||
.get();
|
||||
System.out.println("Long.valueOf 3: " + result);
|
||||
|
||||
ArrayList<String> list = null;
|
||||
|
||||
System.out.println("-----------无返回值,无入参-----------------");
|
||||
// 无返回值,无入参
|
||||
Try.of(() -> Thread.sleep(-1L))
|
||||
.andFinally(() -> list.clear())
|
||||
// .andFinally(list::clear) //https://stackoverflow.com/questions/37413106/java-lang-nullpointerexception-is-thrown-using-a-method-reference-but-not-a-lamb
|
||||
.run();
|
||||
|
||||
System.out.println("--------------无返回值,有入参--------------");
|
||||
// 无返回值,有入参
|
||||
Try.<String>of(v -> list.add(0, v))
|
||||
.andFinally(s -> System.out.println(s))
|
||||
.accept("hello");
|
||||
}
|
||||
}
|
||||
18
budd-demo/pom.xml
Normal file
18
budd-demo/pom.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>budd-demo</artifactId>
|
||||
<name>budd-demo</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd-common</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -26,10 +26,17 @@ package io.github.ehlxr;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-07-07 22:54.
|
||||
* @since 2022-01-17 06:31.
|
||||
*/
|
||||
public class ClassLoaderTest {
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println(ClassLoader.getSystemClassLoader());
|
||||
int[][] ns = {
|
||||
{ 1, 2, 3, 4 },
|
||||
{ 5, 6, 7, 8 },
|
||||
{ 9, 10, 11, 12 }
|
||||
};
|
||||
System.out.println(ns.length); // 3
|
||||
System.out.println(ns[0].length); // 4
|
||||
System.out.println(ns[2][2]); // 11
|
||||
}
|
||||
}
|
||||
260
budd-demo/src/main/java/io/github/ehlxr/ManagedBlockerTest.java
Normal file
260
budd-demo/src/main/java/io/github/ehlxr/ManagedBlockerTest.java
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-09-02 15:52.
|
||||
*/
|
||||
public class ManagedBlockerTest {
|
||||
static String threadDateTimeInfo() {
|
||||
return DateTimeFormatter.ISO_TIME.format(LocalTime.now()) + Thread.currentThread().getName();
|
||||
}
|
||||
|
||||
static void test1() {
|
||||
List<RecursiveTask<String>> tasks = Stream.generate(() -> new RecursiveTask<String>() {
|
||||
private static final long serialVersionUID = 1303648247573881735L;
|
||||
|
||||
@Override
|
||||
protected String compute() {
|
||||
System.out.println(threadDateTimeInfo() + ":simulate io task blocking for 2 seconds···");
|
||||
try {
|
||||
//线程休眠2秒模拟IO调用阻塞
|
||||
TimeUnit.SECONDS.sleep(2);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
return threadDateTimeInfo() + ": io blocking task returns successfully";
|
||||
}
|
||||
}).limit(28).collect(Collectors.toList());
|
||||
|
||||
tasks.forEach(ForkJoinTask::fork);
|
||||
tasks.forEach(e -> {
|
||||
try {
|
||||
System.out.println(e.get());
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Stopwatch started = Stopwatch.createStarted();
|
||||
test4();
|
||||
System.out.println(started);
|
||||
}
|
||||
|
||||
static void test2() {
|
||||
List<IoBlockerTask<String>> tasks = Stream.generate(() -> new IoBlockerTask<>(() -> {
|
||||
System.out.println(threadDateTimeInfo() + ":simulate io task blocking for 2 seconds···");
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(2);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
return threadDateTimeInfo() + ": io blocking task returns successfully";
|
||||
})).limit(28).collect(Collectors.toList());
|
||||
|
||||
tasks.forEach(ForkJoinTask::fork);
|
||||
tasks.forEach(e -> {
|
||||
try {
|
||||
System.out.println(e.get());
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
static void test3() {
|
||||
List<IoBlockerAction> actions = Stream.generate(() -> new IoBlockerAction(() -> {
|
||||
System.out.println(threadDateTimeInfo() + ":simulate io action blocking for 2 seconds···");
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(2);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
System.out.println(threadDateTimeInfo() + ": io blocking action successfully");
|
||||
})).limit(56).collect(Collectors.toList());
|
||||
|
||||
//如果不使用 ManagedBlocker 耗时估算: 56/7(8 cpu - 1) = 8 * 2 =16s,实际 约等于 2s
|
||||
|
||||
actions.forEach(ForkJoinTask::fork);
|
||||
actions.forEach(ForkJoinTask::join);
|
||||
}
|
||||
|
||||
static void test4() {
|
||||
List<IoBlockerAction2<Integer>> actions = Stream.generate(() -> new IoBlockerAction2<>((x) -> {
|
||||
System.out.println(threadDateTimeInfo() + ":simulate io action blocking for 2 seconds···" + x);
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(2);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
System.out.println(threadDateTimeInfo() + ": io blocking action successfully " + x);
|
||||
}, 1)).limit(56).collect(Collectors.toList());
|
||||
|
||||
//如果不使用 ManagedBlocker 耗时估算: 56/7(8 cpu - 1) = 8 * 2 =16s,实际 约等于 2s
|
||||
|
||||
actions.forEach(x -> {
|
||||
x.fork();
|
||||
System.out.println("fork {}"+ x);
|
||||
});
|
||||
actions.forEach(x -> {
|
||||
x.join();
|
||||
System.out.println("join {}"+ x);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class IoBlockerAction2<T> extends RecursiveAction {
|
||||
private static final long serialVersionUID = -4114798302790287199L;
|
||||
private final MyManagedBlockerImpl<T> blocker;
|
||||
|
||||
public IoBlockerAction2(Consumer<T> consumer, T t) {
|
||||
this.blocker = new MyManagedBlockerImpl<>(consumer, t);
|
||||
}
|
||||
|
||||
static class MyManagedBlockerImpl<T> implements ForkJoinPool.ManagedBlocker {
|
||||
private final Consumer<T> consumer;
|
||||
private final T t;
|
||||
|
||||
public MyManagedBlockerImpl(Consumer<T> consumer, T t) {
|
||||
this.consumer = consumer;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean block() {
|
||||
consumer.accept(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReleasable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute() {
|
||||
try {
|
||||
ForkJoinPool.managedBlock(blocker);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IoBlockerAction extends RecursiveAction {
|
||||
private static final long serialVersionUID = -4114798302790287199L;
|
||||
private final MyManagedBlockerImpl blocker;
|
||||
|
||||
public IoBlockerAction(Runnable runnable) {
|
||||
this.blocker = new MyManagedBlockerImpl(runnable);
|
||||
}
|
||||
|
||||
static class MyManagedBlockerImpl implements ForkJoinPool.ManagedBlocker {
|
||||
private final Runnable runnable;
|
||||
|
||||
public MyManagedBlockerImpl(Runnable runnable) {
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean block() {
|
||||
runnable.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReleasable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute() {
|
||||
try {
|
||||
ForkJoinPool.managedBlock(blocker);
|
||||
// setRawResult(blocker.result);
|
||||
// return getRawResult();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IoBlockerTask<T> extends RecursiveTask<T> {
|
||||
private static final long serialVersionUID = -4114798302790287199L;
|
||||
private final MyManagedBlockerImpl<T> blocker;
|
||||
|
||||
public IoBlockerTask(Supplier<T> supplier) {
|
||||
this.blocker = new MyManagedBlockerImpl<>(supplier);
|
||||
}
|
||||
|
||||
static class MyManagedBlockerImpl<T> implements ForkJoinPool.ManagedBlocker {
|
||||
private final Supplier<T> supplier;
|
||||
private T result;
|
||||
|
||||
public MyManagedBlockerImpl(Supplier<T> supplier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean block() {
|
||||
result = supplier.get();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReleasable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T compute() {
|
||||
try {
|
||||
ForkJoinPool.managedBlock(blocker);
|
||||
setRawResult(blocker.result);
|
||||
return getRawResult();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
budd-server/pom.xml
Normal file
59
budd-server/pom.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>budd-server</artifactId>
|
||||
<name>budd-server</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.spring4all</groupId>
|
||||
<artifactId>swagger-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd-demo</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -26,14 +26,16 @@ package io.github.ehlxr;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 09:35.
|
||||
* @since 2021-08-29 18:32.
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class BuddApplication {
|
||||
@ServletComponentScan("io.github.ehlxr.filter")
|
||||
public class BuddServerApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BuddApplication.class, args);
|
||||
SpringApplication.run(BuddServerApplication.class, args);
|
||||
}
|
||||
}
|
||||
141
budd-server/src/main/java/io/github/ehlxr/aop/LogRequestAop.java
Normal file
141
budd-server/src/main/java/io/github/ehlxr/aop/LogRequestAop.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.aop;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import io.github.ehlxr.util.JsonUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 请求日志记录
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-17 22:03.
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class LogRequestAop {
|
||||
private static final Logger log = LoggerFactory.getLogger(LogRequestAop.class);
|
||||
|
||||
// private final AliyunLogManager aliyunLogManager;
|
||||
// /**
|
||||
// * aliyun log 配置
|
||||
// */
|
||||
// @Value("${aliyun.log.project:}")
|
||||
// private String projcet;
|
||||
// @Value("${aliyun.log.logstore.request:}")
|
||||
// private String logStore;
|
||||
// @Value("${aliyun.log.topic:}")
|
||||
// private String topic;
|
||||
|
||||
// @Autowired
|
||||
// public LogRequestAop(AliyunLogManager aliyunLogManager) {
|
||||
// this.aliyunLogManager = aliyunLogManager;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 切入点
|
||||
*/
|
||||
@Pointcut("execution(public * io.github.ehlxr.*Controller.*(..)) && !@annotation(io.github.ehlxr.annotations.NoRequestLog)")
|
||||
// @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && !@annotation(com.tzld.piaoquan.incentive.annotations.NoRequestLog)")
|
||||
public void requestLog() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 前置操作
|
||||
*/
|
||||
@Before("requestLog()")
|
||||
public void beforeLog() {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
|
||||
|
||||
request.setAttribute(Constant.REQUEST_START_TIME, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 后置操作
|
||||
*/
|
||||
@AfterReturning(pointcut = "requestLog()", returning = "returnValue")
|
||||
public void afterReturning(JoinPoint point, Object returnValue) {
|
||||
logRecord(point, JsonUtils.obj2String(returnValue));
|
||||
}
|
||||
|
||||
@AfterThrowing(pointcut = "requestLog()", throwing = "ex")
|
||||
public void afterThrowing(JoinPoint point, Exception ex) {
|
||||
logRecord(point, ex.getMessage());
|
||||
}
|
||||
|
||||
private void logRecord(JoinPoint point, String message) {
|
||||
try {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
|
||||
|
||||
Long startTime = (Long) request.getAttribute(Constant.REQUEST_START_TIME);
|
||||
if (Objects.isNull(startTime)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String query = request.getQueryString();
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
Map<String, Object> logMap = new HashMap<>(8);
|
||||
logMap.put("url", Strings.isNullOrEmpty(query) ? uri : uri + "?" + query);
|
||||
logMap.put("method", request.getMethod());
|
||||
logMap.put("header", getHeaders(request));
|
||||
logMap.put("elapsedTime", String.valueOf(System.currentTimeMillis() - startTime));
|
||||
logMap.put("clientIp", request.getRemoteAddr());
|
||||
logMap.put("requestBody", JsonUtils.obj2String(point.getArgs()));
|
||||
logMap.put(Constant.LOG_TRACE_ID, Strings.nullToEmpty(MDC.get(Constant.LOG_TRACE_ID)));
|
||||
logMap.put("responseBody", message);
|
||||
|
||||
// aliyunLogManager.sendLog(projcet, logStore, topic, logMap);
|
||||
} catch (Exception e) {
|
||||
log.error("log report request error", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getHeaders(HttpServletRequest request) {
|
||||
return Collections.list(request.getHeaderNames())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(
|
||||
name -> name,
|
||||
request::getHeader)).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package io.github.ehlxr.config;
|
||||
|
||||
|
||||
import io.github.ehlxr.util.SendAlarmUtil;
|
||||
import io.github.ehlxr.util.Try;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 项目初始化
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2020/4/22.
|
||||
*/
|
||||
@Component
|
||||
public class Initialization implements ApplicationRunner {
|
||||
private static final Logger log = LoggerFactory.getLogger(Initialization.class);
|
||||
|
||||
@Value("${aliyun.oss.endpoint:}")
|
||||
private String endpoint;
|
||||
@Value("${aliyun.oss.accesskey.id:}")
|
||||
private String accessKeyId;
|
||||
@Value("${aliyun.oss.accesskey.secret:}")
|
||||
private String accessKeySecret;
|
||||
@Value("${aliyun.oss.bucket:}")
|
||||
private String bucket;
|
||||
@Value("${aliyun.oss.key-path:}")
|
||||
private String keyPath;
|
||||
@Value("${aliyun.oss.url-lifetime:0}")
|
||||
private Long urlLifetime;
|
||||
|
||||
@Value("${lk.jmeter.cmd:}")
|
||||
private String jmeterCmd;
|
||||
@Value("${location:}")
|
||||
private String location;
|
||||
|
||||
@Value("${lk.dingtalk-url:}")
|
||||
private String dingtalkUrl;
|
||||
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
// 初始化阿里云 OSS 配置信息
|
||||
// AliyunOssConfig config = AliyunOssConfig.newBuilder()
|
||||
// .endpoint(endpoint)
|
||||
// .accessKeyId(accessKeyId)
|
||||
// .accessKeySecret(accessKeySecret)
|
||||
// .bucketName(bucket)
|
||||
// .keyPath(keyPath)
|
||||
// .urlLifetime(urlLifetime)
|
||||
// .build();
|
||||
// log.info("aliyun oss config {}", config);
|
||||
// FileUploadUtil.init(config);
|
||||
//
|
||||
// if (!"develop".equals(location) && !"PRO2".equals(location)) {
|
||||
// try {
|
||||
// ExecShell.execShellCommand(jmeterCmd);
|
||||
// } catch (Exception e) {
|
||||
// log.error("exec jmeter cmd error {}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
// 预警信息发送初始化
|
||||
Try.of(() -> SendAlarmUtil.init(dingtalkUrl))
|
||||
.trap(e -> log.warn("int SendAlarmUtil error: {}", e.getMessage()))
|
||||
.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2022 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.config;
|
||||
|
||||
// import com.ctrip.framework.apollo.model.ConfigChangeEvent;
|
||||
// import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.logging.LoggingSystem;
|
||||
// import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 结合 apollo 配置中心动态刷新(logging.level.)日志级别
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2022-01-06 17:43.
|
||||
*/
|
||||
// @Component
|
||||
public class LoggerLevelRefresher {
|
||||
private static final Logger logger = LoggerFactory.getLogger(LoggerLevelRefresher.class);
|
||||
private static final String LOGGER_TAG = "logging.level.";
|
||||
private final LoggingSystem loggingSystem;
|
||||
|
||||
@Autowired
|
||||
public LoggerLevelRefresher(LoggingSystem loggingSystem) {
|
||||
this.loggingSystem = loggingSystem;
|
||||
}
|
||||
|
||||
// @ApolloConfigChangeListener(interestedKeyPrefixes = LOGGER_TAG)
|
||||
// private void onChange(ConfigChangeEvent changeEvent) {
|
||||
// for (String key : changeEvent.changedKeys()) {
|
||||
// String strLevel = changeEvent.getChange(key).getNewValue();
|
||||
// loggingSystem.setLogLevel(key.replaceAll(LOGGER_TAG, ""),
|
||||
// LogLevel.valueOf(strLevel.toUpperCase()));
|
||||
//
|
||||
// logger.info("logging changed: {}, oldValue: {}, newValue: {}",
|
||||
// key, changeEvent.getChange(key).getOldValue(), strLevel);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,25 +22,34 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.extension;
|
||||
package io.github.ehlxr.controller;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 把一个接口标识成扩展点。
|
||||
* <p>
|
||||
* 没有此注释的接口 {@link ExtensionLoader} 会拒绝接管
|
||||
*
|
||||
* @author ehlxr
|
||||
* @see ExtensionLoader
|
||||
* @since 2021-08-29 18:45.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface SPI {
|
||||
@RestController
|
||||
@Api(tags = "测试辅助接口")
|
||||
public class IndexController {
|
||||
private static final Logger log = LoggerFactory.getLogger(IndexController.class);
|
||||
|
||||
/**
|
||||
* the default extension name.
|
||||
* 健康检测
|
||||
*/
|
||||
String value() default "";
|
||||
@ApiOperation(value = "健康检测", notes = "健康检测")
|
||||
@GetMapping("/healthcheck")
|
||||
public String healthcheck() {
|
||||
log.debug("env {}", System.getProperty("env"));
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,36 +22,41 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.redis;
|
||||
package io.github.ehlxr.controller.redis;
|
||||
|
||||
import io.github.ehlxr.util.RedisUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 12:18.
|
||||
* @since 2021-08-30 10:08.
|
||||
*/
|
||||
@Component
|
||||
public class Main implements ApplicationListener<ContextRefreshedEvent> {
|
||||
private static final Logger log = LoggerFactory.getLogger(Main.class);
|
||||
@Autowired
|
||||
@Qualifier("lettuceDAOImpl")
|
||||
private RedisDAO redisDAO;
|
||||
@RestController
|
||||
@Api(tags = "Redis 测试接口")
|
||||
@RequestMapping("/redis")
|
||||
public class RedisController {
|
||||
private static final Logger log = LoggerFactory.getLogger(RedisController.class);
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
|
||||
/**
|
||||
* Redis 锁测试
|
||||
*/
|
||||
@ApiOperation(value = "Redis 锁", notes = "Redis 锁测试")
|
||||
@GetMapping("/lock/test")
|
||||
public void lockTest() {
|
||||
Runnable runnable = () -> {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
log.info("{} retry lock...", Thread.currentThread().getName());
|
||||
Boolean lock = redisDAO.getDistributedLock("lock", uuid, 30_000);
|
||||
boolean lock = RedisUtil.getDistributedLock("lock", uuid, 30_000);
|
||||
if (lock) {
|
||||
log.info("{} get lock!", Thread.currentThread().getName());
|
||||
|
||||
@@ -61,7 +66,7 @@ public class Main implements ApplicationListener<ContextRefreshedEvent> {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
Boolean locak = redisDAO.releaseDistributedLock("lock", uuid);
|
||||
Boolean locak = RedisUtil.releaseDistributedLock("lock", uuid);
|
||||
log.info("{} release lock {}", Thread.currentThread().getName(), locak);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package io.github.ehlxr.filter;
|
||||
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import io.github.ehlxr.util.IdUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* auth filter
|
||||
*
|
||||
* @author supeng
|
||||
* @date 2020/08/31
|
||||
*/
|
||||
@Order(value = 1)
|
||||
@WebFilter(filterName = "customFilter", urlPatterns = {"/api/*"})
|
||||
public class CustomFilter implements Filter {
|
||||
private static final Logger log = LoggerFactory.getLogger(CustomFilter.class);
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
log.info("customFilter init");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
MDC.put(Constant.LOG_TRACE_ID, String.valueOf(IdUtil.localId()));
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
MDC.remove(Constant.LOG_TRACE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
log.info("customFilter destroy");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package io.github.ehlxr.handler;
|
||||
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import io.github.ehlxr.common.Result;
|
||||
import io.github.ehlxr.enums.CodeEnum;
|
||||
import io.github.ehlxr.exception.ServiceDataException;
|
||||
import org.assertj.core.util.Strings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2020/4/20.
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseBody
|
||||
public Result<?> defaultExceptionHandler(HttpServletRequest request, Exception e) {
|
||||
log.error("request: {}, exception: ", request.getRequestURI(), e);
|
||||
|
||||
// SendAlarmUtil.send(String.format("未知异常 request: %s, exception: %s", request.getRequestURI(), ExceptionUtils.getStackTrace(e)),
|
||||
// (t, u) -> log.info("send exception message to dingtalk result {} ", t, u));
|
||||
|
||||
String msg = CodeEnum.UNKNOWN_EXCEPTION.getMessage();
|
||||
String traceId = MDC.get(Constant.LOG_TRACE_ID);
|
||||
if (!Strings.isNullOrEmpty(traceId)) {
|
||||
msg = String.format("%s(%s)", msg, traceId);
|
||||
}
|
||||
|
||||
return Result.of(CodeEnum.UNKNOWN_EXCEPTION.getCode(), null, msg);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ServiceDataException.class)
|
||||
@ResponseBody
|
||||
public Result<?> serviceDataExceptionHandler(HttpServletRequest request, ServiceDataException e) {
|
||||
log.error("request: {} service exception: ", request.getRequestURI(), e);
|
||||
|
||||
// SendAlarmUtil.send(String.format("业务异常 request: %s, service exception: %s", request.getRequestURI(), ExceptionUtils.getStackTrace(e)),
|
||||
// (t, u) -> log.info("send service exception message to dingtalk result {} ", t, u));
|
||||
|
||||
String msg = e.getMessage();
|
||||
String traceId = MDC.get(Constant.LOG_TRACE_ID);
|
||||
if (!Strings.isNullOrEmpty(traceId)) {
|
||||
msg = String.format("%s(%s)", msg, traceId);
|
||||
}
|
||||
|
||||
return Result.of(e.getCode(), null, msg);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MultipartException.class)
|
||||
public String handleError(MultipartException e, RedirectAttributes redirectAttributes) {
|
||||
redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
|
||||
return "redirect:/uploadStatus";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrv@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.interceptor;
|
||||
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import io.github.ehlxr.util.IdUtil;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 日志 traceid Interceptor
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2020-12-23 11:23.
|
||||
*/
|
||||
public class TraceInterceptor extends HandlerInterceptorAdapter {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
MDC.put(Constant.LOG_TRACE_ID, String.valueOf(IdUtil.localId()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
MDC.remove(Constant.LOG_TRACE_ID);
|
||||
}
|
||||
}
|
||||
17
budd-server/src/main/resources/application-dev.yml
Normal file
17
budd-server/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
server:
|
||||
port: 8081
|
||||
|
||||
springfox:
|
||||
documentation:
|
||||
enabled: true
|
||||
swagger:
|
||||
base-package: io.github.ehlxr
|
||||
base-path: /**
|
||||
contact:
|
||||
email: xrv@live.com
|
||||
name: rtg
|
||||
url: https://ehlxr.me
|
||||
description: swagger of budd server
|
||||
exclude-path: /error, /ops/**
|
||||
title: budd swagger
|
||||
version: 0.0.1-SNAPSHOT
|
||||
@@ -4,11 +4,6 @@ spring:
|
||||
application:
|
||||
name: budd
|
||||
|
||||
logging:
|
||||
file:
|
||||
path: /datalog/weblog/${spring.application.name}
|
||||
config: classpath:logback-spring.xml
|
||||
|
||||
server:
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
@@ -17,4 +12,7 @@ server:
|
||||
servlet:
|
||||
context-path: /budd
|
||||
session:
|
||||
timeout: 60
|
||||
timeout: 60
|
||||
logging:
|
||||
file:
|
||||
path: /Users/ehlxr/logs/${spring.application.name}
|
||||
@@ -150,71 +150,71 @@
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
<!--
|
||||
<appender name="ALIYUN_LOG_INFO" class="com.aliyun.openservices.log.logback.LoghubAppender">
|
||||
<endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>
|
||||
<accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>
|
||||
<accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>
|
||||
<project>${ALIYUN_LOG_PROJECT}</project>
|
||||
<logStore>${ALIYUN_LOG_LOGSTORE_INFO}</logStore>
|
||||
|
||||
<!--<appender name="ALIYUN_LOG_INFO" class="com.aliyun.openservices.log.logback.LoghubAppender">-->
|
||||
<!-- <endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>-->
|
||||
<!-- <accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>-->
|
||||
<!-- <accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>-->
|
||||
<!-- <project>${ALIYUN_LOG_PROJECT}</project>-->
|
||||
<!-- <logStore>${ALIYUN_LOG_LOGSTORE_INFO}</logStore>-->
|
||||
<totalSizeInBytes>104857600</totalSizeInBytes>
|
||||
<maxBlockMs>0</maxBlockMs>
|
||||
<ioThreadCount>8</ioThreadCount>
|
||||
<batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
|
||||
<batchCountThreshold>4096</batchCountThreshold>
|
||||
<lingerMs>2000</lingerMs>
|
||||
<retries>10</retries>
|
||||
<baseRetryBackoffMs>100</baseRetryBackoffMs>
|
||||
<maxRetryBackoffMs>50000</maxRetryBackoffMs>
|
||||
|
||||
<!-- <totalSizeInBytes>104857600</totalSizeInBytes>-->
|
||||
<!-- <maxBlockMs>0</maxBlockMs>-->
|
||||
<!-- <ioThreadCount>8</ioThreadCount>-->
|
||||
<!-- <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>-->
|
||||
<!-- <batchCountThreshold>4096</batchCountThreshold>-->
|
||||
<!-- <lingerMs>2000</lingerMs>-->
|
||||
<!-- <retries>10</retries>-->
|
||||
<!-- <baseRetryBackoffMs>100</baseRetryBackoffMs>-->
|
||||
<!-- <maxRetryBackoffMs>50000</maxRetryBackoffMs>-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
|
||||
<!-- <encoder>-->
|
||||
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>-->
|
||||
<!-- <charset>UTF-8</charset>-->
|
||||
<!-- </encoder>-->
|
||||
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
|
||||
<timeZone>Asia/Shanghai</timeZone>
|
||||
|
||||
<!-- <timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>-->
|
||||
<!-- <timeZone>Asia/Shanghai</timeZone>-->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
|
||||
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
|
||||
<!-- <level>INFO</level>-->
|
||||
<!-- </filter>-->
|
||||
<mdcFields>logTraceId</mdcFields>
|
||||
</appender>
|
||||
|
||||
<!-- <mdcFields>logTraceId</mdcFields>-->
|
||||
<!--</appender>-->
|
||||
<appender name="ALIYUN_LOG_ERROR" class="com.aliyun.openservices.log.logback.LoghubAppender">
|
||||
<endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>
|
||||
<accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>
|
||||
<accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>
|
||||
<project>${ALIYUN_LOG_PROJECT}</project>
|
||||
<logStore>${ALIYUN_LOG_LOGSTORE_ERROR}</logStore>
|
||||
|
||||
<!--<appender name="ALIYUN_LOG_ERROR" class="com.aliyun.openservices.log.logback.LoghubAppender">-->
|
||||
<!-- <endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>-->
|
||||
<!-- <accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>-->
|
||||
<!-- <accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>-->
|
||||
<!-- <project>${ALIYUN_LOG_PROJECT}</project>-->
|
||||
<!-- <logStore>${ALIYUN_LOG_LOGSTORE_ERROR}</logStore>-->
|
||||
<totalSizeInBytes>104857600</totalSizeInBytes>
|
||||
<maxBlockMs>0</maxBlockMs>
|
||||
<ioThreadCount>8</ioThreadCount>
|
||||
<batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
|
||||
<batchCountThreshold>4096</batchCountThreshold>
|
||||
<lingerMs>2000</lingerMs>
|
||||
<retries>10</retries>
|
||||
<baseRetryBackoffMs>100</baseRetryBackoffMs>
|
||||
<maxRetryBackoffMs>50000</maxRetryBackoffMs>
|
||||
|
||||
<!-- <totalSizeInBytes>104857600</totalSizeInBytes>-->
|
||||
<!-- <maxBlockMs>0</maxBlockMs>-->
|
||||
<!-- <ioThreadCount>8</ioThreadCount>-->
|
||||
<!-- <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>-->
|
||||
<!-- <batchCountThreshold>4096</batchCountThreshold>-->
|
||||
<!-- <lingerMs>2000</lingerMs>-->
|
||||
<!-- <retries>10</retries>-->
|
||||
<!-- <baseRetryBackoffMs>100</baseRetryBackoffMs>-->
|
||||
<!-- <maxRetryBackoffMs>50000</maxRetryBackoffMs>-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
|
||||
<!-- <encoder>-->
|
||||
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>-->
|
||||
<!-- <charset>UTF-8</charset>-->
|
||||
<!-- </encoder>-->
|
||||
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
|
||||
<timeZone>Asia/Shanghai</timeZone>
|
||||
|
||||
<!-- <timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>-->
|
||||
<!-- <timeZone>Asia/Shanghai</timeZone>-->
|
||||
|
||||
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
|
||||
<!-- <level>ERROR</level>-->
|
||||
<!-- </filter>-->
|
||||
|
||||
<!-- <mdcFields>logTraceId</mdcFields>-->
|
||||
<!--</appender>-->
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>ERROR</level>
|
||||
</filter>
|
||||
|
||||
<mdcFields>logTraceId</mdcFields>
|
||||
</appender>
|
||||
-->
|
||||
<!--
|
||||
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
|
||||
以及指定<appender>。<logger>仅有一个name属性,
|
||||
@@ -243,18 +243,6 @@
|
||||
<springProfile name="dev">
|
||||
<logger name="io.github.ehlxr" level="debug"/>
|
||||
</springProfile>
|
||||
<!--<springProfile name="test">-->
|
||||
<!-- <logger name="io.github.ehlxr" level="info"/>-->
|
||||
<!--</springProfile>-->
|
||||
<!--<springProfile name="pre">-->
|
||||
<!-- <logger name="io.github.ehlxr" level="info"/>-->
|
||||
<!--</springProfile>-->
|
||||
<!--<springProfile name="stress">-->
|
||||
<!-- <logger name="io.github.ehlxr" level="info"/>-->
|
||||
<!--</springProfile>-->
|
||||
<!--<springProfile name="prod">-->
|
||||
<!-- <logger name="io.github.ehlxr" level="info"/>-->
|
||||
<!--</springProfile>-->
|
||||
<!--<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="warn"/>-->
|
||||
|
||||
<!-- 可用来获取 StatusManager 中的状态 -->
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.tzld.activity;
|
||||
|
||||
import io.github.ehlxr.semaphore.RedisSemaphore;
|
||||
import io.github.ehlxr.semaphore.SemaphoreInfo;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest()
|
||||
class ServerApplicationTests {
|
||||
|
||||
ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 0, TimeUnit.MINUTES,
|
||||
new LinkedBlockingQueue<>(),
|
||||
Executors.defaultThreadFactory(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@Test
|
||||
public void testNonFair() throws InterruptedException {
|
||||
SemaphoreInfo semaphoreInfo = new SemaphoreInfo("NonFair", 5, 10);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
String id = String.valueOf(i);
|
||||
RedisSemaphore semaphore = new RedisSemaphore(semaphoreInfo, redisTemplate, id);
|
||||
CompletableFuture.supplyAsync(semaphore::tryAcquire, pool).thenAcceptAsync((r) -> {
|
||||
if (r) System.out.println(id + "成功获取到信号量 (NonFair)~ ⭐⭐⭐");
|
||||
else System.out.println(id + "没有获取到信号量 (NonFair)");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
semaphore.release();
|
||||
}, pool);
|
||||
}
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFair() throws ExecutionException, InterruptedException {
|
||||
SemaphoreInfo semaphoreInfo = new SemaphoreInfo("Fair", 5, 10, true);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
String id = String.valueOf(i);
|
||||
RedisSemaphore semaphore = new RedisSemaphore(semaphoreInfo, redisTemplate, id);
|
||||
CompletableFuture.supplyAsync(semaphore::tryAcquire, pool).thenAcceptAsync((r) -> {
|
||||
if (r) System.out.println(id + "成功获取到信号量 (Fair)~~ ⭐⭐⭐");
|
||||
else System.out.println(id + "没有获取到信号量 (Fair)");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
semaphore.release();
|
||||
}, pool);
|
||||
}
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
}
|
||||
489
pom.xml
489
pom.xml
@@ -1,25 +1,17 @@
|
||||
<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 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>budd-common</module>
|
||||
<module>budd-demo</module>
|
||||
<module>budd-server</module>
|
||||
</modules>
|
||||
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<!--<build>-->
|
||||
<!-- <plugins>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <source>11</source>-->
|
||||
<!-- <target>11</target>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- </plugins>-->
|
||||
<!--</build>-->
|
||||
|
||||
<name>budd</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<name>budd-parent</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -28,18 +20,11 @@
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
|
||||
<spring.version>5.2.6.RELEASE</spring.version>
|
||||
<servlet.version>2.5</servlet.version>
|
||||
<mybatis.version>3.5.6</mybatis.version>
|
||||
<mybatis.spring.version>1.1.1</mybatis.spring.version>
|
||||
<mybatis.generator.core.version>1.4.0</mybatis.generator.core.version>
|
||||
<file_encoding>utf-8</file_encoding>
|
||||
<jdk.verion>1.8</jdk.verion>
|
||||
<powermock.version>1.7.1</powermock.version>
|
||||
<kotlin.version>1.3.61</kotlin.version>
|
||||
|
||||
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
|
||||
<guava.version>30.0-jre</guava.version>
|
||||
<spring4all.swagger.version>2.0.0.RELEASE</spring4all.swagger.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -49,430 +34,32 @@
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Google Guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.spring4all</groupId>
|
||||
<artifactId>swagger-spring-boot-starter</artifactId>
|
||||
<version>${spring4all.swagger.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd-demo</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.53</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk16</artifactId>
|
||||
<version>1.46</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<!-- <scope>test</scope> -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.1.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- spring begin-->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-oxm</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jms</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<!-- spring end-->
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sf.json-lib</groupId>
|
||||
<artifactId>json-lib</artifactId>
|
||||
<version>2.4</version>
|
||||
<classifier>jdk15</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.caucho</groupId>
|
||||
<artifactId>hessian</artifactId>
|
||||
<version>4.0.38</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.16</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Servlet -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis start -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>${mybatis.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
<version>${mybatis.spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis.generator</groupId>
|
||||
<artifactId>mybatis-generator-core</artifactId>
|
||||
<version>${mybatis.generator.core.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>c3p0</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
<version>0.9.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis end -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-frontend-jaxws</artifactId>
|
||||
<version>3.1.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-transports-http</artifactId>
|
||||
<version>3.1.6</version>
|
||||
</dependency>
|
||||
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>org.apache.activemq</groupId>-->
|
||||
<!-- <artifactId>activemq-all</artifactId>-->
|
||||
<!-- <version>5.13.3</version>-->
|
||||
<!--</dependency>-->
|
||||
<!-- activemq依赖包 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-broker</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-pool</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-spring</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>javax.jms-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.xbean</groupId>
|
||||
<artifactId>xbean-spring</artifactId>
|
||||
<version>4.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>${powermock.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito2</artifactId>
|
||||
<version>${powermock.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.reactivex</groupId>
|
||||
<artifactId>rxjava</artifactId>
|
||||
<version>1.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.reactivex.rxjava2</groupId>
|
||||
<artifactId>rxjava</artifactId>
|
||||
<version>2.1.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>29.0-jre</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jodd</groupId>
|
||||
<artifactId>jodd-props</artifactId>
|
||||
<version>3.6.1</version>
|
||||
</dependency>
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>cn.ceres.did</groupId>-->
|
||||
<!-- <artifactId>did-sdk</artifactId>-->
|
||||
<!-- <version>1.0-SNAPSHOT</version>-->
|
||||
<!--</dependency>-->
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>cn.enncloud.ceres</groupId>-->
|
||||
<!-- <artifactId>ceres</artifactId>-->
|
||||
<!-- <version>1.1.0-SNAPSHOT</version>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.rabbitmq</groupId>
|
||||
<artifactId>amqp-client</artifactId>
|
||||
<version>4.8.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hbase</groupId>
|
||||
<artifactId>hbase-client</artifactId>
|
||||
<version>1.3.5</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>log4j</artifactId>
|
||||
<groupId>log4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>2.10.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.10.5.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>3.14.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.vavr</groupId>
|
||||
<artifactId>vavr</artifactId>
|
||||
<version>0.10.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>pl.touk</groupId>
|
||||
<artifactId>throwing-function</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>did-sdk</artifactId>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>github</id>
|
||||
<url>https://git.ehlxr.me/ehlxr/maven-repository/raw/branch/main</url>
|
||||
<!--<url>https://raw.githubusercontent.com/ehlxr/maven-repository/main</url>-->
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<!--<repositories>-->
|
||||
<!-- <repository>-->
|
||||
<!-- <!–-->
|
||||
<!-- 需要在 setting.xml 中配置认证信息-->
|
||||
<!-- <servers>-->
|
||||
<!-- <server>-->
|
||||
<!-- <id>github</id>-->
|
||||
<!-- <username>ehlxr</username>-->
|
||||
<!-- <password>${env.GITHUB_MVN_TOKEN}</password>-->
|
||||
<!-- </server>-->
|
||||
<!-- </servers>-->
|
||||
<!-- –>-->
|
||||
<!-- <id>github</id>-->
|
||||
<!-- <url>https://maven.pkg.github.com/ehlxr/mvn-repository</url>-->
|
||||
<!-- <releases>-->
|
||||
<!-- <enabled>true</enabled>-->
|
||||
<!-- </releases>-->
|
||||
<!-- <snapshots>-->
|
||||
<!-- <enabled>true</enabled>-->
|
||||
<!-- </snapshots>-->
|
||||
<!-- </repository>-->
|
||||
<!--</repositories>-->
|
||||
|
||||
<build>
|
||||
<!--单元测试时引用src/main/resources下的资源文件-->
|
||||
<testResources>
|
||||
<testResource>
|
||||
<directory>src/test/resources</directory>
|
||||
</testResource>
|
||||
<testResource>
|
||||
<directory>src/main/resources</directory>
|
||||
</testResource>
|
||||
</testResources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2017/8/3.
|
||||
*/
|
||||
public class CharToHex {
|
||||
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String hex = bytesToHex("彤".getBytes());
|
||||
System.out.println(hex);
|
||||
|
||||
System.out.println(toUnicode("彤"));
|
||||
|
||||
// 十六进制 -> 十进制
|
||||
int i = Integer.parseInt(hex, 16);
|
||||
System.out.println(i);
|
||||
|
||||
// 十进制 -> 二进制
|
||||
String bin = Integer.toBinaryString(i);
|
||||
System.out.println(bin);
|
||||
|
||||
// 十进制 -> 十六进制
|
||||
String hex1 = Integer.toHexString(i);
|
||||
System.out.println(hex1);
|
||||
|
||||
// 十进制 -> 八进制
|
||||
String oct = Integer.toOctalString(i);
|
||||
System.out.println(oct);
|
||||
|
||||
System.out.println("---------------");
|
||||
System.out.println(Integer.toBinaryString(-22));
|
||||
//测试 int 转 byte
|
||||
int int0 = 234;
|
||||
byte byte0 = intToByte(int0);
|
||||
System.out.println("byte0= " + byte0);//byte0=-22
|
||||
//测试 byte 转 int
|
||||
int int1 = byteToInt(byte0);
|
||||
System.out.println("int1= " + int1);//int1=234
|
||||
}
|
||||
|
||||
|
||||
//byte 与 int 的相互转换
|
||||
public static byte intToByte(int x) {
|
||||
return (byte) x;
|
||||
}
|
||||
|
||||
public static int byteToInt(byte b) {
|
||||
//Java 总是把 byte 当做有符处理;我们可以通过将其和 0xFF 进行二进制与得到它的无符值
|
||||
return b & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 字符对应编码的哈希值
|
||||
*
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
char[] hexChars = new char[bytes.length * 2];
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
int v = bytes[j] & 0xFF;
|
||||
hexChars[j * 2] = hexArray[v >>> 4];
|
||||
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
||||
}
|
||||
return new String(hexChars);
|
||||
}
|
||||
|
||||
public static String toUnicode(String s) {
|
||||
String[] as = new String[s.length()];
|
||||
StringBuilder s1 = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
as[i] = Integer.toHexString(s.charAt(i) & 0xffff);
|
||||
s1.append("\\u").append(as[i]);
|
||||
}
|
||||
return s1.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2017/11/17.
|
||||
* <p>
|
||||
* 递归扫描 Java 文件,添加 CopyRight 信息,已有跳过
|
||||
*/
|
||||
public class ContentReplace {
|
||||
private static int total = 0;
|
||||
private static int unDeal = 0;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
File dir = new File("/Users/ehlxr/WorkSpaces/Budd");
|
||||
deal(dir);
|
||||
System.out.println("总文件数:" + total);
|
||||
System.out.println("未处理文件数:" + unDeal);
|
||||
}
|
||||
|
||||
private static void deal(File file) throws IOException {
|
||||
if (file.isDirectory()) {
|
||||
File[] fs = file.listFiles(((dir, name) -> {
|
||||
File f = new File(dir.getPath() + File.separator + name);
|
||||
|
||||
return (f.getPath().contains("src") && name.endsWith(".java")) || f.isDirectory();
|
||||
}));
|
||||
|
||||
for (File f : fs != null ? fs : new File[0]) {
|
||||
deal(f);
|
||||
}
|
||||
} else {
|
||||
++total;
|
||||
// System.out.println(file.getPath());
|
||||
|
||||
File tmp = File.createTempFile("tmp", null);
|
||||
try (
|
||||
FileOutputStream tmpOut = new FileOutputStream(tmp);
|
||||
FileInputStream tmpIn = new FileInputStream(tmp);
|
||||
RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
|
||||
byte[] buf = new byte[64];
|
||||
int hasRead;
|
||||
while ((hasRead = raf.read(buf)) > 0) {
|
||||
if (new String(buf).contains("Copyright")) {
|
||||
++unDeal;
|
||||
System.out.println("未处理文件:" + file.getPath());
|
||||
return;
|
||||
}
|
||||
// 把原有内容读入临时文件
|
||||
tmpOut.write(buf, 0, hasRead);
|
||||
}
|
||||
raf.seek(0L);
|
||||
String tmpl = "/*\n" +
|
||||
" * The MIT License (MIT)\n" +
|
||||
" *\n" +
|
||||
" * Copyright © 2020 xrv <xrg@live.com>\n" +
|
||||
" *\n" +
|
||||
" * Permission is hereby granted, free of charge, to any person obtaining a copy\n" +
|
||||
" * of this software and associated documentation files (the \"Software\"), to deal\n" +
|
||||
" * in the Software without restriction, including without limitation the rights\n" +
|
||||
" * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" +
|
||||
" * copies of the Software, and to permit persons to whom the Software is\n" +
|
||||
" * furnished to do so, subject to the following conditions:\n" +
|
||||
" *\n" +
|
||||
" * The above copyright notice and this permission notice shall be included in\n" +
|
||||
" * all copies or substantial portions of the Software.\n" +
|
||||
" *\n" +
|
||||
" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" +
|
||||
" * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" +
|
||||
" * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" +
|
||||
" * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" +
|
||||
" * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" +
|
||||
" * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n" +
|
||||
" * THE SOFTWARE.\n" +
|
||||
" */\n\n";
|
||||
raf.write(tmpl.getBytes());
|
||||
// raf.write("/*\n".getBytes());
|
||||
// raf.write(Files.readAllBytes(Paths.get(System.getProperty("user.dir") + File.separator + "LICENSE")));
|
||||
// raf.write("\n*/\n\n".getBytes());
|
||||
|
||||
// 追加临时文件内容
|
||||
while ((hasRead = tmpIn.read(buf)) > 0) {
|
||||
raf.write(buf, 0, hasRead);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public class ContentReplace2 {
|
||||
public static void main(String[] args) {
|
||||
File file = new File("/Users/ehlxr/ehlxr/blog/hugoBlog/content/post");
|
||||
File[] files = file.listFiles();
|
||||
|
||||
for (File f : files) {
|
||||
operationFile(f);
|
||||
}
|
||||
}
|
||||
|
||||
private static void operationFile(File file) {
|
||||
File tmpfile = new File(file.getParentFile().getAbsolutePath() + "\\" + file.getName() + ".tmp");
|
||||
try (
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(tmpfile))) {
|
||||
|
||||
boolean flag = false;
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
|
||||
if (line.startsWith("title")) {
|
||||
System.out.println(line);
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
// line = sb.append("title: \"").append(line.substring(line.indexOf("title") + 7)).append("\"").toString();
|
||||
line = line.replaceAll("'", "");
|
||||
System.out.println(line);
|
||||
|
||||
flag = true;
|
||||
}
|
||||
writer.write(line + "\n");
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
file.delete();
|
||||
tmpfile.renameTo(new File(file.getAbsolutePath()));
|
||||
} else {
|
||||
tmpfile.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.interfaces.ECPrivateKey;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2017/8/1.
|
||||
*/
|
||||
public class DemoECDSA {
|
||||
|
||||
//摘要
|
||||
private static final String strMsg = "hold on";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
jdkECDSA();
|
||||
}
|
||||
|
||||
/**
|
||||
* ECDSA 微软的椭圆曲线算法 jdk1.7以后引入的算法
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void jdkECDSA() throws Exception {
|
||||
//1.初始化密钥
|
||||
KeyPair keyPair = initKey();
|
||||
|
||||
//2.执行签名(用私钥签名)
|
||||
ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();
|
||||
byte[] sign = privateKeySign(strMsg, ecPrivateKey);
|
||||
String signStr = Base64.encodeBase64String(sign);
|
||||
System.out.println("sign String :" + signStr);//数字签名格式转换,以便报文传输用
|
||||
|
||||
ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
|
||||
String publicKeyStr = Base64.encodeBase64String(ecPublicKey.getEncoded());
|
||||
System.out.println("publicKeyStr String :" + publicKeyStr);//提供给对端,以便于对端使用公钥验证签名
|
||||
|
||||
|
||||
//3.验证签名(公钥验证签名)
|
||||
boolean result = publicKeyVerify(Base64.decodeBase64(signStr), Base64.decodeBase64(publicKeyStr));
|
||||
System.out.println("JDK DSA verify:" + result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1.初始化密钥,采用ECDSA
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static KeyPair initKey() throws Exception {
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
|
||||
keyPairGenerator.initialize(256); //key长度设置
|
||||
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 2.执行签名(用私钥签名)
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static byte[] privateKeySign(String data, ECPrivateKey ecPrivateKey) throws Exception {
|
||||
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
||||
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
|
||||
Signature signature = Signature.getInstance("SHA1withECDSA");
|
||||
signature.initSign(privateKey);
|
||||
signature.update(strMsg.getBytes());
|
||||
byte[] sign = signature.sign();
|
||||
|
||||
return sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* 3.公钥验证签名(摘要+签名串+公钥)
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean publicKeyVerify(byte[] sign, byte[] dsaPublicKey) throws Exception {
|
||||
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
||||
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
|
||||
Signature signature = Signature.getInstance("SHA1withECDSA");
|
||||
signature.initVerify(publicKey);
|
||||
signature.update(strMsg.getBytes());
|
||||
boolean result = signature.verify(sign);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.management.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Code which writes a stack dump for all threads to a file.
|
||||
*/
|
||||
public class DumpStack {
|
||||
|
||||
// directory where the stack files are written
|
||||
private static final String STACK_DUMP_DIR = "/var/tmp";
|
||||
|
||||
// here for testing
|
||||
public static void main(String[] args) throws Exception {
|
||||
dumpStacks();
|
||||
}
|
||||
|
||||
private static void dumpStacks() throws IOException {
|
||||
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
|
||||
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
|
||||
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
|
||||
|
||||
|
||||
ThreadInfo[] threadInfos = mxBean.getThreadInfo(mxBean.getAllThreadIds(), 0);
|
||||
Map<Long, ThreadInfo> threadInfoMap = new HashMap<>();
|
||||
for (ThreadInfo threadInfo : threadInfos) {
|
||||
threadInfoMap.put(threadInfo.getThreadId(), threadInfo);
|
||||
}
|
||||
|
||||
// choose our dump-file
|
||||
File dumpFile = new File(STACK_DUMP_DIR, "stacks." + System.currentTimeMillis());
|
||||
try (Writer writer = new BufferedWriter(new FileWriter(dumpFile))) {
|
||||
dumpTraces(mxBean, threadInfoMap, writer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpTraces(ThreadMXBean mxBean, Map<Long, ThreadInfo> threadInfoMap, Writer writer)
|
||||
throws IOException {
|
||||
Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces();
|
||||
writer.write("Dump of " + stacks.size() + " thread at "
|
||||
+ new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z").format(new Date(System.currentTimeMillis())) + "\n\n");
|
||||
for (Map.Entry<Thread, StackTraceElement[]> entry : stacks.entrySet()) {
|
||||
Thread thread = entry.getKey();
|
||||
writer.write("\"" + thread.getName() + "\" prio=" + thread.getPriority() + " tid=" + thread.getId() + " "
|
||||
+ thread.getState() + " " + (thread.isDaemon() ? "deamon" : "worker") + "\n");
|
||||
ThreadInfo threadInfo = threadInfoMap.get(thread.getId());
|
||||
if (threadInfo != null) {
|
||||
writer.write(" native=" + threadInfo.isInNative() + ", suspended=" + threadInfo.isSuspended()
|
||||
+ ", block=" + threadInfo.getBlockedCount() + ", wait=" + threadInfo.getWaitedCount() + "\n");
|
||||
writer.write(" lock=" + threadInfo.getLockName() + " owned by " + threadInfo.getLockOwnerName()
|
||||
+ " (" + threadInfo.getLockOwnerId() + "), cpu="
|
||||
+ (mxBean.getThreadCpuTime(threadInfo.getThreadId()) / 1000000L) + ", user="
|
||||
+ (mxBean.getThreadUserTime(threadInfo.getThreadId()) / 1000000L) + "\n");
|
||||
}
|
||||
for (StackTraceElement element : entry.getValue()) {
|
||||
writer.write(" ");
|
||||
writer.write(element.toString());
|
||||
writer.write("\n");
|
||||
}
|
||||
writer.write("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
*/
|
||||
public class FindRequestMapping {
|
||||
private static final int total = 0;
|
||||
private static final int unDeal = 0;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
File dir = new File("/Users/ehlxr/WorkSpaces/enncloud/ceres-epns/ceres-epns-web/src/main/java/com/ceres/epns/web");
|
||||
deal(dir);
|
||||
}
|
||||
|
||||
private static void deal(File file) throws IOException {
|
||||
if (file.isDirectory()) {
|
||||
File[] fs = file.listFiles(((dir, name) -> {
|
||||
File f = new File(dir.getPath() + File.separator + name);
|
||||
|
||||
return (f.getPath().contains("src") && name.endsWith(".java")) || f.isDirectory();
|
||||
}));
|
||||
|
||||
for (File f : fs != null ? fs : new File[0]) {
|
||||
deal(f);
|
||||
}
|
||||
|
||||
} else {
|
||||
InputStreamReader read = new InputStreamReader(new FileInputStream(file));
|
||||
BufferedReader bufferedReader = new BufferedReader(read);
|
||||
String lineTxt;
|
||||
|
||||
while ((lineTxt = bufferedReader.readLine()) != null) {
|
||||
if (lineTxt.contains("@RequestMapping")) {
|
||||
System.out.println(lineTxt);
|
||||
}
|
||||
}
|
||||
bufferedReader.close();
|
||||
read.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import net.sf.json.JSONObject;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2016/11/8.
|
||||
*/
|
||||
public class MD2Json {
|
||||
public static void main(String[] args) throws IOException {
|
||||
resume();
|
||||
}
|
||||
|
||||
private static void resume() throws IOException {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("show", 1);
|
||||
String content = FileUtils.readFileToString(new File("E:\\ehlxr\\Git\\md-files\\resume.md"), "UTF-8");
|
||||
jsonObject.put("content", content);
|
||||
System.out.println(jsonObject.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/*
|
||||
* 替换文件(如果该文件含有子目录,则包括子目录所有文件)中某个字符串并写入新内容(Java代码实现).
|
||||
*
|
||||
*原理:逐行读取源文件的内容,一边读取一边同时写一个*.tmp的文件。
|
||||
*当读取的行中发现有需要被替换和改写的目标内容‘行’时候,用新的内容‘行’替换之。
|
||||
*最终,删掉源文件,把*.tmp的文件重命名为源文件名字。
|
||||
*
|
||||
*注意!代码功能是逐行读取一个字符串,然后检测该字符串‘行’中是否含有替换的内容,有则用新的字符串‘行’替换源文件中该处整个字符串‘行’。没有则继续读。
|
||||
*注意!替换是基于‘行’,逐行逐行的替换!
|
||||
*
|
||||
* */
|
||||
public class Modify {
|
||||
|
||||
private final String target;
|
||||
private final String newContent;
|
||||
private final String path;
|
||||
|
||||
public Modify(String path, String target, String newContent) {
|
||||
// 操作目录。从该目录开始。该文件目录下及其所有子目录的文件都将被替换。
|
||||
this.path = path;
|
||||
// target:需要被替换、改写的内容。
|
||||
this.target = target;
|
||||
// newContent:需要新写入的内容。
|
||||
this.newContent = newContent;
|
||||
|
||||
operation();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
//代码测试:假设有一个test文件夹,test文件夹下含有若干文件或者若干子目录,子目录下可能也含有若干文件或者若干子目录(意味着可以递归操作)。
|
||||
//把test目录下以及所有子目录下(如果有)中文件含有"hi"的字符串行替换成新的"hello,world!"字符串行。
|
||||
new Modify("/Users/ehlxr/WorkSpaces/budd/src/main/java/me/ehlxr/test.txt", "hi", "hello,world!");
|
||||
}
|
||||
|
||||
private void operation() {
|
||||
File file = new File(path);
|
||||
opeationDirectory(file);
|
||||
}
|
||||
|
||||
private void opeationDirectory(File file) {
|
||||
if (file.isFile()) {
|
||||
operationFile(file);
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
if (files != null) {
|
||||
for (File f : files) {
|
||||
opeationDirectory(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void operationFile(File file) {
|
||||
|
||||
try {
|
||||
InputStream is = new FileInputStream(file);
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(is));
|
||||
|
||||
String filename = file.getName();
|
||||
// tmpfile为缓存文件,代码运行完毕后此文件将重命名为源文件名字。
|
||||
File tmpfile = new File(file.getParentFile().getAbsolutePath() + "\\" + filename + ".tmp");
|
||||
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(tmpfile));
|
||||
|
||||
boolean flag = false;
|
||||
String str;
|
||||
while (true) {
|
||||
str = reader.readLine();
|
||||
|
||||
if (str == null)
|
||||
break;
|
||||
|
||||
if (str.contains(target)) {
|
||||
writer.write(newContent + "\n");
|
||||
|
||||
flag = true;
|
||||
} else
|
||||
writer.write(str + "\n");
|
||||
}
|
||||
|
||||
is.close();
|
||||
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
if (flag) {
|
||||
file.delete();
|
||||
tmpfile.renameTo(new File(file.getAbsolutePath()));
|
||||
} else {
|
||||
tmpfile.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2018/2/13.
|
||||
*/
|
||||
public class PrintMatrixClockWisely {
|
||||
/**
|
||||
* 题目:输入一个矩阵,按照从外向里以顺时针的顺序打印出每一个数字。
|
||||
* 思路:
|
||||
* 循环打印:
|
||||
* 1:先打印一行(第 1 行肯定会打印)
|
||||
* 2:再打印当前矩阵的最后一列
|
||||
* 3:再倒序打印当前矩阵的最后一行
|
||||
* 4:再倒序打印当前矩阵的第一列
|
||||
* 起始坐标的规律:
|
||||
* (0,0),(1,1),(2,2)...(startX,startY), 起始坐标的两个坐标值相等。
|
||||
* 并且 startX<= (rows-1)/2,startY<=(columns-1)/2
|
||||
* 当前矩阵,第 1 行 坐标 (start,columns-1-start) => (start,endX)
|
||||
* 当前矩阵,最后 1 列 坐标 (start+1,rows-1-start) => (start+1,endY)
|
||||
* 当前矩阵,最后 1 行 坐标 (start,columns-1-start+1) => (start,endX-1)
|
||||
* 当前矩阵,第 1 行 坐标 (start+1,columns-1+1) => (start+1,endY-1)
|
||||
*
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
// 初始化矩阵 arr[][]
|
||||
int[][] arr = new int[5][5];
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
for (int j = 0; j < arr[i].length; j++) {
|
||||
arr[i][j] = i * arr[i].length + j;
|
||||
System.out.print(arr[i][j] + " " + '\t');
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
System.out.println("顺时针打印矩阵:");
|
||||
// 顺时针打印矩阵 arr[][]
|
||||
printMatrixWisely(arr);
|
||||
}
|
||||
|
||||
// 循环打印
|
||||
private static void printMatrixWisely(int[][] arr) {
|
||||
if (arr == null || arr.length < 1 || arr[0].length < 1)
|
||||
return;
|
||||
int start = 0;
|
||||
int rows = arr.length;
|
||||
int columns = arr[0].length;
|
||||
while (2 * start < columns && 2 * start < rows) {
|
||||
printMatrix(arr, rows, columns, start);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
// 打印一圈
|
||||
private static void printMatrix(int[][] arr, int rows, int columns, int start) {
|
||||
int endX = columns - 1 - start; // 最后一列的列号
|
||||
int endY = rows - 1 - start; // 最后一行的行号
|
||||
// 打印该圈第一行
|
||||
for (int i = start; i <= endX; i++)
|
||||
System.out.print(arr[start][i] + " ");
|
||||
// 打印该圈最后一列 (至少是两行)
|
||||
if (start < endY)
|
||||
for (int i = start + 1; i <= endY; i++)
|
||||
System.out.print(arr[i][endX] + " ");
|
||||
// 打印该圈最后一行 (至少是两行两列)
|
||||
if ((start < endX) && (start < endY))
|
||||
for (int i = endX - 1; i >= start; i--)
|
||||
System.out.print(arr[endY][i] + " ");
|
||||
// 打印该圈的第一列 (至少是三行两列)
|
||||
if ((start < endX) && (start < endY - 1))
|
||||
for (int i = endY - 1; i >= start + 1; i--)
|
||||
System.out.print(arr[i][start] + " ");
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @date 2018/8/21
|
||||
*/
|
||||
public class ReferenceCountingGC {
|
||||
public Object instance = null;
|
||||
private static final int _1MB = 1024 * 1024;
|
||||
/**
|
||||
* 这个成员属性的唯一意义就是占点内存,以便在能在 GC 日志中看清楚是否有回收过
|
||||
*/
|
||||
private final byte[] bigSize = new byte[2 * _1MB];
|
||||
|
||||
public static void testGC() {
|
||||
ReferenceCountingGC objA = new ReferenceCountingGC();
|
||||
ReferenceCountingGC objB = new ReferenceCountingGC();
|
||||
objA.instance = objB;
|
||||
objB.instance = objA;
|
||||
|
||||
objA = null;
|
||||
objB = null;
|
||||
|
||||
// 假设在这行发生 GC,objA 和 objB 是否能被回收?
|
||||
System.gc();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
testGC();
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @date 2017/3/27
|
||||
*/
|
||||
public class Rename {
|
||||
public static void main(String[] args) {
|
||||
File dir = new File("/Users/ehlxr/ehlxr/blog/posts");
|
||||
|
||||
File[] files = dir.listFiles();
|
||||
if (null == files || files.length <= 0) {
|
||||
System.out.println("sources is null!");
|
||||
return;
|
||||
}
|
||||
int count = 0;
|
||||
for (File file : files) {
|
||||
try {
|
||||
String oName = file.getName();
|
||||
|
||||
String date = oName.substring(oName.lastIndexOf("-201") + 1, oName.indexOf(".md"));
|
||||
String title = oName.substring(0, oName.lastIndexOf("-201"));
|
||||
|
||||
String nName = date + "-" + title + ".md";
|
||||
|
||||
copyFileUsingFileStreams(file, new File("/Users/ehlxr/Desktop/post/" + nName));
|
||||
count++;
|
||||
} catch (Exception e) {
|
||||
System.out.println("exce file [ " + file.getName() + " ] error, reason: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
System.out.println("complete: " + count);
|
||||
}
|
||||
|
||||
private static void copyFileUsingFileStreams(File source, File dest)
|
||||
throws IOException {
|
||||
try (InputStream input = new FileInputStream(source); OutputStream output = new FileOutputStream(dest)) {
|
||||
byte[] buf = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = input.read(buf)) > 0) {
|
||||
output.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
public class SerializeUtil {
|
||||
/**
|
||||
* 序列化
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
public static byte[] serialize(Object object) {
|
||||
ObjectOutputStream oos = null;
|
||||
ByteArrayOutputStream baos = null;
|
||||
try {
|
||||
// 序列化
|
||||
baos = new ByteArrayOutputStream();
|
||||
oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(object);
|
||||
byte[] bytes = baos.toByteArray();
|
||||
return bytes;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化
|
||||
*
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public static Object unserialize(byte[] bytes) {
|
||||
ByteArrayInputStream bais = null;
|
||||
try {
|
||||
// 反序列化
|
||||
bais = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
||||
return ois.readObject();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.activemq;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
|
||||
import javax.jms.*;
|
||||
|
||||
/**
|
||||
* 消息的消费者(接受者)
|
||||
* Created by ehlxr on 2016-07-11
|
||||
*/
|
||||
public class JMSConsumer {
|
||||
|
||||
private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;//默认连接用户名
|
||||
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;//默认连接密码
|
||||
private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL;//默认连接地址
|
||||
|
||||
public static void main(String[] args) {
|
||||
ConnectionFactory connectionFactory;//连接工厂
|
||||
Connection connection = null;//连接
|
||||
|
||||
Session session;//会话 接受或者发送消息的线程
|
||||
Destination destination;//消息的目的地
|
||||
|
||||
MessageConsumer messageConsumer;//消息的消费者
|
||||
|
||||
//实例化连接工厂
|
||||
connectionFactory = new ActiveMQConnectionFactory(JMSConsumer.USERNAME, JMSConsumer.PASSWORD, JMSConsumer.BROKEURL);
|
||||
|
||||
try {
|
||||
//通过连接工厂获取连接
|
||||
connection = connectionFactory.createConnection();
|
||||
//启动连接
|
||||
connection.start();
|
||||
//创建session
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
//创建一个连接HelloWorld的消息队列
|
||||
destination = session.createQueue("HelloWorld");
|
||||
//创建消息消费者
|
||||
messageConsumer = session.createConsumer(destination);
|
||||
|
||||
while (true) {
|
||||
TextMessage textMessage = (TextMessage) messageConsumer.receive(100000);
|
||||
if (textMessage != null) {
|
||||
System.out.println("收到的消息:" + textMessage.getText());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.activemq;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
|
||||
import javax.jms.*;
|
||||
|
||||
/**
|
||||
* 消息的生产者(发送者)
|
||||
* Created by ehlxr on 2016-07-11.
|
||||
*/
|
||||
public class JMSProducer {
|
||||
|
||||
//默认连接用户名
|
||||
private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
|
||||
//默认连接密码
|
||||
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
|
||||
//默认连接地址
|
||||
private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL;
|
||||
//发送的消息数量
|
||||
private static final int SENDNUM = 10;
|
||||
|
||||
public static void main(String[] args) {
|
||||
//连接工厂
|
||||
ConnectionFactory connectionFactory;
|
||||
//连接
|
||||
Connection connection = null;
|
||||
//会话 接受或者发送消息的线程
|
||||
Session session;
|
||||
//消息的目的地
|
||||
Destination destination;
|
||||
//消息生产者
|
||||
MessageProducer messageProducer;
|
||||
//实例化连接工厂
|
||||
connectionFactory = new ActiveMQConnectionFactory(JMSProducer.USERNAME, JMSProducer.PASSWORD, JMSProducer.BROKEURL);
|
||||
|
||||
try {
|
||||
//通过连接工厂获取连接
|
||||
connection = connectionFactory.createConnection();
|
||||
//启动连接
|
||||
connection.start();
|
||||
//创建session
|
||||
session = connection.createSession(true, javax.jms.Session.AUTO_ACKNOWLEDGE);
|
||||
//创建一个名称为HelloWorld的消息队列
|
||||
destination = session.createQueue("HelloWorld");
|
||||
//创建消息生产者
|
||||
messageProducer = session.createProducer(destination);
|
||||
//发送消息
|
||||
sendMessage(session, messageProducer);
|
||||
|
||||
session.commit();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param session
|
||||
* @param messageProducer 消息生产者
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void sendMessage(Session session, MessageProducer messageProducer) throws Exception {
|
||||
for (int i = 0; i < JMSProducer.SENDNUM; i++) {
|
||||
//创建一条文本消息
|
||||
TextMessage message = session.createTextMessage("ActiveMQ 发送消息" + i);
|
||||
System.out.println("发送消息:Activemq 发送消息" + i);
|
||||
//通过消息生产者发出消息
|
||||
messageProducer.send(message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
public class TestPkgAnnotation {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Package pkg = Package.getPackage("osc.git.eh3.annotation");
|
||||
Annotation[] annotations = pkg.getAnnotations();
|
||||
for (Annotation annotation : annotations) {
|
||||
System.out.println(annotation);
|
||||
}
|
||||
|
||||
// ===========================友好类和包内访问常量==============
|
||||
new MyPackageMethod().myPackageMethod();
|
||||
System.out.println(MyPackageConst.PACKAGE_STRING);
|
||||
}
|
||||
}
|
||||
75
src/main/java/io/github/ehlxr/cache/Cache.java
vendored
75
src/main/java/io/github/ehlxr/cache/Cache.java
vendored
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.cache;
|
||||
|
||||
public class Cache {
|
||||
private String key;// 缓存ID
|
||||
private Object value;// 缓存数据
|
||||
private long timeOut;// 更新时间
|
||||
private boolean expired; // 是否终止
|
||||
|
||||
public Cache() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Cache(String key, Object value, long timeOut, boolean expired) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.timeOut = timeOut;
|
||||
this.expired = expired;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public long getTimeOut() {
|
||||
return timeOut;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setKey(String string) {
|
||||
key = string;
|
||||
}
|
||||
|
||||
public void setTimeOut(long l) {
|
||||
timeOut = l;
|
||||
}
|
||||
|
||||
public void setValue(Object object) {
|
||||
value = object;
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
return expired;
|
||||
}
|
||||
|
||||
public void setExpired(boolean b) {
|
||||
expired = b;
|
||||
}
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class CacheManager {
|
||||
private static final HashMap<String, Object> cacheMap = new HashMap<String, Object>();
|
||||
|
||||
// 单实例构造方法
|
||||
private CacheManager() {
|
||||
super();
|
||||
}
|
||||
|
||||
// 得到缓存。同步静态方法
|
||||
private synchronized static Cache getCache(String key) {
|
||||
return (Cache) cacheMap.get(key);
|
||||
}
|
||||
|
||||
// 判断是否存在一个缓存
|
||||
private synchronized static boolean hasCache(String key) {
|
||||
return cacheMap.containsKey(key);
|
||||
}
|
||||
|
||||
// 清除所有缓存
|
||||
public synchronized static void clearAll() {
|
||||
cacheMap.clear();
|
||||
}
|
||||
|
||||
// 清除某一类特定缓存,通过遍历HASHMAP下的所有对象,来判断它的KEY与传入的TYPE是否匹配
|
||||
public synchronized static void clearAll(String type) {
|
||||
Iterator<Entry<String, Object>> i = cacheMap.entrySet().iterator();
|
||||
String key;
|
||||
ArrayList<String> arr = new ArrayList<String>();
|
||||
try {
|
||||
while (i.hasNext()) {
|
||||
Entry<String, Object> entry = i.next();
|
||||
key = entry.getKey();
|
||||
if (key.startsWith(type)) { // 如果匹配则删除掉
|
||||
arr.add(key);
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < arr.size(); k++) {
|
||||
clearOnly(arr.get(k));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 清除指定的缓存
|
||||
public synchronized static void clearOnly(String key) {
|
||||
cacheMap.remove(key);
|
||||
}
|
||||
|
||||
// 载入缓存
|
||||
public synchronized static void putCache(String key, Cache obj) {
|
||||
cacheMap.put(key, obj);
|
||||
}
|
||||
|
||||
// 获取缓存信息
|
||||
public static Cache getCacheInfo(String key) {
|
||||
if (hasCache(key)) {
|
||||
Cache cache = getCache(key);
|
||||
if (cacheExpired(cache)) { // 调用判断是否终止方法
|
||||
cache.setExpired(true);
|
||||
}
|
||||
return cache;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 载入缓存信息
|
||||
public static void putCacheInfo(String key, Cache obj, long dt, boolean expired) {
|
||||
Cache cache = new Cache();
|
||||
cache.setKey(key);
|
||||
cache.setTimeOut(dt + System.currentTimeMillis()); // 设置多久后更新缓存
|
||||
cache.setValue(obj);
|
||||
cache.setExpired(expired); // 缓存默认载入时,终止状态为FALSE
|
||||
cacheMap.put(key, cache);
|
||||
}
|
||||
|
||||
// 重写载入缓存信息方法
|
||||
public static void putCacheInfo(String key, Cache obj, long dt) {
|
||||
Cache cache = new Cache();
|
||||
cache.setKey(key);
|
||||
cache.setTimeOut(dt + System.currentTimeMillis());
|
||||
cache.setValue(obj);
|
||||
cache.setExpired(false);
|
||||
cacheMap.put(key, cache);
|
||||
}
|
||||
|
||||
// 判断缓存是否终止
|
||||
public static boolean cacheExpired(Cache cache) {
|
||||
if (null == cache) { // 传入的缓存不存在
|
||||
return false;
|
||||
}
|
||||
long nowDt = System.currentTimeMillis(); // 系统当前的毫秒数
|
||||
long cacheDt = cache.getTimeOut(); // 缓存内的过期毫秒数
|
||||
// 过期时间小于等于零时,或者过期时间大于当前时间时,则为FALSE
|
||||
// 大于过期时间 即过期
|
||||
return cacheDt > 0 && cacheDt <= nowDt;
|
||||
}
|
||||
|
||||
// 获取缓存中的大小
|
||||
public static int getCacheSize() {
|
||||
return cacheMap.size();
|
||||
}
|
||||
|
||||
// 获取指定的类型的大小
|
||||
public static int getCacheSize(String type) {
|
||||
int k = 0;
|
||||
Iterator<Entry<String, Object>> i = cacheMap.entrySet().iterator();
|
||||
String key;
|
||||
try {
|
||||
while (i.hasNext()) {
|
||||
Entry<String, Object> entry = i.next();
|
||||
key = entry.getKey();
|
||||
if (key.indexOf(type) != -1) { // 如果匹配则删除掉
|
||||
k++;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
// 获取缓存对象中的所有键值名称
|
||||
public static ArrayList<String> getCacheAllkey() {
|
||||
ArrayList<String> a = new ArrayList<String>();
|
||||
try {
|
||||
Iterator<Entry<String, Object>> i = cacheMap.entrySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
Entry<String, Object> entry = i.next();
|
||||
a.add(entry.getKey());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// 获取缓存对象中指定类型 的键值名称
|
||||
public static ArrayList<String> getCacheListkey(String type) {
|
||||
ArrayList<String> a = new ArrayList<String>();
|
||||
String key;
|
||||
try {
|
||||
Iterator<Entry<String, Object>> i = cacheMap.entrySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
Entry<String, Object> entry = i.next();
|
||||
key = entry.getKey();
|
||||
if (key.indexOf(type) != -1) {
|
||||
a.add(key);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.cache;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public final class SimpleCache<K, V> {
|
||||
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private final int maxCapacity;
|
||||
private final Map<K, V> eden;
|
||||
private final Map<K, V> perm;
|
||||
|
||||
public SimpleCache(int maxCapacity) {
|
||||
this.maxCapacity = maxCapacity;
|
||||
this.eden = new ConcurrentHashMap<K, V>(maxCapacity);
|
||||
this.perm = new WeakHashMap<K, V>(maxCapacity);
|
||||
}
|
||||
|
||||
public V get(K k) {
|
||||
V v = this.eden.get(k);
|
||||
if (v == null) {
|
||||
lock.lock();
|
||||
try {
|
||||
v = this.perm.get(k);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
if (v != null) {
|
||||
this.eden.put(k, v);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
public void put(K k, V v) {
|
||||
if (this.eden.size() >= maxCapacity) {
|
||||
lock.lock();
|
||||
try {
|
||||
this.perm.putAll(this.eden);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
this.eden.clear();
|
||||
}
|
||||
this.eden.put(k, v);
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.cache;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SimpleCacheUtil<T> {
|
||||
private final Map<String, T> m_objects;
|
||||
private final Map<String, Long> m_expiredObjects;
|
||||
private final long m_lExpireTime;
|
||||
private final ExecutorService m_executor;
|
||||
|
||||
public SimpleCacheUtil() {
|
||||
this(500);
|
||||
}
|
||||
|
||||
public SimpleCacheUtil(final int nExpireTime) {
|
||||
m_objects = Collections.synchronizedMap(new HashMap<String, T>());
|
||||
m_expiredObjects = Collections.synchronizedMap(new HashMap<String, Long>());
|
||||
m_lExpireTime = nExpireTime;
|
||||
m_executor = Executors.newFixedThreadPool(256);
|
||||
Executors.newScheduledThreadPool(5).scheduleWithFixedDelay(RemoveExpiredObjects(), m_lExpireTime / 2, m_lExpireTime,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private final Runnable RemoveExpiredObjects() {
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
for (final String name : m_expiredObjects.keySet()) {
|
||||
if (System.currentTimeMillis() > m_expiredObjects.get(name)) {
|
||||
m_executor.execute(CreateRemoveRunnable(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final Runnable CreateRemoveRunnable(final String name) {
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
m_objects.remove(name);
|
||||
m_expiredObjects.remove(name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public long getExpireTime() {
|
||||
return m_lExpireTime;
|
||||
}
|
||||
|
||||
public void put(final String name, final T obj) {
|
||||
put(name, obj, m_lExpireTime);
|
||||
}
|
||||
|
||||
public void put(final String name, final T obj, final long expireTime) {
|
||||
m_objects.put(name, obj);
|
||||
m_expiredObjects.put(name, System.currentTimeMillis() + expireTime * 1000);
|
||||
}
|
||||
|
||||
public T get(final String name) {
|
||||
final Long expireTime = m_expiredObjects.get(name);
|
||||
if (expireTime == null)
|
||||
return null;
|
||||
if (System.currentTimeMillis() > expireTime) {
|
||||
m_executor.execute(CreateRemoveRunnable(name));
|
||||
return null;
|
||||
}
|
||||
return m_objects.get(name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R extends T> R get(final String name, final Class<R> type) {
|
||||
return (R) get(name);
|
||||
}
|
||||
}
|
||||
35
src/main/java/io/github/ehlxr/cache/Test.java
vendored
35
src/main/java/io/github/ehlxr/cache/Test.java
vendored
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.cache;
|
||||
|
||||
public class Test {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SimpleCacheUtil<Object> cache2 = new SimpleCacheUtil<>(5);
|
||||
cache2.put("123", "fdfd");
|
||||
|
||||
System.out.println(cache2.get("123"));
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class TestCache {
|
||||
public static void main(String[] args) {
|
||||
CacheManager.putCache("abc", new Cache("key", "value", 10, false));
|
||||
CacheManager.putCache("def", new Cache());
|
||||
CacheManager.putCache("ccc", new Cache());
|
||||
CacheManager.clearOnly("");
|
||||
Cache c = new Cache();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
CacheManager.putCache("" + i, c);
|
||||
}
|
||||
CacheManager.putCache("aaaaaaaa", c);
|
||||
CacheManager.putCache("abchcy;alskd", c);
|
||||
CacheManager.putCache("cccccccc", c);
|
||||
CacheManager.putCache("abcoqiwhcy", c);
|
||||
System.out.println("删除前的大小:" + CacheManager.getCacheSize());
|
||||
ArrayList<String> cacheAllkey = CacheManager.getCacheAllkey();
|
||||
for (String key : cacheAllkey) {
|
||||
System.out.println(key + ":" + CacheManager.getCacheInfo(key).getValue());
|
||||
}
|
||||
CacheManager.clearAll("aaaa");
|
||||
System.out.println("删除后的大小:" + CacheManager.getCacheSize());
|
||||
cacheAllkey = CacheManager.getCacheAllkey();
|
||||
for (String key : cacheAllkey) {
|
||||
System.out.println(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.cache;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2017/4/11.
|
||||
*/
|
||||
public class TestFutureCahe<K, V> {
|
||||
private final ConcurrentHashMap<K, Future<V>> cacheMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
final TestFutureCahe<String, String> TestGuaVA = new TestFutureCahe<String, String>();
|
||||
|
||||
Thread t1 = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
System.out.println("T1======start========");
|
||||
Object value = TestGuaVA.getCache("key", "T1");
|
||||
System.out.println("T1 value==============" + value);
|
||||
System.out.println("T1======end========");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Thread t2 = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("T2======start========");
|
||||
Object value = TestGuaVA.getCache("key", "T2");
|
||||
System.out.println("T2 value==============" + value);
|
||||
System.out.println("T2======end========");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Thread t3 = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("T3======start========");
|
||||
Object value = TestGuaVA.getCache("key", "T3");
|
||||
System.out.println("T3 value==============" + value);
|
||||
System.out.println("T3======end========");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
t1.start();
|
||||
t2.start();
|
||||
t3.start();
|
||||
|
||||
}
|
||||
|
||||
public Object getCache(K keyValue, String ThreadName) {
|
||||
Future<V> value = null;
|
||||
try {
|
||||
System.out.println("ThreadName getCache==============" + ThreadName);
|
||||
//从缓存获取数据
|
||||
value = cacheMap.get(keyValue);
|
||||
//如果没有的话,把数据放到缓存
|
||||
if (value == null) {
|
||||
value = putCache(keyValue, ThreadName);
|
||||
return value.get();
|
||||
}
|
||||
return value.get();
|
||||
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Future<V> putCache(K keyValue, final String ThreadName) {
|
||||
// //把数据放到缓存
|
||||
Future<V> value = null;
|
||||
Callable<V> callable = new Callable<V>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public V call() throws Exception {
|
||||
//可以根据业务从数据库获取等取得数据,这边就模拟已经获取数据了
|
||||
System.out.println("ThreadName 执行业务数据并返回处理结果的数据(访问数据库等)==============" + ThreadName);
|
||||
return (V) "dataValue";
|
||||
}
|
||||
};
|
||||
FutureTask<V> futureTask = new FutureTask<V>(callable);
|
||||
value = cacheMap.putIfAbsent(keyValue, futureTask);
|
||||
if (value == null) {
|
||||
value = futureTask;
|
||||
futureTask.run();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.linkedlist;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-04-04 14:19.
|
||||
*/
|
||||
public class DoubleLinkedListDemo {
|
||||
public static void main(String[] args) {
|
||||
HeroNode2 hero1 = new HeroNode2(1, "宋江", "及时雨");
|
||||
HeroNode2 hero2 = new HeroNode2(3, "卢俊义", "玉麒麟");
|
||||
HeroNode2 hero3 = new HeroNode2(5, "吴用", "智多星");
|
||||
HeroNode2 hero4 = new HeroNode2(8, "林冲", "豹子头");
|
||||
|
||||
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
|
||||
doubleLinkedList.addByOrder(hero1);
|
||||
doubleLinkedList.addByOrder(hero2);
|
||||
doubleLinkedList.addByOrder(hero3);
|
||||
doubleLinkedList.addByOrder(hero4);
|
||||
|
||||
doubleLinkedList.list();
|
||||
|
||||
doubleLinkedList.update(new HeroNode2(3, "小卢", "玉麒麟--"));
|
||||
System.out.println("修改后的结果");
|
||||
doubleLinkedList.list();
|
||||
|
||||
doubleLinkedList.del(3);
|
||||
System.out.println("删除后的结果");
|
||||
doubleLinkedList.list();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 双向链表
|
||||
*/
|
||||
class DoubleLinkedList {
|
||||
private final HeroNode2 head = new HeroNode2(0, "", "");
|
||||
|
||||
public HeroNode2 getHead() {
|
||||
return head;
|
||||
}
|
||||
|
||||
public void list() {
|
||||
HeroNode2 temp = head.next;
|
||||
while (temp != null) {
|
||||
System.out.println(temp);
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(HeroNode2 heroNode) {
|
||||
HeroNode2 temp = head;
|
||||
while (temp.next != null) {
|
||||
temp = temp.next;
|
||||
}
|
||||
temp.next = heroNode;
|
||||
heroNode.pre = temp;
|
||||
}
|
||||
|
||||
public void addByOrder(HeroNode2 heroNode) {
|
||||
HeroNode2 temp = head;
|
||||
while (true) {
|
||||
if (temp.next == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到需要插入位置的前一个节点
|
||||
if (temp.next.no > heroNode.no) {
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
|
||||
heroNode.next = temp.next;
|
||||
heroNode.pre = temp;
|
||||
|
||||
if (temp.next != null) {
|
||||
temp.next.pre = heroNode;
|
||||
}
|
||||
temp.next = heroNode;
|
||||
}
|
||||
|
||||
public void update(HeroNode2 newHeroNode) {
|
||||
HeroNode2 temp = head.next;
|
||||
if (temp == null) {
|
||||
System.out.println("链表为空!");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (temp == null) {
|
||||
System.out.printf("没找到 %d 的节点\n", newHeroNode.no);
|
||||
break;
|
||||
}
|
||||
|
||||
if (temp.no == newHeroNode.no) {
|
||||
temp.name = newHeroNode.name;
|
||||
temp.nickname = newHeroNode.nickname;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void del(int no) {
|
||||
HeroNode2 temp = head.next;
|
||||
if (temp == null) {
|
||||
System.out.println("链表为空!");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (temp == null) {
|
||||
System.out.printf("没找到要删除的 %d 节点\n", no);
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到待删除节点
|
||||
if (temp.no == no) {
|
||||
temp.pre.next = temp.next;
|
||||
if (temp.next != null) {
|
||||
temp.next.pre = temp.pre;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义HeroNode , 每个HeroNode 对象就是一个节点
|
||||
*/
|
||||
class HeroNode2 {
|
||||
public int no;
|
||||
public String name;
|
||||
public String nickname;
|
||||
public HeroNode2 next; //指向下一个节点
|
||||
public HeroNode2 pre;// 指向上一个节点
|
||||
|
||||
public HeroNode2(int no, String name, String nickname) {
|
||||
this.no = no;
|
||||
this.name = name;
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为了显示方法,我们重新 toString
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HeroNode2 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.linkedlist;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-04-09 21:14.
|
||||
*/
|
||||
public class Josephu {
|
||||
public static void main(String[] args) {
|
||||
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
|
||||
circleSingleLinkedList.addBoy(5);
|
||||
circleSingleLinkedList.show();
|
||||
|
||||
circleSingleLinkedList.countBoy(1, 2, 5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环单向链表
|
||||
*/
|
||||
class CircleSingleLinkedList {
|
||||
private Boy first = null;
|
||||
|
||||
public void addBoy(int nums) {
|
||||
if (nums < 1) {
|
||||
return;
|
||||
}
|
||||
Boy curBoy = null;
|
||||
for (int i = 1; i <= nums; i++) {
|
||||
Boy boy = new Boy(i);
|
||||
if (i == 1) {
|
||||
first = boy;
|
||||
curBoy = first;
|
||||
first.setNext(first);
|
||||
} else {
|
||||
curBoy.setNext(boy);
|
||||
boy.setNext(first);
|
||||
curBoy = boy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (first == null) {
|
||||
System.out.println("没有boy");
|
||||
return;
|
||||
}
|
||||
|
||||
Boy curBoy = first;
|
||||
while (true) {
|
||||
System.out.printf("boy no %d\n", curBoy.getNo());
|
||||
if (curBoy.getNext() == first) {
|
||||
break;
|
||||
}
|
||||
|
||||
curBoy = curBoy.getNext();
|
||||
}
|
||||
}
|
||||
|
||||
public void countBoy(int startNo, int countNum, int size) {
|
||||
if (first == null || startNo > size || startNo < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 找到最后一个节点
|
||||
Boy helper = first;
|
||||
while (true) {
|
||||
if (helper.getNext() == first) {
|
||||
break;
|
||||
}
|
||||
helper = helper.getNext();
|
||||
}
|
||||
|
||||
// 找到开始报数的位置
|
||||
for (int i = 0; i < startNo - 1; i++) {
|
||||
helper = helper.getNext();
|
||||
first = first.getNext();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (helper == first) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < countNum - 1; i++) {
|
||||
helper = helper.getNext();
|
||||
first = first.getNext();
|
||||
}
|
||||
System.out.printf("出圈的小孩 %d\n", first.getNo());
|
||||
|
||||
first = first.getNext();
|
||||
helper.setNext(first);
|
||||
}
|
||||
System.out.printf("最后出圈的小孩 %d\n", first.getNo());
|
||||
}
|
||||
}
|
||||
|
||||
class Boy {
|
||||
private int no;
|
||||
private Boy next;
|
||||
|
||||
public Boy(int no) {
|
||||
this.no = no;
|
||||
}
|
||||
|
||||
public int getNo() {
|
||||
return no;
|
||||
}
|
||||
|
||||
public void setNo(int no) {
|
||||
this.no = no;
|
||||
}
|
||||
|
||||
public Boy getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public void setNext(Boy next) {
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.linkedlist;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-04-04 14:19.
|
||||
*/
|
||||
public class SingleLinkedListDemo {
|
||||
public static void main(String[] args) {
|
||||
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
|
||||
HeroNode hero2 = new HeroNode(3, "卢俊义", "玉麒麟");
|
||||
HeroNode hero3 = new HeroNode(5, "吴用", "智多星");
|
||||
HeroNode hero4 = new HeroNode(8, "林冲", "豹子头");
|
||||
|
||||
SingleLinkedList singleLinkedList = new SingleLinkedList();
|
||||
|
||||
// 加入
|
||||
// singleLinkedList.add(hero1);
|
||||
// singleLinkedList.add(hero4);
|
||||
// singleLinkedList.add(hero2);
|
||||
// singleLinkedList.add(hero3);
|
||||
|
||||
singleLinkedList.addByOrder(hero1);
|
||||
singleLinkedList.addByOrder(hero4);
|
||||
singleLinkedList.addByOrder(hero2);
|
||||
singleLinkedList.addByOrder(hero3);
|
||||
singleLinkedList.list();
|
||||
|
||||
// 反转链表
|
||||
// reverseList(singleLinkedList.getHead());
|
||||
// System.out.println("反转之后的链表");
|
||||
// singleLinkedList.list();
|
||||
//
|
||||
// HeroNode newHeroNode = new HeroNode(3, "小吴", "智多星..");
|
||||
// singleLinkedList.update(newHeroNode);
|
||||
// System.out.println("修改后的链表");
|
||||
// singleLinkedList.list();
|
||||
//
|
||||
// singleLinkedList.del(3);
|
||||
// System.out.println("删除 no 为 3 的节点");
|
||||
// singleLinkedList.list();
|
||||
|
||||
SingleLinkedList singleLinkedList2 = new SingleLinkedList();
|
||||
singleLinkedList2.addByOrder(new HeroNode(2, "2", "2"));
|
||||
singleLinkedList2.addByOrder(new HeroNode(3, "3", "3"));
|
||||
singleLinkedList2.addByOrder(new HeroNode(8, "8", "8"));
|
||||
singleLinkedList2.addByOrder(new HeroNode(9, "9", "9"));
|
||||
singleLinkedList2.list();
|
||||
|
||||
bind2(singleLinkedList.getHead(), singleLinkedList2.getHead());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 反转链表
|
||||
*/
|
||||
public static void reverseList(HeroNode head) {
|
||||
HeroNode pre = null;
|
||||
HeroNode cur = head.next;
|
||||
while (cur != null) {
|
||||
HeroNode next = cur.next;
|
||||
|
||||
cur.next = pre;
|
||||
|
||||
pre = cur;
|
||||
|
||||
cur = next;
|
||||
}
|
||||
|
||||
head.next = pre;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并有序链表
|
||||
*/
|
||||
public static void bind2(HeroNode node1, HeroNode node2) {
|
||||
Stack<HeroNode> stack = new Stack<>();
|
||||
|
||||
HeroNode cur = node1.next;
|
||||
while (cur != null) {
|
||||
stack.push(cur);
|
||||
cur = cur.next;
|
||||
}
|
||||
|
||||
cur = node2.next;
|
||||
while (cur != null) {
|
||||
stack.push(cur);
|
||||
cur = cur.next;
|
||||
}
|
||||
|
||||
SingleLinkedList result = new SingleLinkedList();
|
||||
for (HeroNode node : stack) {
|
||||
result.addByOrder(node);
|
||||
}
|
||||
|
||||
// 打印结果
|
||||
System.out.println("合并结果");
|
||||
result.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并有序链表
|
||||
*/
|
||||
public static void bind(HeroNode node1, HeroNode node2) {
|
||||
SingleLinkedList result = new SingleLinkedList();
|
||||
|
||||
if (node1.next == null) {
|
||||
result.add(node2.next);
|
||||
return;
|
||||
}
|
||||
if (node2.next == null) {
|
||||
result.add(node1.next);
|
||||
return;
|
||||
}
|
||||
while (node1.next != null || node2.next != null) {
|
||||
HeroNode temp = null;
|
||||
if (node1.next == null) {
|
||||
result.add(node2.next);
|
||||
break;
|
||||
}
|
||||
if (node2.next == null) {
|
||||
result.add(node1.next);
|
||||
break;
|
||||
}
|
||||
|
||||
if (node1.next.no < node2.next.no) {
|
||||
temp = node1.next;
|
||||
node1.next = node1.next.next;
|
||||
} else {
|
||||
temp = node2.next;
|
||||
node2.next = node2.next.next;
|
||||
}
|
||||
|
||||
temp.next = null;
|
||||
result.add(temp);
|
||||
}
|
||||
|
||||
// 打印结果
|
||||
System.out.println("合并结果");
|
||||
result.list();
|
||||
}
|
||||
}
|
||||
|
||||
class SingleLinkedList {
|
||||
private final HeroNode head = new HeroNode(0, "", "");
|
||||
|
||||
public HeroNode getHead() {
|
||||
return head;
|
||||
}
|
||||
|
||||
public void list() {
|
||||
HeroNode temp = head.next;
|
||||
while (temp != null) {
|
||||
System.out.println(temp);
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(HeroNode heroNode) {
|
||||
HeroNode temp = head;
|
||||
while (temp.next != null) {
|
||||
temp = temp.next;
|
||||
}
|
||||
temp.next = heroNode;
|
||||
}
|
||||
|
||||
public void addByOrder(HeroNode heroNode) {
|
||||
HeroNode temp = head;
|
||||
while (true) {
|
||||
if (temp.next == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到需要插入位置的前一个节点
|
||||
if (temp.next.no > heroNode.no) {
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
|
||||
heroNode.next = temp.next;
|
||||
temp.next = heroNode;
|
||||
}
|
||||
|
||||
public void update(HeroNode newHeroNode) {
|
||||
HeroNode temp = head.next;
|
||||
if (temp == null) {
|
||||
System.out.println("链表为空!");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (temp == null) {
|
||||
System.out.printf("没找到 %d 的节点\n", newHeroNode.no);
|
||||
break;
|
||||
}
|
||||
|
||||
if (temp.no == newHeroNode.no) {
|
||||
temp.name = newHeroNode.name;
|
||||
temp.nickname = newHeroNode.nickname;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void del(int no) {
|
||||
HeroNode temp = head;
|
||||
if (temp.next == null) {
|
||||
System.out.println("链表为空!");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (temp.next == null) {
|
||||
System.out.printf("没找到要删除的 %d 节点\n", no);
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到待删除节点的前一个节点
|
||||
if (temp.next.no == no) {
|
||||
temp.next = temp.next.next;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义HeroNode , 每个HeroNode 对象就是一个节点
|
||||
*/
|
||||
class HeroNode {
|
||||
public int no;
|
||||
public String name;
|
||||
public String nickname;
|
||||
public HeroNode next; //指向下一个节点
|
||||
|
||||
// 构造器
|
||||
public HeroNode(int no, String name, String nickname) {
|
||||
this.no = no;
|
||||
this.name = name;
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为了显示方法,我们重新 toString
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.queue;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 使用数组模拟队列
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-03-30 22:26.
|
||||
*/
|
||||
public class ArrayQueueDemo {
|
||||
public static void main(String[] args) {
|
||||
//测试一把
|
||||
//创建一个队列
|
||||
ArrayQueue queue = new ArrayQueue(3);
|
||||
char key; //接收用户输入
|
||||
Scanner scanner = new Scanner(System.in);//
|
||||
boolean loop = true;
|
||||
//输出一个菜单
|
||||
while (loop) {
|
||||
System.out.println("s(show): 显示队列");
|
||||
System.out.println("e(exit): 退出程序");
|
||||
System.out.println("a(add): 添加数据到队列");
|
||||
System.out.println("g(get): 从队列取出数据");
|
||||
System.out.println("h(head): 查看队列头的数据");
|
||||
key = scanner.next().charAt(0);//接收一个字符
|
||||
switch (key) {
|
||||
case 's':
|
||||
queue.showQueue();
|
||||
break;
|
||||
case 'a':
|
||||
System.out.println("输出一个数");
|
||||
int value = scanner.nextInt();
|
||||
queue.addQueue(value);
|
||||
break;
|
||||
case 'g': //取出数据
|
||||
try {
|
||||
int res = queue.getQueue();
|
||||
System.out.printf("取出的数据是%d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case 'h': //查看队列头的数据
|
||||
try {
|
||||
int res = queue.headQueue();
|
||||
System.out.printf("队列头的数据是%d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case 'e': //退出
|
||||
scanner.close();
|
||||
loop = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("程序退出~~");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ArrayQueue {
|
||||
private final int maxSize; // 表示数组的最大容量
|
||||
private int front; // 队列头
|
||||
private int rear; // 队列尾
|
||||
private final int[] arr; // 该数据用于存放数据, 模拟队列
|
||||
|
||||
// 创建队列的构造器
|
||||
public ArrayQueue(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
this.arr = new int[maxSize];
|
||||
}
|
||||
|
||||
// 判断队列是否满
|
||||
public boolean isFull() {
|
||||
return rear == maxSize;
|
||||
}
|
||||
|
||||
// 判断队列是否为空
|
||||
public boolean isEmpty() {
|
||||
return rear == front;
|
||||
}
|
||||
|
||||
// 添加数据到队列
|
||||
public void addQueue(int n) {
|
||||
if (isFull()) {
|
||||
System.out.println("队列已满,无法添加数据!");
|
||||
return;
|
||||
}
|
||||
|
||||
arr[rear++] = n;
|
||||
}
|
||||
|
||||
// 获取队列的数据, 出队列
|
||||
public int getQueue() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("队列为空,无法获取数据!");
|
||||
}
|
||||
|
||||
return arr[front++];
|
||||
}
|
||||
|
||||
// 显示队列的所有数据
|
||||
public void showQueue() {
|
||||
if (isEmpty()) {
|
||||
System.out.println("队列为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = front; i < rear; i++) {
|
||||
System.out.printf("arr[%d]=%d\n", i, arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示队列的头数据, 注意不是取出数据
|
||||
public int headQueue() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("队列为空,无法获取数据!");
|
||||
}
|
||||
|
||||
return arr[front];
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.queue;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-03-30 22:52.
|
||||
*/
|
||||
public class CircleArrayQueueDemo {
|
||||
public static void main(String[] args) {
|
||||
//创建一个环形队列
|
||||
CircleArrayQueue queue = new CircleArrayQueue(3);
|
||||
char key; //接收用户输入
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
boolean loop = true;
|
||||
//输出一个菜单
|
||||
while (loop) {
|
||||
System.out.println("s(show): 显示队列");
|
||||
System.out.println("e(exit): 退出程序");
|
||||
System.out.println("a(add): 添加数据到队列");
|
||||
System.out.println("g(get): 从队列取出数据");
|
||||
System.out.println("h(head): 查看队列头的数据");
|
||||
key = scanner.next().charAt(0);//接收一个字符
|
||||
switch (key) {
|
||||
case 's':
|
||||
queue.showQueue();
|
||||
break;
|
||||
case 'a':
|
||||
System.out.println("输出一个数");
|
||||
int value = scanner.nextInt();
|
||||
queue.addQueue(value);
|
||||
break;
|
||||
case 'g': //取出数据
|
||||
try {
|
||||
int res = queue.getQueue();
|
||||
System.out.printf("取出的数据是%d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case 'h': //查看队列头的数据
|
||||
try {
|
||||
int res = queue.headQueue();
|
||||
System.out.printf("队列头的数据是%d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case 'e': //退出
|
||||
scanner.close();
|
||||
loop = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("程序退出~~");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class CircleArrayQueue {
|
||||
private final int maxSize; // 表示数组的最大容量
|
||||
private int front; // 队列头
|
||||
private int rear; // 队列尾
|
||||
private final int[] arr; // 该数据用于存放数据, 模拟队列
|
||||
|
||||
// 创建队列的构造器
|
||||
public CircleArrayQueue(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
this.arr = new int[maxSize];
|
||||
}
|
||||
|
||||
// 判断队列是否满
|
||||
public boolean isFull() {
|
||||
return rear - front == maxSize;
|
||||
// return (rear + 1) % maxSize == front;
|
||||
}
|
||||
|
||||
// 判断队列是否为空
|
||||
public boolean isEmpty() {
|
||||
return rear == front;
|
||||
}
|
||||
|
||||
// 添加数据到队列
|
||||
public void addQueue(int n) {
|
||||
if (isFull()) {
|
||||
System.out.println("队列已满,无法添加数据!");
|
||||
return;
|
||||
}
|
||||
|
||||
arr[(rear++) % maxSize] = n;
|
||||
}
|
||||
|
||||
// 获取队列的数据, 出队列
|
||||
public int getQueue() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("队列为空,无法获取数据!");
|
||||
}
|
||||
int tem = arr[front % maxSize];
|
||||
front++;
|
||||
return tem;
|
||||
}
|
||||
|
||||
// 显示队列的所有数据
|
||||
public void showQueue() {
|
||||
if (isEmpty()) {
|
||||
System.out.println("队列为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = front; i < rear; i++) {
|
||||
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示队列的头数据, 注意不是取出数据
|
||||
public int headQueue() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("队列为空,无法获取数据!");
|
||||
}
|
||||
|
||||
return arr[front];
|
||||
}
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.stack;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-04-15 22:18.
|
||||
*/
|
||||
public class LinkedListStackDemo {
|
||||
public static void main(String[] args) {
|
||||
LinkedListStack2 stack = new LinkedListStack2(4);
|
||||
String key;
|
||||
boolean loop = true; //控制是否退出菜单
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
|
||||
while (loop) {
|
||||
System.out.println("show: 表示显示栈");
|
||||
System.out.println("exit: 退出程序");
|
||||
System.out.println("push: 表示添加数据到栈(入栈)");
|
||||
System.out.println("pop: 表示从栈取出数据(出栈)");
|
||||
System.out.println("请输入你的选择");
|
||||
key = scanner.next();
|
||||
switch (key) {
|
||||
case "show":
|
||||
stack.list();
|
||||
break;
|
||||
case "push":
|
||||
System.out.println("请输入一个数");
|
||||
int value = scanner.nextInt();
|
||||
stack.push(value);
|
||||
break;
|
||||
case "pop":
|
||||
try {
|
||||
int res = stack.pop();
|
||||
System.out.printf("出栈的数据是 %d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case "exit":
|
||||
scanner.close();
|
||||
loop = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("程序退出~~~");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 栈顶是链表的最后一个节点
|
||||
*/
|
||||
class LinkedListStack {
|
||||
private final int maxSize;
|
||||
private int top = -1;
|
||||
private final Node head = new Node(0);
|
||||
|
||||
public LinkedListStack(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return maxSize == top + 1;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return top == -1;
|
||||
}
|
||||
|
||||
public void push(int value) {
|
||||
if (isFull()) {
|
||||
System.out.println("栈满");
|
||||
return;
|
||||
}
|
||||
Node temp = head;
|
||||
while (true) {
|
||||
if (temp.next == null) {
|
||||
temp.next = new Node(value);
|
||||
top++;
|
||||
break;
|
||||
}
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public int pop() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("栈空");
|
||||
}
|
||||
|
||||
Node temp = head;
|
||||
while (true) {
|
||||
// if (temp.next == null) {
|
||||
// throw new RuntimeException("栈空~~~");
|
||||
// }
|
||||
if (temp.next.next == null) {
|
||||
top--;
|
||||
int id = temp.next.id;
|
||||
temp.next = null;
|
||||
return id;
|
||||
}
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void list() {
|
||||
if (isEmpty()) {
|
||||
System.out.println("栈空");
|
||||
return;
|
||||
}
|
||||
|
||||
revert();
|
||||
|
||||
Node temp = head.next;
|
||||
while (temp != null) {
|
||||
System.out.println(temp);
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
|
||||
revert();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 反转单向链表
|
||||
*/
|
||||
private void revert() {
|
||||
Node pre = null;
|
||||
Node cur = head.next;
|
||||
while (cur != null) {
|
||||
Node next = cur.next;
|
||||
cur.next = pre;
|
||||
pre = cur;
|
||||
cur = next;
|
||||
}
|
||||
|
||||
head.next = pre;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 栈底是链表的最后一个节点
|
||||
*/
|
||||
class LinkedListStack2 {
|
||||
private final Node head = new Node(0);
|
||||
private final int maxSize;
|
||||
private int top = -1;
|
||||
|
||||
public LinkedListStack2(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return top == -1;
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return top == maxSize - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 入栈:插入新元素到链表第一个节点
|
||||
*/
|
||||
public void push(int id) {
|
||||
if (isFull()) {
|
||||
System.out.println("栈满");
|
||||
return;
|
||||
}
|
||||
Node newNode = new Node(id);
|
||||
|
||||
Node temp = head.next;
|
||||
head.next = newNode;
|
||||
newNode.next = temp;
|
||||
top++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出栈:取出链表第一个元素
|
||||
*/
|
||||
public int pop() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("栈空,无法取出数据");
|
||||
}
|
||||
|
||||
Node temp = head.next;
|
||||
|
||||
head.next = temp.next;
|
||||
top--;
|
||||
|
||||
return temp.id;
|
||||
}
|
||||
|
||||
public void list() {
|
||||
if (isEmpty()) {
|
||||
System.out.println("栈空,无数据");
|
||||
}
|
||||
|
||||
Node temp = head.next;
|
||||
while (temp != null) {
|
||||
System.out.println(temp);
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Node {
|
||||
public int id;
|
||||
public Node next;
|
||||
|
||||
public Node(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node{" + id + "}";
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.date;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-01-28 16:03.
|
||||
*/
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// 旧 API 转新 API
|
||||
// Date -> Instant:
|
||||
Instant ins1 = new Date().toInstant();
|
||||
System.out.println(ins1);
|
||||
|
||||
ZonedDateTime zonedDateTime = ins1.atZone(ZoneId.systemDefault());
|
||||
System.out.println(zonedDateTime);
|
||||
|
||||
LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
|
||||
System.out.println(localDateTime);
|
||||
|
||||
// Calendar -> Instant -> ZonedDateTime:
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
Instant ins2 = calendar.toInstant();
|
||||
ZonedDateTime zdt = ins2.atZone(calendar.getTimeZone().toZoneId());
|
||||
System.out.println(zdt);
|
||||
|
||||
// 新 API 转旧 API
|
||||
// ZonedDateTime -> long:
|
||||
ZonedDateTime zdt1 = ZonedDateTime.now();
|
||||
long ts = zdt1.toEpochSecond() * 1000;
|
||||
|
||||
// long -> Date:
|
||||
Date date = new Date(ts);
|
||||
|
||||
// long -> Calendar:
|
||||
Calendar calendar1 = Calendar.getInstance();
|
||||
calendar1.clear();
|
||||
calendar1.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
|
||||
calendar1.setTimeInMillis(zdt.toEpochSecond() * 1000);
|
||||
|
||||
|
||||
// 在数据库中存储时间戳时,尽量使用 long 型时间戳,它具有省空间,效率高,不依赖数据库的优点
|
||||
ts = 1574208900000L;
|
||||
System.out.println(timestampToString(ts, Locale.CHINA, "Asia/Shanghai"));
|
||||
System.out.println(timestampToString(ts, Locale.US, "America/New_York"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 不同用户以不同的偏好来显示不同的本地时间
|
||||
*/
|
||||
static String timestampToString(long epochMilli, Locale lo, String zoneId) {
|
||||
Instant ins = Instant.ofEpochMilli(epochMilli);
|
||||
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT)
|
||||
// 按照 Locale 默认习惯格式化
|
||||
.withLocale(lo);
|
||||
|
||||
return f.withLocale(lo).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2016/12/23.
|
||||
*/
|
||||
public class dfd {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// var map = Maps.newHashMap();
|
||||
// map.put("d", 1);
|
||||
// System.out.println(map);
|
||||
}
|
||||
|
||||
public void printCircle(int[][] matrix, int startX, int startY, int endX, int endY) {
|
||||
// only one column left
|
||||
if (startY == endY) {
|
||||
for (int i = startX; i <= endX; i++) {
|
||||
System.out.println(matrix[i][endY]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// only one row left
|
||||
if (startX == endX) {
|
||||
for (int i = startY; i <= endY; i++) {
|
||||
System.out.println(matrix[startX][i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i = startY; i < endY; i++) {
|
||||
System.out.println(matrix[startX][i]);
|
||||
}
|
||||
for (int i = startX; i < endX; i++) {
|
||||
System.out.println(matrix[i][endY]);
|
||||
}
|
||||
for (int i = endY; i > startY; i--) {
|
||||
System.out.println(matrix[endX][i]);
|
||||
}
|
||||
for (int i = endX; i > startX; i--) {
|
||||
System.out.println(matrix[i][startY]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void printMatrix(int[][] matrix) {
|
||||
|
||||
if (matrix == null) {
|
||||
return;
|
||||
}
|
||||
int startX = 0;
|
||||
int startY = 0;
|
||||
int endY = matrix[0].length - 1;
|
||||
int endX = matrix.length - 1;
|
||||
|
||||
while ((startX <= endX) && (startY <= endY)) {
|
||||
printCircle(matrix, startX, startY, endX, endY);
|
||||
startX++;
|
||||
startY++;
|
||||
endX--;
|
||||
endY--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.extension;
|
||||
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 加载和管理扩展(简化版 Dubbo SPI)
|
||||
*
|
||||
* @author ehlxr
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ExtensionLoader<T> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
|
||||
|
||||
private static final String EXTENSIONS_DIRECTORY = "META-INF/extensions/";
|
||||
private static final String EXTENSIONS_INTERNAL_DIRECTORY = "META-INF/extensions/internal/";
|
||||
|
||||
private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*,+\\s*");
|
||||
|
||||
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>();
|
||||
|
||||
private final Class<T> type;
|
||||
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
|
||||
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
|
||||
private final Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();
|
||||
private String defaultExtension;
|
||||
|
||||
private ExtensionLoader(Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ExtensionLoader} 的工厂方法。
|
||||
*
|
||||
* @param type 扩展点接口类型
|
||||
* @param <T> 扩展点类型
|
||||
* @return {@link ExtensionLoader} 实例
|
||||
* @throws IllegalArgumentException 参数为 <code>null</code>;
|
||||
* 或是扩展点接口上没有 {@link SPI} 注解。
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("SPI type == null");
|
||||
}
|
||||
if (!type.isInterface()) {
|
||||
throw new IllegalArgumentException("SPI type(" + type.getName() + ") is not interface!");
|
||||
}
|
||||
if (!type.isAnnotationPresent(SPI.class)) {
|
||||
throw new IllegalArgumentException("type(" + type.getName() +
|
||||
") is not a extension, because WITHOUT @SPI Annotation!");
|
||||
}
|
||||
|
||||
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
|
||||
if (loader == null) {
|
||||
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<>(type));
|
||||
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
|
||||
}
|
||||
return loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the String of Throwable, like the output of {@link Throwable#printStackTrace()}.
|
||||
*
|
||||
* @param throwable the input throwable.
|
||||
*/
|
||||
private static String throwable2String(Throwable throwable) {
|
||||
StringWriter w = new StringWriter(1024);
|
||||
try (PrintWriter p = new PrintWriter(w)) {
|
||||
throwable.printStackTrace(p);
|
||||
return w.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public T getExtension(String name) {
|
||||
if (StringUtil.isNullOrEmpty(name)) {
|
||||
throw new IllegalArgumentException("SPI name == null");
|
||||
}
|
||||
|
||||
Holder<Object> holder = cachedInstances.get(name);
|
||||
if (holder == null) {
|
||||
cachedInstances.putIfAbsent(name, new Holder<>());
|
||||
holder = cachedInstances.get(name);
|
||||
}
|
||||
|
||||
Object instance = holder.get();
|
||||
if (instance == null) {
|
||||
synchronized (cachedInstances) {
|
||||
instance = holder.get();
|
||||
if (instance == null) {
|
||||
instance = createExtension(name);
|
||||
holder.set(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (T) instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回缺省的扩展。
|
||||
*
|
||||
* @throws IllegalStateException 指定的扩展没有设置缺省扩展点
|
||||
*/
|
||||
public T getDefaultExtension() {
|
||||
loadExtensionClasses0();
|
||||
|
||||
if (null == defaultExtension || defaultExtension.length() == 0) {
|
||||
throw new IllegalStateException("No default extension on extension " + type.getName());
|
||||
}
|
||||
return getExtension(defaultExtension);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取扩展点实现的所有扩展点名。
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
public Set<String> getSupportedExtensions() {
|
||||
Map<String, Class<?>> classes = getExtensionClasses();
|
||||
return Collections.unmodifiableSet(new HashSet<>(classes.keySet()));
|
||||
}
|
||||
|
||||
public String getExtensionName(Class<?> spi) {
|
||||
getExtensionClasses();
|
||||
return cachedNames.get(spi);
|
||||
}
|
||||
|
||||
private T createExtension(String name) {
|
||||
Class<?> clazz = getExtensionClasses().get(name);
|
||||
if (clazz == null) {
|
||||
throw findExtensionClassLoadException(name);
|
||||
}
|
||||
try {
|
||||
//noinspection unchecked
|
||||
T instance = (T) EXTENSION_INSTANCES.get(clazz);
|
||||
if (instance == null) {
|
||||
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
|
||||
//noinspection unchecked
|
||||
instance = (T) EXTENSION_INSTANCES.get(clazz);
|
||||
}
|
||||
|
||||
return instance;
|
||||
} catch (Throwable t) {
|
||||
throw new IllegalStateException("SPI instance(name: " + name + ", class: " +
|
||||
type + ") could not be instantiated: " + t.getMessage(), t);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Class<?>> getExtensionClasses() {
|
||||
Map<String, Class<?>> classes = cachedClasses.get();
|
||||
if (classes == null) {
|
||||
synchronized (cachedClasses) {
|
||||
classes = cachedClasses.get();
|
||||
if (classes == null) {
|
||||
loadExtensionClasses0();
|
||||
classes = cachedClasses.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
private IllegalStateException findExtensionClassLoadException(String name) {
|
||||
for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
|
||||
if (entry.getKey().toLowerCase().contains(name.toLowerCase())) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
StringBuilder buf = new StringBuilder("No such extension " + type.getName() + " by name " + name);
|
||||
for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
|
||||
if (i == 1) {
|
||||
buf.append(", possible causes: ");
|
||||
}
|
||||
|
||||
buf.append("\r\n(");
|
||||
buf.append(i++);
|
||||
buf.append(") ");
|
||||
buf.append(entry.getKey());
|
||||
buf.append(":\r\n");
|
||||
buf.append(throwable2String(entry.getValue()));
|
||||
}
|
||||
return new IllegalStateException(buf.toString());
|
||||
}
|
||||
|
||||
private void loadExtensionClasses0() {
|
||||
final SPI annotation = type.getAnnotation(SPI.class);
|
||||
if (annotation != null) {
|
||||
String value = annotation.value();
|
||||
if ((value = value.trim()).length() > 0) {
|
||||
String[] names = NAME_SEPARATOR.split(value);
|
||||
if (names.length > 1) {
|
||||
throw new IllegalStateException("more than 1 default extension name on extension " +
|
||||
type.getName() + ": " + Arrays.toString(names));
|
||||
}
|
||||
if (names.length == 1 && names[0].trim().length() > 0) {
|
||||
defaultExtension = names[0].trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Class<?>> extensionClasses = new HashMap<>();
|
||||
loadFile(extensionClasses, EXTENSIONS_DIRECTORY);
|
||||
loadFile(extensionClasses, EXTENSIONS_INTERNAL_DIRECTORY);
|
||||
cachedClasses.set(extensionClasses);
|
||||
}
|
||||
|
||||
private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
|
||||
String fileName = dir + type.getName();
|
||||
try {
|
||||
Enumeration<URL> urls;
|
||||
ClassLoader classLoader = ExtensionLoader.class.getClassLoader();
|
||||
if (classLoader != null) {
|
||||
urls = classLoader.getResources(fileName);
|
||||
} else {
|
||||
urls = ClassLoader.getSystemResources(fileName);
|
||||
}
|
||||
|
||||
if (urls != null) {
|
||||
while (urls.hasMoreElements()) {
|
||||
URL url = urls.nextElement();
|
||||
|
||||
try (
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))
|
||||
) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
// delete comments
|
||||
final int ci = line.indexOf('#');
|
||||
if (ci >= 0) {
|
||||
line = line.substring(0, ci);
|
||||
}
|
||||
line = line.trim();
|
||||
if (line.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
String name = null;
|
||||
int i = line.indexOf('=');
|
||||
|
||||
if (i > 0) {
|
||||
name = line.substring(0, i).trim();
|
||||
line = line.substring(i + 1).trim();
|
||||
}
|
||||
|
||||
if (line.length() > 0) {
|
||||
Class<? extends T> clazz = Class.forName(line, true, classLoader).asSubclass(type);
|
||||
if (!type.isAssignableFrom(clazz)) {
|
||||
throw new IllegalStateException("Error when load extension class(interface: " +
|
||||
type.getName() + ", class line: " + clazz.getName() + "), class "
|
||||
+ clazz.getName() + "is not subtype of interface.");
|
||||
}
|
||||
|
||||
if (name == null || name.length() == 0) {
|
||||
// clazz: xxx.xxx.ZfyAPI
|
||||
// type: xxx.xxx.API
|
||||
// -> name: zfy
|
||||
if (clazz.getSimpleName().length() > type.getSimpleName().length()
|
||||
&& clazz.getSimpleName().endsWith(type.getSimpleName())) {
|
||||
name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length()
|
||||
- type.getSimpleName().length()).toLowerCase();
|
||||
} else {
|
||||
throw new IllegalStateException("No such extension name for the class "
|
||||
+ clazz.getName() + " in the config " + url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!cachedNames.containsKey(clazz)) {
|
||||
cachedNames.put(clazz, name);
|
||||
}
|
||||
|
||||
Class<?> c = extensionClasses.get(name);
|
||||
if (c == null) {
|
||||
extensionClasses.put(name, clazz);
|
||||
} else if (c != clazz) {
|
||||
throw new IllegalStateException("Duplicate extension "
|
||||
+ type.getName() + " name " + name + " on " + c.getName()
|
||||
+ " and " + clazz.getName());
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: "
|
||||
+ type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
|
||||
exceptions.put(line, e);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.error("Exception when load extension class(interface: " +
|
||||
type + ", class file: " + url + ") in " + url, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.error("Exception when load extension class(interface: " +
|
||||
type + ", description file: " + fileName + ").", t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getName() + "[" + type.getName() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds a value of type <code>T</code>.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private static final class Holder<T> {
|
||||
/**
|
||||
* The value contained in the holder.
|
||||
*/
|
||||
private volatile T value;
|
||||
|
||||
/**
|
||||
* Creates a new holder with a <code>null</code> value.
|
||||
*/
|
||||
Holder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new holder with the specified value.
|
||||
*
|
||||
* @param value The value to be stored in the holder.
|
||||
*/
|
||||
public Holder(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void set(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.forkjoin;
|
||||
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.RecursiveTask;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2020-12-30 17:59.
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
|
||||
|
||||
// Future<Integer> future = forkJoinPool.submit(new RecursiveTaskDemo(arr, 0, arr.length));
|
||||
// System.out.println("计算出来的总和="+future.get());
|
||||
|
||||
|
||||
int[] arr = IntStream.range(0, 1000).toArray();
|
||||
Integer integer = forkJoinPool.invoke(new RecursiveTaskDemo(arr, 0, arr.length));
|
||||
System.out.println("计算出来的总和=" + integer);
|
||||
|
||||
// 关闭线程池
|
||||
forkJoinPool.shutdown();
|
||||
|
||||
System.out.println(IntStream.range(0, 1000).parallel().reduce((i, j) -> i + j));
|
||||
System.out.println(IntStream.range(0, 1000).parallel().reduce(Integer::sum));
|
||||
System.out.println(IntStream.range(0, 1000).parallel().sum());
|
||||
}
|
||||
|
||||
static class RecursiveTaskDemo extends RecursiveTask<Integer> {
|
||||
/**
|
||||
* 每个"小任务"最多只打印70个数
|
||||
*/
|
||||
private static final int MAX = 100;
|
||||
private static final long serialVersionUID = -134954066152987391L;
|
||||
private final int[] arr;
|
||||
private final int start;
|
||||
private final int end;
|
||||
|
||||
public RecursiveTaskDemo(int[] arr, int start, int end) {
|
||||
this.arr = arr;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer compute() {
|
||||
int sum = 0;
|
||||
// 当end-start的值小于MAX时候,开始打印
|
||||
if ((end - start) < MAX) {
|
||||
for (int i = start; i < end; i++) {
|
||||
sum += arr[i];
|
||||
}
|
||||
return sum;
|
||||
} else {
|
||||
System.err.println("=====任务分解======");
|
||||
// 将大任务分解成两个小任务
|
||||
int middle = (start + end) / 2;
|
||||
RecursiveTaskDemo left = new RecursiveTaskDemo(arr, start, middle);
|
||||
RecursiveTaskDemo right = new RecursiveTaskDemo(arr, middle, end);
|
||||
// 并行执行两个小任务
|
||||
left.fork();
|
||||
right.fork();
|
||||
// 把两个小任务累加的结果合并起来
|
||||
return left.join() + right.join();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user