补第四周
1.Algorithm:每周至少做一个 leetcode 的算法题
2.Review:阅读并点评至少一篇英文技术文章
3.Tip:学习至少一个技术技巧
4.Share:分享一篇有观点和思考的技术文章
以下是各项的情况:
Algorithm
链接:[LeetCode-13]-Roman to Integer
罗马数字 | I | V | X | L | C | D | M |
相应的阿拉伯数字表示为 | 1 | 5 | 10 | 50 | 100 | 500 | 1000 |
总结 :
没有让我们来验证输入字符串是不是罗马数字这点很赞,不然得考虑用正则或者写判断条件判断下 要写很长。 那么 假定 输入的绝对是罗马数字,那么要将题转换成 :
输入罗马数字 转换成对应整数值,同时
1.如果当前数字是最后一个数字,或者之后的数字比它小的话,则加上当前数字。
2. 其他情况则减去这个数字。
要将罗马数字和相应整数值对应 那么使用map结构进行对应 , 应该会是一个可行的方案 。
/* 记录对应数组 String[] num1 = {“I”,”II”,”III”,”IV”,”V”,”VI”,”VII”,”VIII”,”IX”}; String[] num10 = {“X”, “XX”,”XXX”,”XL”,”L”,”LX”,”LXX”,”LXXX”,”XC”}; String[] num100 = {“C”,”CC”,”CCC”,”CD”,”D”,”DC”,”DCC”,”DCCC”,”CM”}; String[] num1000 = {“M”,”MM”,”MMM”}; */ class Solution { public int romanToInt(String s) { int sum = 0; if(s.indexOf("IV")!=-1) sum-=2; if(s.indexOf("IX")!=-1) sum-=2; if (s.indexOf("XL") != -1) sum -= 20; if (s.indexOf("XC") != -1) sum -= 20; if (s.indexOf("CD") != -1) sum -= 200; if (s.indexOf("CM") != -1) sum -= 200; char[] c = s.toCharArray(); for(int i = 0; i < c.length; i++) { if (c[i] == 'I') sum += 1; if (c[i] == 'V') sum += 5; if (c[i] == 'X') sum += 10; if (c[i] == 'L') sum += 50; if (c[i] == 'C') sum += 100; if (c[i] == 'D') sum += 500; if (c[i] == 'M') sum += 1000; } return sum; } }
Review
分享 设计模式:工厂模式
工厂是每个开发人员应该知道的关键创建模式之一。
4种工厂模式:
- 工厂(factory)方法模式 ,
- 抽象(abstract)工厂模式,
- 静态(static)工厂方法,
- 简单(simple)工厂(也称为工厂)。
此外最关键的 作者提出不要滥用 工厂模式 ,只有在对于涉及使用相同代码的多个开发人员的大中型项目推荐使用 , 他会在以下情况内推荐避免使用:
- 当我在家里/工作单独编码时,避免使用。
- 对于不会改变很多的小项目,也避免使用。
工厂模式的优势是代码的可读性和理解之间的权衡!
工厂模式用来创建objects, 不过为什么不直接用构造函数调用创建objets 作者也有讲到,很细心。
两个优点是工厂模式在复杂的使用中 抛弃了直接用构造函数 :
1. 控制实例化
限制类的实例数 比如 : 将如何设置只有一个(或2个或10个)类的实例,特别是它使用类似套接字,或者数据库连接或文件系统描述符等资源。
这种情况下,使用构造函数方法,不同的函数(来自不同的类)很难知道类的实例是否已经存在。 而使用一个静态工厂方法 ,相对于构造函数方法 就轻松了很多
public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return INSTANCE; } ... } ... public class ClassXXX{ ... public static void someFunctionInClassXXX(){ Singleton instance = Singleton.getInstance(); //some stuff } } ... public class ClassYYY{ ... public static void someFunctionInClassYYY(){ Singleton instance = Singleton.getInstance(); //some stuff } }
我们使用的工厂将Singleton类的实例数限制为一个。
注意:我们可以修改实例的创建方式(例如,通过使用原型模式而不是每次从头开始创建新对象),而不是限制实例的数量。
2. 松耦合
比如 ,我们假设您编写了一个计算内容并需要编写日志的程序。由于它是一个很大的项目,你的代码是在编写业务类时将日志写入文件系统(类FileSystemLogger)的类。没有工厂,您需要在使用之前使用构造函数实现FileSystemLogger:
public class FileSystemLogger { ... public void writeLog(String s) { //Implemation } } ... public void someFunctionInClassXXX(some parameters){ FileSystemLogger logger= new FileSystemLogger(some paramters); logger.writeLog("This is a log"); }
但是如果突然发生变化并且您现在需要使用实现DatabaseLogger在数据库中写入日志会发生什么?没有工厂,您将不得不使用FileSystemLogger类修改所有函数。由于此记录器在任何地方都使用,您需要修改数百个函数/类,而使用工厂, 您可以通过仅修改工厂来轻松地从一个实现切换到另一个实现:
//this is an abstraction of a Logger public interface ILogger { public void writeLog(String s); } public class FileSystemLogger implements ILogger { ... public void writeLog(String s) { //Implemation } } public class DatabaseLogger implements ILogger { ... public void writeLog(String s) { //Implemation } } public class FactoryLogger { public static ILogger createLogger() { //you can choose the logger you want // as long as it's an ILogger return new FileSystemLogger(); } } ////////////////////some code using the factory public class SomeClass { public void someFunction() { //if the logger implementation changes //you have nothing to change in this code ILogger logger = FactoryLogger.createLogger(); logger.writeLog("This is a log"); } }
可以轻松地将Logger实现从FileSystemLogger更改为DatabaseLogger。您只需要修改createLogger()函数(这是一个工厂)。此更改对于客户端(业务)代码是不可见的,因为客户端代码使用logger(ILogger)的接口。
3 . 封装 (具体见文章里的)
4. 消歧 (具体见文章里的)
静态工厂:
Joshua Bloch在“Effective Java”中描述了静态工厂方法:
“类可以提供一个公共静态工厂方法,它只是一个返回类实例的静态方法。”
真实的例子
以下是Java框架和Java API中的静态工厂方法的一些示例。由于Joshua Bloch是许多Java API的主要架构师,所以在Java API中查找示例非常简单。
记录框架
java日志框架slf4j,logback和log4j使用抽象类LoggerFactory。如果开发人员想要编写日志,他需要从LoggerFactory的静态方法getLogger()获取Logger实例。
getLogger()返回的Logger实现将取决于getLogger()实现(以及getLogger()使用的开发人员编写的配置文件)。
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Example{ public void example() { //we're using the static factory method to get our logger Logger logger = LoggerFactory.getLogger(Example.class); logger.info("This is an example."); } }
简单的工厂
Tip
MySQL查询流程
只有查询优化,索引优化,库表结构优化都进行时,才能实现MySQL高性能 。真正重要的是响应时间。
查询主流程:
1. 客户端发送一条查询给服务器
2. 服务器先检查查询缓存,如果命中缓存,立刻返回存储在缓存中的结果,否则进入下一阶段
3. 服务器进行SQL解析,预处理,再由优化器生成对应的执行计划,
4. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询
5. 将结果返回客户端
MYSQL连接状态:
对于一个MYSQL连接,或者说一个线程,任何时刻都有一个状态,代表MYSQL在做什么
最简单查看状态方式命令是使用show full processlist
在一个查询周期中,状态可能会改变多次
这些状态有:
sleep:
线程正在等待客户端发送新的请求
query:
线程正在执行查询或者正在将结果发送给客户端
locked:
在MYSQL服务器层,该线程正在等待表锁。在存储引擎级别实现的锁,
例如innoDB的行锁,并不会体现在线程状态中。对于myisam来说这是一个比较典型的状态,其他没有
行锁的引擎也会经常出现
analyzing and statistics:
线程正在收集存储引擎的统计信息,并生成查询的执行计划。
copying to tmp table[on disk] :
线程正在执行查询,并且将结果复制到一个临时表 , 这种状态一般要么是在做group by 操作, 要么是文件排序操作,或者是union操作
如果这个状态后有on disk 标记,那表示MYSQL正在将一个内存临时表放在磁盘上
sorting result:
线程正在对结果集进行排序
sending data:
这表示多种情况,线程可能在多个状态之间传送数据,或者在生成结果集,或者在客户端发送请求
Share
这周推荐一篇观点,是关于性玩具应用程序现在可以计算卡路里,应该反对的 , 比较有趣 。果然不管国内外 , 科技是第一生产力 , 性是第二生产力啊 。。。 大意就是 飞机杯或者自慰器 有应用程序去监控消耗了多少的卡路里,甚至有厂商用智能手表 去监控 你啪啪啪的程度 , 有教程推送 来教你 , 来让你达到一个标准让双方满足 ???? 以此来达到健身的效果。。。真是黑科技。。。将性产品转换为了健康运动制度的一部分进行营销 。。。
不过 我和作者观点一致 不只是由于尴尬 , 其实这也是一种侵犯隐私的方式 。 如果是国内 还会记录数据 加入大数据里 进行分析 , 来达到购买推荐和相亲的推荐吧 ?? 这其实并不好 。是一件无语的创新。
https://sextechguide.com/opinion/sex-toy-apps-can-now-count-calories-really-shouldnt/