一、tag 树
import com.google.common.collect.Maps;
import com.google.common.collect.Lists;
import lombok.Data;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
/**
* tag 树
*/
public class TagTools {
/**
* 根节点对象存放到这里
*/
private List<TreeDto> rootList;
/**
* 其他节点存放到这里,可以包含根节点
*/
private List<TreeDto> bodyList;
public TagTools(List<TreeDto> rootList, List<TreeDto> bodyList) {
this.rootList = rootList;
this.bodyList = bodyList;
}
/**
* 调用的方法入口
* @return
*/
public List<TreeDto> getTree(){
if(!CollectionUtils.isEmpty(bodyList)){
/**
* 声明一个map,用来过滤已操作过的数据
*/
Map<String,String> map = Maps.newHashMapWithExpectedSize(bodyList.size());
rootList.stream().forEach(beanTree -> getChild(beanTree,map));
return rootList;
}
return null;
}
public void getChild(TreeDto treeDto,Map<String,String> map){
List<TreeDto> childList = Lists.newArrayList();
bodyList.stream()
//并发编程
.parallel()
.filter(c -> !map.containsKey(c.getId()))
.filter(c ->c.getPid().equals(treeDto.getId()))
.forEach(c ->{
map.put(c.getId(),c.getPid());
getChild(c,map);
childList.add(c);
});
treeDto.setChildTreeDto(childList);
}
@Data
static class TreeDto {
private String id;
private String name;
private String pid;
private String isParent;
private List<TreeDto> childTreeDto;
public TreeDto(String id, String name, String pid, String isParent, List<TreeDto> childTreeDto) {
this.id = id;
this.name = name;
this.pid = pid;
this.isParent = isParent;
this.childTreeDto = childTreeDto;
}
}
}
二、决策树 task树
实现算法:(C4.5/ID3/CART/Decision Tree/envi)等算法
相关依赖:
<dependency>
<groupId>com.helger</groupId>
<artifactId>ph-tree</artifactId>
<version>9.4.6</version>
</dependency>
三、字典树
import java.util.HashMap;
import java.util.Map;
/**
* 字典树
*/
public class TrieTools {
private TrieNode root;
public TrieTools() {
root = new TrieNode();
root.wordEnd = false;
}
public void insert(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
Character c = new Character(word.charAt(i));
if (!node.children.containsKey(c)) {
node.children.put(c, new TrieNode());
}
node = node.children.get(c);
}
node.wordEnd = true;
}
public boolean search(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
Character c = new Character(word.charAt(i));
if (!node.children.containsKey(c)) {
return false;
}
node = node.children.get(c);
}
return true && node.wordEnd;
}
public boolean startsWith(String prefix) {
TrieNode node = root;
for (int i = 0; i < prefix.length(); i++) {
Character c = new Character(prefix.charAt(i));
if (!node.children.containsKey(c)) {
return false;
}
node = node.children.get(c);
}
return true;
}
class TrieNode {
Map<Character, TrieNode> children;
boolean wordEnd;
public TrieNode() {
children = new HashMap<>();
wordEnd = false;
}
}
}
四、BitMap全局字典
import java.util.BitSet;
/**
* BitMap全局字典
*/
public class BitMapTools {
/**
* 保存数据的
*/
private byte[] bits;
/**
* 能够存储多少数据
*/
private int capacity;
/**
* 用两个bit为来标记某个元素的个数
*/
int bNum=2;
/**
* 一个32位字节能标记多少个数
*/
int bSize=32/bNum;
/**
* 数据范围(0到2^32内的数)
* 此处是16万,便于测试
*/
int numSize = 160000;
public BitMapTools(int capacity){
this.capacity = capacity;
//1bit能存储8个数据,那么capacity数据需要多少个bit呢,capacity/8+1,右移3位相当于除以8
bits = new byte[(capacity >>3 )+1];
}
public void install(int num){
// num/8得到byte[]的index
int arrayIndex = num >> 3;
// num%8得到在byte[index]的位置
int position = num & 0x07;
//将1左移position后,那个位置自然就是1,然后和以前的数据做|,这样,那个位置就替换成1了。
bits[arrayIndex] |= 1 << position;
}
public boolean contain(int num){
// num/8得到byte[]的index
int arrayIndex = num >> 3;
// num%8得到在byte[index]的位置
int position = num & 0x07;
//将1左移position后,那个位置自然就是1,然后和以前的数据做&,判断是否为0即可
return (bits[arrayIndex] & (1 << position)) !=0;
}
public void clear(int num){
// num/8得到byte[]的index
int arrayIndex = num >> 3;
// num%8得到在byte[index]的位置
int position = num & 0x07;
//将1左移position后,那个位置自然就是1,然后对取反,再与当前值做&,即可清除当前的位置了.
bits[arrayIndex] &= ~(1 << position);
}
/**
* 定义bitmap数组大小
*/
int arraySize =(int)Math.ceil((double) numSize / bSize);
private int array[] = new int[arraySize];
/**
* 初始化BitMap
*/
public void initBitMap(){
for(int i=0;i<array.length;i++){
array[i] = 0;
}
}
/**
* 往BitMap中设置对应的数的个数
* @param x 要添加的数
* @param num 对应的个数
*/
public void set(int x,int num){
//获得bitMap的下标
//或 int m = x /bSize;
int m = x >> 4;
//获得对应的位置
int n = x % bSize;
//将x对应位置上的数值先清零,但是有要保证其他位置上的数不变
array[m] &= ~((0x3<<(2*n)));
//重新对x的个数赋值
array[m] |= ((num&3)<<(2*n));
}
/**
* 获取x在BitMap中的数量
* @param x
* @return
*/
public int get(int x){
int m = x >> 4;
int n = x % bSize;
return (array[m] & (0x3<<(2*n))) >> (2*n);
}
/**
* 往BitMap中添加数
* 如果x的个数大于三,则不在添加(2个bit为最多只能表示到3:00 01 10 11)
* @param x
*/
public void add(int x){
int num = get(x);
//只处理num小于3的
if(num<3) {
set(x, num + 1);
}
}
/**
* 数据量去重
* @param nums
*/
public void removal(int[] nums){
BitSet bitSet=new BitSet();
for (int num : nums) {
if(bitSet.get(num)){
System.out.println(num);
break;
}else {
bitSet.set(num);
}
}
}
}
五、SCF API 实现
<!-- https://mvnrepository.com/artifact/com.tencentcloudapi/scf-java-events -->
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>scf-java-events</artifactId>
<version>0.0.2</version>
</dependency>
开源地址:https://github.com/ecsoya/tencent-function-gateway
代码:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import org.ecsoya.cloud.function.scf.api.LambdaGatewayFunction;
import org.ecsoya.cloud.function.scf.api.model.Gateway;
import org.ecsoya.cloud.function.scf.api.model.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import com.qcloud.scf.runtime.Context;
import function.DemoGatewayFunction;;
@Component
public class FunctionRegistry {
private final PathMatcher pathMatcher;
private Logger logger = LoggerFactory.getLogger(FunctionRegistry.class);
private Map<String, Function<Gateway, Response>> functions;
private Map<String, Method> functionMethods;
private DemoGatewayFunction delegate = new DemoGatewayFunction();
@SuppressWarnings("unchecked")
public FunctionRegistry() {
functions = new HashMap<>();
pathMatcher = new AntPathMatcher();
try {
Method method = LambdaGatewayFunction.class.getDeclaredMethod("initialize", Context.class);
method.setAccessible(true);
method.invoke(delegate, createContext());
} catch (Exception e) {
logger.error("Could not to initialize CsfxFunction.");
}
try {
Field field = LambdaGatewayFunction.class.getDeclaredField("functions");
field.setAccessible(true);
functions = (Map<String, Function<Gateway, Response>>) field.get(delegate);
} catch (Exception e) {
logger.error("Could not to get functions from CsfxFunction.");
functions = new HashMap<>();
}
try {
Field field = LambdaGatewayFunction.class.getDeclaredField("functionMethods");
field.setAccessible(true);
functionMethods = (Map<String, Method>) field.get(delegate);
} catch (Exception e) {
logger.error("Could not to get functions from CsfxFunction.");
functionMethods = new HashMap<>();
}
}
public String validateFunction(String name, Gateway gateway) {
try {
Method method = LambdaGatewayFunction.class.getDeclaredMethod("validateFunction", String.class,
Gateway.class);
method.setAccessible(true);
return (String) method.invoke(delegate, name, gateway);
} catch (Exception e) {
logger.error("Could not to initialize CsfxFunction.");
}
return null;
}
private static Context createContext() {
return new Context() {
@Override
public int getTimeLimitInMs() {
return 0;
}
@Override
public String getRequestId() {
return null;
}
@Override
public int getMemoryLimitInMb() {
return 0;
}
};
}
public Set<String> getFunctionNames() {
return functions.keySet();
}
public Function<Gateway, Response> lookup(String name) {
if (name == null) {
return null;
}
return functions.get(name);
}
public Entry<String, Function<Gateway, Response>> match(String path) {
if (path == null) {
return null;
}
Set<Entry<String, Function<Gateway, Response>>> entrySet = functions.entrySet();
for (Entry<String, Function<Gateway, Response>> entry : entrySet) {
String pattern = entry.getKey();
if (pathMatcher.match(pattern, path)) {
return entry;
}
}
return null;
}
public Map<String, String> buildPathParameters(String contextPath, String path) {
if (contextPath == null || path == null) {
return Collections.emptyMap();
}
return pathMatcher.extractUriTemplateVariables(contextPath, path);
}
}
六、redis相关操作15条建议
1、redis间数据同步可以使用:redis-port。
2、allkeys-lru策略:根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止。
3、allkeys-random策略:随机删除所有键,直到腾出足够空间为止。
4、volatile-random策略:随机删除过期键,直到腾出足够空间为止。
5、volatile-ttl策略:根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退到noeviction策略。
6、noeviction策略:不会剔除任何数据,拒绝所有写入操作并返回客户端错误信息"(error) OOM command not 7、allowed when used memory策略:此时Redis只响应读操作。
8、big key搜索:redis大key搜索工具。
9、内部实现使用monitor,所以建议短时间使用facebook的redis-faina 阿里云Redis已经在内核层面解决热点key问题。
10、高并发下建议客户端添加熔断功能(例如netflix hystrix)。
11、原生命令:例如mget、mset ;非原生命令:可以使用pipeline提高效率。
12、有遍历的需求可以使用hscan、sscan、zscan代替。
13、建议使用expire设置过期时间(条件允许可以打散过期时间,防止集中过期),不过期的数据重点关注idletime
14、redis的key名称以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id
15、redis 4.0已经支持key的异步删除。