1.Algorithm
给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
class Solution { public int[] twoSum(int[] nums, int target) { Map<integer,integer> map = new HashMap<integer,integer>; for(int i = 0; i < nums.length; i++){ int difference = target - nums[i]; if(map.containsKey(difference)){ retur new int[nums[i],map.get(difference)] } map.put(nums[i],i) } throw new illegalAtgumentExveption("no"); } }
复杂度分析:
-
时间复杂度:O(n)O(n), 我们只遍历了包含有 nn 个元素的列表一次。在表中进行的每次查找只花费 O(1)O(1) 的时间。
-
空间复杂度:O(n)O(n), 所需的额外空间取决于哈希表中存储的元素数量,该表最多需要存储 nn 个元素。
2.Review
阅读了redis 官方技术 关于pub/sub的文档 ,在阅读的过程中 认识到了 自己英语水平能力的差劲,
SUBSCRIBE,UNSUBSCRIBE和PUBLISH 实现了发布/订阅消息传递范例,其中(引用维基百科)发件人(发布者)没有被编程为将其消息发送给特定接收者(订阅者)。相反,已发布的消息被表征为信道,而不知道可能存在什么(如果有的话)订户。订阅者表达对一个或多个频道的兴趣,并且仅接收感兴趣的消息,而不知道存在哪些(如果有的话)发布者。发布者和订阅者的这种分离可以允许更大的可扩展性和更动态的网络拓扑。
为了订阅频道foo
,bar
客户端发出提供频道名称的SUBSCRIBE:
SUBSCRIBE foo bar
推送消息的格式
第一个元素是消息的类型:
-
subscribe
:表示我们成功订阅了作为回复中第二个元素的通道。第三个参数表示我们当前订阅的频道数。 -
unsubscribe
:表示我们成功取消订阅作为回复中第二个元素的频道。第三个参数表示我们当前订阅的频道数。当最后一个参数为零时,我们不再订阅任何通道,并且客户端可以发出任何类型的Redis命令,因为我们在Pub / Sub状态之外。 -
message
:它是由另一个客户端发出的PUBLISH命令收到的消息。第二个元素是原始通道的名称,第三个参数是实际的消息有效负载
数据库和范围
Pub / Sub与密钥空间无关。它被认为不会在任何级别上干扰它,包括数据库号。
数据库1上的订阅者将听到db 10上的发布。
匹配模式订阅
redis pub/sub实现支持模式匹配,客户端可以订阅glob样式模式,以便接收发送到与给定模式匹配的通道名称的所有消息。
PSUBSCRIBE news.*
PUNSUBSCRIBE news.*
然后将取消订阅改模式的客户端,此通话不会影响其他订阅
由于模式匹配而收到的消息以不同的格式发送:
消息的类型是pmessage:它是由另一个客户端发出的PUBLISH命令接收的消息,匹配模式匹配订阅。第二个元素是原始模式匹配,第三个元素是原始通道的名称,最后一个元素是实际消息有效负载。
类似于SUBSCRIBE和UNSUBSCRIBE,PSUBSCRIBE和 PUNSUBSCRIBE命令由系统发送类型的消息确认psubscribe和punsubscribe使用相同的格式 subscribe和unsubscribe消息格式。
匹配模式和订到订阅的消息
如果客户端订阅了与已发布消息匹配的多个模式,或者如果订阅了与该消息匹配的模式和信道,则客户端可以多次接收单个消息
SUBSCRIBE foo
PSUBSCRIBE f*
订阅的含义计数与模式匹配
在subscribe和unsubscribe,psubscribe以及punsubscribe 消息类型中,最后一个参数是仍处于活动状态的订阅计数。此数字实际上是客户端仍订阅的频道和模式的总数。因此,只有当此计数从所有通道和模式取消订阅后降至零时,客户端才会退出发布/订阅状态。
3.TIPS
利用spring-AOP 实现了 请求参数 路径 和返回参数的 日志打印
@Aspect @Configuration public class LogRecordAspect { private static final Logger logger = LoggerFactory.getLogger(LogRecordAspect.class); /** * 定义切点Pointcut */ @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)") public void excudeService() { } @Around("excudeService()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; HttpServletRequest request = sra.getRequest(); String url = request.getRequestURL().toString(); String method = request.getMethod(); String uri = request.getRequestURI(); String queryString = request.getQueryString(); Object[] args = pjp.getArgs(); String params = ""; //获取请求参数集合并进行遍历拼接 if(args.length>0){ if("POST".equals(method)){ Object object = args[0]; Map map = getKeyAndValue(object); params = JSON.toJSONString(map); }else if("GET".equals(method)){ params = queryString; } } logger.info("请求开始===地址:"+url); logger.info("请求开始===类型:"+method); logger.info("请求开始===参数:"+params); // result的值就是被拦截方法的返回值 Object result = pjp.proceed(); logger.info("请求结束===返回值:" + JSON.toJSON(result)); return result; } public static Map<String, Object> getKeyAndValue(Object obj) { Map<String, Object> map = new HashMap<>(); // 得到类对象 Class userCla = (Class) obj.getClass(); /* 得到类中的所有属性集合 */ Field[] fs = userCla.getDeclaredFields(); for (int i = 0; i < fs.length; i++) { Field f = fs[i]; // 设置些属性是可以访问的 f.setAccessible(true); Object val = new Object(); try { val = f.get(obj); // 得到此属性的值 // 设置键值 map.put(f.getName(), val); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return map; } }
Share
用redis 实现分布式 锁
private ThreadLocal<String> local = new ThreadLocal<>(); @Override public void lock() { if(tryLock()){ return; } try { Thread.sleep(RandomUtils.nextInt(2000)); } catch (InterruptedException e) { e.printStackTrace(); } lock(); } @Override public boolean tryLock() { String uuid = UUID.randomUUID().toString(); Long setResdisLocal = RedisUtils.setNx("local", uuid); if(setResdisLocal != null && "OK".equals(setResdisLocal)){ RedisUtils.expire("loca",200); local.set(uuid); System.out.println("加锁成功。。。"); return true; } System.out.println("加锁失败。。。"); return false; } @Override public void unlock() { String uuid = local.get(); Jedis jedis = new Jedis("localhost"); Object loca = jedis.eval("if redis.call('get',KEYS[1])==ARGV[1] " + "then reeturn redis.call('del',KEYS[1] else return 0 end)", 1, "loca", uuid); }