树相关算法工具、redis相关操作15条建议、SCF API 实现

一、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的异步删除。

猜你喜欢

转载自blog.csdn.net/qq_32447301/article/details/108312767