提交 2ade34fc authored 作者: 黄夏豪's avatar 黄夏豪

练习项目更新结构后第一次提交

上级
这是一个练习代码库
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>practice</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>letcode</artifactId>
<dependencies>
<!-- https://mvnrepository.com/artifact/xyz.downgoon/snowflake -->
<dependency>
<groupId>xyz.downgoon</groupId>
<artifactId>snowflake</artifactId>
<version>1.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package DesignTwitter;
import java.util.*;
/**
* 题目:355.设计推特
* 设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户
* 能够看见关注人(包括自己)的最近十条推文。你的设计需要支持以下的几个功能:
* postTweet(userId, tweetId): 创建一条新的推文
* getNewsFeed(userId): 检索最近的十条推文。每个推文都必须是由此用户关注的人或者是用户自己发出的。推文必须按照时间顺序由最近的开始排序。
* follow(followerId, followeeId): 关注一个用户
* unfollow(followerId, followeeId): 取消关注一个用户
* 示例:
* Twitter twitter = new Twitter();
* <p>
* 用户1发送了一条新推文 (用户id = 1, 推文id = 5).
* twitter.postTweet(1, 5);
* <p>
* 用户1的获取推文应当返回一个列表,其中包含一个id为5的推文.
* twitter.getNewsFeed(1);
* <p>
* 用户1关注了用户2.
* twitter.follow(1, 2);
* <p>
* 用户2发送了一个新推文 (推文id = 6).
* twitter.postTweet(2, 6);
* <p>
* 用户1的获取推文应当返回一个列表,其中包含两个推文,id分别为 -> [6, 5].
* 推文id6应当在推文id5之前,因为它是在5之后发送的.
* twitter.getNewsFeed(1);
* <p>
* 用户1取消关注了用户2.
* twitter.unfollow(1, 2);
* <p>
* 用户1的获取推文应当返回一个列表,其中包含一个id为5的推文.
* 因为用户1已经不再关注用户2.
* twitter.getNewsFeed(1);
* <p>
* 说明:你不能倾斜容器,且 n 的值至少为 2。
* 示例:
* 输入:[1,8,6,2,5,4,8,3,7]
* 输出:49
*
* @author HuangXiahao
* @version V1.0
* @class DesignTwitter
* @packageName my.test.hello
* @data 2020/4/13
**/
public class DesignTwitter {
public static void main(String[] args) {
Twitter twitter = new Twitter();
twitter.follow(1, 2);
twitter.postTweet(2, 6);
twitter.postTweet(2, 3);
twitter.postTweet(1, 5);
twitter.postTweet(2, 4);
twitter.getNewsFeed(1);
System.out.println("1");
}
static
class Twitter {
Integer currentNum = 0;
ArrayList hasTweetIds = new ArrayList();
HashMap<Integer, User> userMap = new HashMap();
/**
* Initialize your data structure here.
*/
public Twitter() {
}
/**
* Compose a new tweet.
*/
public void postTweet(int userId, int tweetId) {
if (!hasTweetIds.contains(tweetId)) {
hasTweetIds.add(tweetId);
if (userMap.containsKey(userId)) {
userMap.get(userId).addTweet(++currentNum, tweetId);
} else {
User user = new User();
user.addTweet(++currentNum, tweetId);
userMap.put(userId, user);
}
}
}
/**
* Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent.
*/
public List<Integer> getNewsFeed(int userId) {
List<Integer> resultList = new ArrayList();
if (userMap.containsKey(userId)) {
TreeMap<Integer, Integer> tweetMap = new TreeMap(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
User user = userMap.get(userId);
tweetMap.putAll(user.tweetMap);
for (int i = 0; i < user.looks.size(); i++) {
if (userMap.containsKey(user.looks.get(i))) {
tweetMap.putAll(userMap.get(user.looks.get(i)).tweetMap);
}
}
if (tweetMap.size() > 10) {
int i = 0;
for (Integer value :
tweetMap.values()) {
if (i == 10) {
break;
}
resultList.add(value);
i++;
}
} else {
resultList.addAll(tweetMap.values());
}
}
return resultList;
}
/**
* Follower follows a followee. If the operation is invalid, it should be a no-op.
*/
public void follow(int followerId, int followeeId) {
if (userMap.containsKey(followerId)) {
userMap.get(followerId).addLook(followeeId);
} else {
User user = new User();
user.addLook(followeeId);
userMap.put(followerId, user);
}
}
/**
* Follower unfollows a followee. If the operation is invalid, it should be a no-op.
*/
public void unfollow(int followerId, int followeeId) {
if (userMap.containsKey(followerId)) {
userMap.get(followerId).delLook(followeeId);
}
}
class User {
HashMap<Integer, Integer> tweetMap = new HashMap();
ArrayList<Integer> looks = new ArrayList();
private void addLook(Integer id) {
if (!looks.contains(id)) {
looks.add(id);
}
}
private void delLook(Integer id) {
if (looks.contains(id)) {
for (int i = 0; i < looks.size(); i++) {
if (looks.get(i) == id) {
looks.remove(i);
}
}
}
}
private void addTweet(Integer num, Integer id) {
tweetMap.put(num, id);
}
}
}
/**
* Your Twitter object will be instantiated and called as such:
* Twitter obj = new Twitter();
* obj.postTweet(userId,tweetId);
* List<Integer> param_2 = obj.getNewsFeed(userId);
* obj.follow(followerId,followeeId);
* obj.unfollow(followerId,followeeId);
*/
}
package MaxArea;
/**
*
* 题目:11.盛最多的水
* 给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。
* 在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中
* 的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
* 说明:你不能倾斜容器,且 n 的值至少为 2。
* 示例:
* 输入:[1,8,6,2,5,4,8,3,7]
* 输出:49
*
* @author HuangXiahao
* @version V1.0
* @class MaxArea
* @packageName my.test.hello
* @data 2020/4/5
**/
public class MaxArea {
/***
* 解题思路:通过双指针向内夹进的方式进行运算。
* 对坐标数组的头和尾建立指针left和right,设最大面积为maxArea。
* 通过循环使两枚指针向内夹进,直到两枚指针重合。
* 每一次循环时计算当前指针位置所表示的最大面积并判断是否大于maxArea,若大于则赋值给maxArea
* 计算完毕后,将所代表数较小的一方对应的指针向中间移动一位
* 循环结束后返回maxArea
* @param height 坐标数组
* @Return : int
* @Author : HuangXiahao
* @Date : 2020/4/5 18:58
*/
public static int maxArea(int[] height) {
if (height.length < 2) {
return 0;
}
int left = 0;
int right = height.length-1;
int maxArea = 0;
while (left<right){
maxArea = Math.max((right-left)*Math.min(height[left], height[right]),maxArea);
if (height[left] < height[right]) {
left++;
}else {
right--;
}
}
return maxArea;
}
}
package MaxArea;
/**
*
* 题目:11.盛最多的水
* 给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。
* 在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中
* 的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
* 说明:你不能倾斜容器,且 n 的值至少为 2。
* 示例:
* 输入:[1,8,6,2,5,4,8,3,7]
* 输出:49
*
* @author HuangXiahao
* @version V1.0
* @class MaxArea
* @packageName my.test.hello
* @data 2020/4/5
**/
public class MaxArea_2 {
/***
* 以下代码为另一种解题思路
* 解题思路:通过循环的方式进行运算。
* 设最大面积为maxArea
* 对数组进行两次循环,每一次循环对本次循环能代表的最大面积进行计算
* 每次计算后对本次计算结果与maxArea进行比较
* 若本次计算结果大于maxArea则将结果赋值给maxArea
* 嵌套循环结束后返回maxArea
*
* @param height 坐标数组
* @Return : int
* @Author : HuangXiahao
* @Date : 2020/4/5 18:58
*/
public static int maxArea(int[] height) {
if (height.length < 2) {
return 0;
}
int maxArea = 0;
for (int i = 0; i < height.length; i++) {
for (int j = i+1; j < height.length; j++) {
maxArea = Math.max((j-i)*Math.min(height[j],height[i]),maxArea);
}
}
return maxArea;
}
}
package MinimumSizeSubarraySum;
/**
* 题目:209.长度最小的子数组
* 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的
* 长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
*
* 示例:
* 输入: s = 7, nums = [2,3,1,2,4,3]
* 输出: 2
* 解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
*
* @author HuangXiahao
* @version V1.0
* @class MinimumSizeSubarraySum
* @packageName my.test.hello
* @data 2020/4/5
**/
public class MinimumSizeSubarraySum {
/**
* 解题思路:双重循环法
* 通过对数组进行嵌套循环计算出每一次大于等于目标数的数组,并记录下该次的数组长度
* 所有循环执行完后输出最小数组长度
* 优化:
* 先通过一次循环计算出一个sums数组记录了,同下标下nums数组的该下标前的相加数
* 在循环时通过 sums[j] - sums[i] + nums[i] 计算出相加数 该算法可以减少循环中计算相加数的时间
*
* @param s
* @param nums
* @Return : int
* @Author : HuangXiahao
* @Date : 2020/4/6 18:55
*/
public static int minSubArrayLen(int s, int[] nums) {
int length = nums.length;
if (length==0){
return 0;
}
int maxsize = nums.length+1;
int[] sums = new int[length];
sums[0] = nums[0];
for (int i = 1; i < length; i++) {
sums[i] = sums[i-1]+nums[i];
}
for (int i = 0; i <length ; i++) {
for (int j = i; j < length ; j++) {
int sum = sums[j] - sums[i] + nums[i];
if (sum>=s){
maxsize = Math.min(maxsize,(j-i+1));
break;
}
}
}
return maxsize!=length+1?maxsize:0;
}
}
package ThreeSum;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 题目:15.三数之和
* 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0
* 请你找出所有满足条件且不重复的三元组。
* 注意:答案中不可以包含重复的三元组。
* 示例:
* 输入:nums = [-1, 0, 1, 2, -1, -4]
* 满足要求的三元组集合为:
* [
* [-1, 0, 1],
* [-1, -1, 2]
* ]
*
* @author HuangXiahao
* @version V1.0
* @class TwoSum_t1
* @packageName my.test.hello
* @data 2020/4/5
**/
public class ThreeSum {
/**
* 解题思路:三指针算法
* 因为本题目不需要考虑数组下标,且不能出现重复的三元组
* 所以第一步对数组进行排序
* 排序后对数组进行进行一次遍历,每次遍历的index作为第一个指针
* 其余两个指针l和r 分别是 index+1 , 和 length-1
* 之后用循环使 l 和 r 两枚指针向中间移动,若 l 和 r所代表的数相加为目标数字
* 则向结果数组中添加一个结果
* 判断完毕后两边指针向内移动一位,指针移动后若移动后的数字跟移动前的数字相同则再次移动一位
*
*
* @param nums 需要计算的数组
* @Return : java.util.List<java.util.List<java.lang.Integer>>
* @Author : HuangXiahao
* @Date : 2020/4/5 21:12
*/
public static List<List<Integer>> threeSum(int[] nums) {
if (nums.length<3){
return new ArrayList();
}
Arrays.sort(nums);
ArrayList<List<Integer>> arrayList = new ArrayList();
for (int i = 0; i <nums.length ; i++) {
if (i>0&&nums[i]==nums[i-1]){
continue;
}
int l = i+1;
int r = nums.length-1;
int targe = -nums[i];
while (l<r){
if (nums[l]+nums[r]==targe){
arrayList.add(Arrays.asList(nums[l],nums[r],nums[i])) ;
r--;
l++;
while (l<nums.length&&nums[l]==nums[l-1]){
l++;
}
while (l<r&&nums[r]==nums[r+1]){
r--;
}
}else if (nums[l]+nums[r]<targe){
l++;
}else {
r --;
}
}
}
return arrayList;
}
}
package TrappingRainWater;
/**
* 题目:42. 接雨水
* 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
* 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)
* 示例:
* 输入: [0,1,0,2,1,0,1,3,2,1,2,1]
* 输出: 6
*
* @author HuangXiahao
* @version V1.0
* @class TrappingRainWater
* @packageName my.test.hello
* @data 2020/4/6
**/
public class TrappingRainWater {
/**
* 解题思路:双指针法
* 本题的主要思路是通过双指针的夹进的方式判定每个格子可接雨水的量。
* !!通过双指针在数组的两边维系一面最高的墙,通过最高的墙体可用计算每个格子能接雨水的量!!
* 指针通过不断的循环夹进,在循环开始时需要判断两面最高的墙中哪边较矮
* 较矮的一遍减去当前的格子便能得到当前格子的可接水量
* 通过将每次接水量相加得到最后的答案
* @param height 输入数组
* @Return : int
* @Author : HuangXiahao
* @Date : 2020/4/10 13:36
*/
public static int trap(int[] height) {
int left = 0;
int right = height.length-1;
int leftMax = 0;
int rightMax = 0;
int result = 0;
while (left<=right){
if (leftMax>rightMax){
result += leftMax - height[left] >0?leftMax - height[left]:0;
leftMax = Math.max(leftMax,height[left]);
left++;
}else {
result += rightMax - height[right] >0?rightMax - height[right]:0;
rightMax = Math.max(rightMax,height[right]);
right--;
}
}
return result;
}
}
package TwoSum_t1;
import java.util.HashMap;
import java.util.Map;
/**
* 题目:1.两数之和
* 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
* 说明:你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
*
* 示例:
* 输入:nums = [2, 7, 11, 15], target = 9
* 因为 nums[0] + nums[1] = 2 + 7 = 9
* 所以返回 [0, 1]
*
* @author HuangXiahao
* @version V1.0
* @class TwoSum_t1
* @packageName my.test.hello
* @data 2020/4/5
**/
public class TwoSum_t1 {
/**
* 解题思路:利用hashmap的特性完成计算
* 对数组进行遍历,每次遍历时计算机目标数字并检查哈希表中是否存在目标数字
* 若存在则得出最后的答案,若不存在则将遍历的数字和下标插入哈希表中
*
* @param nums 需要计算的数组
* @param target 目标数字
* @Return : int[]
* @Author : HuangXiahao
* @Date : 2020/4/5 20:08
*/
public static int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) ) {
return new int[] { map.get(complement),i };
}
map.put(nums[i],i);
}
throw new IllegalArgumentException("数据错误");
}
}
package TwoSum_t167;
/**
* 题目:167.两数之和
* 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
* 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
* 说明:
* 返回的下标值(index1 和 index2)不是从零开始的。
* 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
*
* 示例:
* 输入:nums = [2, 7, 11, 15], target = 9
* 输出: [1,2]
* 解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
*
* @author HuangXiahao
* @version V1.0
* @class TwoSum_t1
* @packageName my.test.hello
* @data 2020/4/5
**/
public class TwoSum_t167 {
/**
* 解题思路:利用双指针算法进行计算
* 对数组的头和尾建立指针,分别为l和r
* 通过循环使两枚指针向中间夹进,直至两枚相遇
* 每次循环时对两枚指针所代表的数字进行相加
* 当计算的值与目标数字相同时返回结果
* 若不相等时判断相加值是否大于目标值
* 若大于则右边指针向作移动否则左边指针向右移动
*
* @param nums 需要计算的数组
* @param target 目标数字
* @Return : int[]
* @Author : HuangXiahao
* @Date : 2020/4/5 20:20
*/
public static int[] twoSum(int[] nums, int target) {
int l = 0;
int r = nums.length-1;
while (l<r){
int sum = nums[l] + nums[r];
if (sum==target){
return new int[] { l,r };
}else if (sum<target){
l++;
}else {
r --;
}
}
throw new IllegalArgumentException("数据错误");
}
}
package TwoSum_t167;
import java.util.HashMap;
import java.util.Map;
/**
* 题目:167.两数之和
* 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
* 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
* 说明:
* 返回的下标值(index1 和 index2)不是从零开始的。
* 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
*
* 示例:
* 输入:nums = [2, 7, 11, 15], target = 9
* 输出: [1,2]
* 解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
*
* @author HuangXiahao
* @version V1.0
* @class TwoSum_t1
* @packageName my.test.hello
* @data 2020/4/5
**/
public class TwoSum_t167_2 {
/**
* 解题思路:利用hashmap的特性完成计算
* 对数组进行遍历,每次遍历时计算机目标数字并检查哈希表中是否存在目标数字
* 若存在则得出最后的答案,若不存在则将遍历的数字和下标插入哈希表中
*
* @param nums 需要计算的数组
* @param target 目标数字
* @Return : int[]
* @Author : HuangXiahao
* @Date : 2020/4/5 20:20
*/
public static int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) ) {
return new int[] { map.get(complement),i };
}
map.put(nums[i],i);
}
throw new IllegalArgumentException("数据错误");
}
}
package quickSort;
/**
* @author HuangXiahao
* @version V1.0
* @class QuickSort
* @packageName my.test.hello.quickSort
* @data 2020/4/17
**/
public class QuickSort {
public static void main(String[] args) {
int[] x = new int[]{2,3,6,7,8,1};
quickSort(x,0,x.length-1);
System.out.println("1");
}
public static void quickSort(int[] s,int l,int r){
if (l < r) {
int i = l, j = r, x = s[l];
while (i < j) {
while (i < j && s[j] >= x) // 从右向左找第一个小于x的数
j--;
if (i < j)
s[i++] = s[j];
while (i < j && s[i] < x) // 从左向右找第一个大于等于x的数
i++;
if (i < j)
s[j--] = s[i];
}
s[i] = x;
quickSort(s, l, i - 1); // 递归调用
quickSort(s, i + 1, r);
}
};
}
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>practice</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>letcode</module>
<module>snowFake</module>
</modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>practice</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<dependencies>
<dependency>
<groupId>xyz.downgoon</groupId>
<artifactId>snowflake</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<artifactId>snowFake</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package snowflake;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author HuangXiahao
* @version V1.0
* @class SnowFlakThread
* @packageName snowflake
* @data 2020/6/3
**/
public class SnowFlakThread extends Thread{
private SnowFlake snowFlake;
private long n;
public SnowFlakThread( SnowFlake snowFlake, long n) {
this.snowFlake = snowFlake;
this.n = n;
}
@Override
public void run() {
for (int j = 0; j < n; j++) {
snowFlake.nextId();
}
}
}
package snowflake;
import java.util.concurrent.atomic.AtomicLong;
/**
* 描述:分布式自增ID算法
* ID共64位
* @author HuangXiahao
* @version V1.0
* @class SnowFake
* @packageName my.test.hello.snowflake
* @data 2020/5/20
**/
public class SnowFlake {
/**
* 机器ID位数
* */
private long workIdLength ;
/**
* 每秒产生的序列号位数
* */
private long sequenceLength ;
/**
* 每秒产生的序列号最大值
**/
private long maxSequence = ~(-1L <<sequenceLength);
/**
* 默认给了一个机器码
* */
private final long workId = 116L;
/**
* 用于记录上一毫秒的时间戳
* */
private long lastTimestamp = 0L;
/**
* 用于记录上一个序列号
* */
private long sequence = 0L;
/**
* 时间戳左编译量
* */
private final long timestampOffset = sequenceLength + workIdLength;
/**
* 计数器
* */
private AtomicLong atomicLong = new AtomicLong(0);
public SnowFlake(long sequenceLength) {
this.sequenceLength = sequenceLength;
this.workIdLength = 22L - sequenceLength;
maxSequence = ~(-1L <<sequenceLength);
}
/***
* 描述:获取雪花算法ID
* @Retrun : long
* @Author : HuangXiahao
* @Date : 2020/5/22 15:31
*/
public synchronized long nextId(){
//获取当前时间戳
long currentTime = getNewTime();
if (lastTimestamp==currentTime){
sequence = (sequence + 1) & maxSequence;
if (sequence==0L){
//进入下一毫秒并将序列号重置
currentTime = nextTime(lastTimestamp);
}
}else {
//重置时间戳记录和序列号
sequence = 0L;
}
lastTimestamp = currentTime;
atomicLong.incrementAndGet();
//将数据移动到对应的位置上
return currentTime<<(timestampOffset)|workId<<(sequenceLength)|sequence;
}
/***
* 描述:进入下一毫秒并重置序列号和时间记录
* @Return : void
* @Author : HuangXiahao
* @Date : 2020/5/22 15:39
*/
public Long nextTime(long previouTimestamp){
long currentTime = getNewTime();
while (currentTime<=previouTimestamp){
currentTime = getNewTime();
}
return currentTime;
}
private Long getNewTime(){
return System.currentTimeMillis();
}
/**
* 测试生成N个雪花ID中是否出现错误ID
* @param n 生成个数
*/
public void testError(int n){
long last = 0L;
for (int i = 0; i <n ; i++) {
long l = nextId();
if (last!=l){
if (last>l&&last!=0){
System.out.println("非单调递增");
}
last = l;
}else {
System.out.println("重复了");
}
}
System.out.println("跑完了");
}
/**
* 测试生成N个雪花ID的QPS
* @param n 生成个数
*/
public void testQPS(int n){
long start = System.currentTimeMillis();
for (int i = 0; i < n ; i++) {
nextId();
}
long end = System.currentTimeMillis();
System.out.println("每秒QPS:"+(n/(end-start))*1000 );
System.out.println(end-start+"ms");
}
public long getAtomicLong() {
return atomicLong.get();
}
}
package snowflake;
import xyz.downgoon.snowflake.Snowflake;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author HuangXiahao
* @version V1.0
* @class TestSnowFake
* @packageName my.test.hello.snowfake
* @data 2020/5/31
**/
public class TestSnowFlake {
static class TimeAndQPS{
private double QPS;
private long time;
public TimeAndQPS(double QPS, long time) {
this.QPS = QPS;
this.time = time;
}
@Override
public String toString() {
return "每秒QPS:"+this.QPS+" 所用时间:" + this.time;
}
}
public static void main(String[] args) {
//测试个数
long n = 100_000_000;
//线程数
int threadNum = 10;
//序列号位数
int sequenceLength = 14;
//测试5次
for (int i = 0; i < 5; i++) {
System.out.println(startWithThread(n, threadNum,sequenceLength));
}
}
public static TimeAndQPS startWithThread(long num, int threadNum,long sequenceLength) {
ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
SnowFlake snowFake = new SnowFlake(sequenceLength);
long start = System.currentTimeMillis();
for (int i = 0; i < threadNum; i++) {
executorService.submit(new SnowFlakThread(snowFake, num / threadNum));
}
//暂定主线程直到num个雪花ID生成完毕
while (snowFake.getAtomicLong() != num) {
}
long end = System.currentTimeMillis();
executorService.shutdown();
return new TimeAndQPS((num / (end - start) * 1.0) * 1000.0,end-start);
}
}
package snowflake;
/**
* @author HuangXiahao
* @version V1.0
* @class test
* @packageName snowflake
* @data 2020/6/5
**/
public class test {
public static int count = 0;
public static void main(String[] args) {
int target = 300000;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < target; i++) {
count++;
System.out.println("count:"+count);
}
}
});
thread.start();
int validNumber = count;
while (validNumber!=target){
System.out.println("");
validNumber = count;
}
System.out.println("OK");
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论