日常学习回顾与汇总

日常学习回顾与汇总

20200321 星期六

mysql

1
2
3
4
5
6
7
8
9
group_concat()与group by一起使用,支持排序

group_concat( columnA order by columnA desc/asc)

distinct columnA,columnB

cast(columnA as decimal(20,4))

case when 表达式 then 结果 when 表达式2 then 结果 else 结果 end

English

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
I love dog. 我爱吃狗肉
dog eat dog 残酷的竞争
Love me , love my dog. 爱屋及乌
Every dog has its day. 凡人皆有出头之日

fish out of water 尴尬,不自在的人
She is blackwashed. 有人黑你
Come out in the wash. 真相大白
Come on be reasonable. 理智一点

reputation 声誉声望

play my foot in my mouth 说错话
a slip of the tongue 口误 说漏嘴
my foot 我不信,得了吧
foot the bill 买单
keep a foot in both camps 脚踏两只船

java

if…else的优化

  1. 提前return ,去除不必else

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    private static void one() {

    int a = 10;
    int b = 100;

    // 优化前
    if (a < b) {
    System.out.println(b - a);
    } else {
    return;
    }
    //优化后
    if (b <= a) {
    return;
    }
    System.out.println(b - a);

    }
  1. 三目运算符

  2. 使用枚举

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    private static void three() {
    int status = 5;
    String statusName = "";

    //优化前
    if (status == 0) {
    statusName = "临时保存";
    } else if (status == 1) {
    statusName = "提交";
    } else if (status == 2) {
    statusName = "审批";
    } else if (status == 3) {
    statusName = "拒绝";
    } else if (status == 4) {
    statusName = "回收";
    } else if (status == 5) {
    statusName = "删除";
    }

    //优化后
    statusName = Status.getStatusName(status);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    package base;

    public enum Status {
    temp(0,"临时保存"),save(1,"提交"),sp(2,"审批"),hs(3,"回收"),jj(4,"拒绝"),delete(5,"删除");

    public static String getStatusName(int value){
    for(Status o: Status.values() ){
    if(o.getValue() == value){
    return o.getDesc();
    }
    }
    return "";
    }


    private int value;
    private String desc;

    public int getValue() {
    return value;
    }

    public void setValue(int value) {
    this.value = value;
    }

    public String getDesc() {
    return desc;
    }

    public void setDesc(String desc) {
    this.desc = desc;
    }

    Status(int value, String desc) {
    this.value = value;
    this.desc = desc;
    }
    }
  1. 合并条件表达式

    多个表达式,可以进行判断的进行何在一个条件里面进行判断

  2. 使用optional

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    String name = "张三";
    //优化前
    if(name != null){
    System.out.println(name);
    } else {
    System.out.println("NULL");
    }

    //优化后
    Optional<String> nameOP = Optional.of(name);
    // JAVA9
    nameOP.ifPresentOrElse(System.out::println, () -> System.out.println("Null"));
  1. 表驱动法

    表驱动法,又称之为表驱动、表驱动方法。表驱动方法是一种使你可以在表中查找信息,而不必用很多的逻辑语句(if或case)来把它们找出来的方法。以下的demo,把map抽象成表,在map中查找信息,而省去不必要的逻辑语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 优化前
if (param.equals(value1)) {
doAction1(someParams);
} else if (param.equals(value2)) {
doAction2(someParams);
} else if (param.equals(value3)) {
doAction3(someParams);
}
//优化后
Map<?, Function<?> action> actionMappings = new HashMap<>(); // 这里泛型 ? 是为方便演示,实际可替换为你需要的类型
// 初始化
actionMappings.put(value1, (someParams) -> { doAction1(someParams)});
actionMappings.put(value2, (someParams) -> { doAction2(someParams)});
actionMappings.put(value3, (someParams) -> { doAction3(someParams)});
// 省略多余逻辑语句
actionMappings.get(param).apply(someParams)
  1. 优化逻辑结构,正常流程走主干

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //优化前
    public double getAdjustedCapital(){
    if(_capital <= 0.0 ){
    return 0.0;
    }
    if(_intRate > 0 && _duration >0){
    return (_income / _duration) *ADJ_FACTOR;
    }
    return 0.0;
    }
    //优化后

    public double getAdjustedCapital(){
    if(_capital <= 0.0 ){
    return 0.0;
    }
    if(_intRate <= 0 || _duration <= 0){
    return 0.0;
    }
    return (_income / _duration) *ADJ_FACTOR;
  1. 策略模式+工厂方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        String medalType = "guest";
    if ("guest".equals(medalType)) {
    System.out.println("嘉宾勋章");
    } else if ("vip".equals(medalType)) {
    System.out.println("会员勋章");
    } else if ("guard".equals(medalType)) {
    System.out.println("展示守护勋章");
    }

    //勋章接口
    public interface IMedalService {
    void showMedal();
    String getMedalType();
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    //守护勋章策略实现类
    public class GuardMedalServiceImpl implements IMedalService {
    @Override
    public void showMedal() {
    System.out.println("展示守护勋章");
    }
    @Override
    public String getMedalType() {
    return "guard";
    }
    }
    //嘉宾勋章策略实现类
    public class GuestMedalServiceImpl implements IMedalService {
    @Override
    public void showMedal() {
    System.out.println("嘉宾勋章");
    }
    @Override
    public String getMedalType() {
    return "guest";
    }
    }
    //VIP勋章策略实现类
    public class VipMedalServiceImpl implements IMedalService {
    @Override
    public void showMedal() {
    System.out.println("会员勋章");
    }
    @Override
    public String getMedalType() {
    return "vip";
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //勋章服务工产类
    public class MedalServicesFactory {
    private static final Map<String, IMedalService> map = new HashMap<>();
    static {
    map.put("guard", new GuardMedalServiceImpl());
    map.put("vip", new VipMedalServiceImpl());
    map.put("guest", new GuestMedalServiceImpl());
    }
    public static IMedalService getMedalService(String medalType) {
    return map.get(medalType);
    }
    }
    1
    2
    3
    String medalType = "guest";
    IMedalService medalService = MedalServicesFactory.getMedalService(medalType);
    medalService.showMedal();

JVM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-XX:MetaspaceSize=128m 元空间默认大小

-XX:MaxMetaspaceSize=128m 元空间最大大小

-Xms1024m 堆最大大小

-Xmx1024m 堆最小大小

-Xmn256m 新生代大小

-Xss256k 栈最大深度

-XX:SurvivorRatio=8 新生代分区比例(8:2

-XX:+userConcMarkSweepGC 指定CMS收集器

-XX:+printGCDetails 打印详细的GC日志

20200325 星期三

English

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Eat one's words   收回前言  承认错误
Break one's word 食言
keep one's word 守信用 履行诺言
cut it out 省省吧 闭嘴

level off 稳定下来

go to your room 你完蛋了(来源于美国把孩子关小黑屋)
sleep late 睡到很晚才起来
It's sick 狂拽炫霸
I feel you 我懂你
You are a chicken 胆小鬼 胆怯的人

prise 赞扬 钦佩
compliment 赞美称赞
flatter 奉承 讨好
Good for you 干的漂亮
fire something off 匆忙寄发(邮件等)

Don't go around something the world owes you a living.The world owes you nothing.
别到处跟别人抱怨这个世界欠你什么,这个世界什么都不欠你的。

bad apple 坏家伙

a cool fish 冷漠的人,态度冰冷的人

drawn-out 冗长的

You have a phone call 你来电话了
It is your call 这是你的电话
Your phone is ringing.

hang up 挂断
answer the phone 回电话
screen your calls 不方便接电话/骚扰电话

I have got the wrong number 打错电话

It didn't get through 电话打不通

I'm broke. 我没钱了。

make heavy weather of sth 小题大做
replacement 代替 替补
take out the rubbish. 扔垃圾

mysql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
count(column)  查询不为null的数目
count(*) sql标准用法,查询所有数据

mysql执行引擎:InnonDB MyISAM

MyISAM:表级锁,可以把表的总行数记录下来,会直接把行数返回,前提是没有where 条件
MyISAM做了一个简单的优化,那就是它可以把表的总行数单独记录下来,如果从一张表中使用COUNT(*)进行查询的时候,可以直接返回这个记录下来的数值即可。

InnonDB:支持事务,行级锁
InnoDB中索引分为:
聚簇索引(主键索引)->查询的是整行记录
非聚簇索引(非主键索引)->该行记录的逐渐值

非聚簇索引比聚簇索引小很多,mysql优先选择最小的非聚簇索引来扫表,故在建表时,创建一个非主键索引很有必要。

InnonDB: count(1)和count(*) 查询速率是一样的

Mysql索引扫盲总结

其他

模因:英文 meme

基因使得各种物种生物把自己的生理特征遗传给下一代。

模因使得人类把思想、行为传播给其他人。

两者有区别:遗传性(童话,诗歌)、变异性(改编童话)、选择性(适者生存)

传播方式、表理行事、自主选择权

20200330

mysql

  • 尽量使用select 具体字段

    • 节省资源,减少网络开销
    • select * 可能不会使用到覆盖索引
  • 如果知道只有一条结果,建议使用limit 1

    • 如果存在limit 1 找到第一条就会返回不会继续扫描
    • 如果查询条件为唯一索引的话没有必要加上limit 1 ,因为唯一索引也是在查找到第一个记过后进行返回0
  • 尽量避免在where语句众使用or进行连接条件

    • 使用or可能会使索引失效,从而扫描全表,使用union all

      1
      select * from t_user where id= 1 union all select * from t_user where name = '张三'

      如果name没有索引,操作为:索引扫描+全表扫描+合并

  • 优化limit分页

    • 当偏移量很大时,limit就会很低下

      1
      2
      3
      4
      select * from t_user limit 100000,10
      -- 改造后
      select * form t_user where id >100000 limit 10
      -- 或者

20210506

mysql

offset 与 limit

在常规的使用中科院满足,在大数量的情况下会导致不足。

因每次进行分页时数据库都会进行低效的全盘扫描。

全盘扫描:又称为顺序扫描,在数据库中进行逐行扫描,顺序读取每一行的数据,然后检查是否符合查询条件。这种扫描最慢,因为需要大量的磁盘I/O,从磁盘到内存的开销很大。

OFFSET 越高,查询时间就越长。

替代方案

1
select * from table_name id > 10 limit 20

基于指针的分页,本地上保存上次分页的接受的主键和limit。

因为通过显示的告诉数据库最新行,数据库可知道从哪里开始搜索(基于有效的索引),而无需考虑范围之外的记录。

建议:尽量使用自增主键,即使为了分页。

其他

  • Drone自动化部署

  • 获取key用keyset(),若获取value则使用entryset()

  • Collection.isEmpty()的复杂度为O(1),size()的时间复杂度为O(n)
  • 初始化集合尽量指定大小
  • 频繁调用Collection.contains使用set,复杂度为O(1)
  • 工具类中屏蔽构造函数(private)
  • 字符串用String.valueOf()比“”+value更有效
  • 返回空数组或者集合而非NULL
  • 枚举属性字段为私有并不可修改

布隆过滤器

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难

使用场景:

1、黑名单 2、URL去重 3、单词拼写检查 4、Key-Value缓存系统的Key校验 5、ID校验,比如订单系统查询某个订单ID是否存在,如果不存在就直接返回

20210507

springboot启动原理

注解:

1
2
3
@SpringBootApplication
=@SpringBootConfiguration(实际上是@Configuration)+@EnableAutoConfiguration+
@ComponentScan

启动时候的执行流程

  1. 创建SpringApplication实例,然后调用该对象的实例方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
    * Static helper that can be used to run a {@link SpringApplication} from the
    * specified sources using default settings and user supplied arguments.
    * @param primarySources the primary sources to load
    * @param args the application arguments (usually passed from a Java main method)
    * @return the running {@link ApplicationContext}
    */
    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return new SpringApplication(primarySources).run(args);
    }

    在初始化的时候会进行一下操作

    • 判断是否创建一个为web使用的ApplicationContext类型。

    • 加载可用的ApplicationContextInitializer

    • 加载可用的ApplicationListener

    • 推断并设置main方法定义类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      /**
      * Create a new {@link SpringApplication} instance. The application context will load
      * beans from the specified primary sources (see {@link SpringApplication class-level}
      * documentation for details. The instance can be customized before calling
      * {@link #run(String...)}.
      * @param resourceLoader the resource loader to use
      * @param primarySources the primary bean sources
      * @see #run(Class, String[])
      * @see #setSources(Set)
      */
      @SuppressWarnings({ "unchecked", "rawtypes" })
      public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
      this.resourceLoader = resourceLoader;
      Assert.notNull(primarySources, "PrimarySources must not be null");
      this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
      this.webApplicationType = WebApplicationType.deduceFromClasspath();
      setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
      setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
      this.mainApplicationClass = deduceMainApplicationClass();
      }
  1. 初始化完成后执行,执行main方法。遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener.调用他们的starting()方法,通知他们SpringBoot要启动了。

  2. 创建并配置当前springboot将要使用的Environment(包括配置要使用的PropertySource以及Profile)

  3. 遍历所有的SpringApplicationRunListener的environmentPrepared(),通知SpringBoot,环境准备好了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
    ApplicationArguments applicationArguments) {
    // Create and configure the environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
    environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
    deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
    }
  1. 如果SpringBoot的showBanner属性为TRUE,则进行打印Banner

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private Banner printBanner(ConfigurableEnvironment environment) {
    if (this.bannerMode == Banner.Mode.OFF) {
    return null;
    }
    ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
    : new DefaultResourceLoader(null);
    SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
    if (this.bannerMode == Mode.LOG) {
    return bannerPrinter.print(environment, this.mainApplicationClass, logger);
    }
    return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
    }
  1. 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    /**
    * Strategy method used to create the {@link ApplicationContext}. By default this
    * method will respect any explicitly set application context or application context
    * class before falling back to a suitable default.
    * @return the application context (not yet refreshed)
    * @see #setApplicationContextClass(Class)
    */
    protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
    try {
    switch (this.webApplicationType) {
    case SERVLET:
    contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
    break;
    case REACTIVE:
    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
    break;
    default:
    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
    }
    }
    catch (ClassNotFoundException ex) {
    throw new IllegalStateException(
    "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
    }
    }
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
    }
  2. ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializerinitialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。

  3. 遍历调用所有SpringApplicationRunListenercontextPrepared()方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
    SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    context.setEnvironment(environment);
    postProcessApplicationContext(context);
    applyInitializers(context);
    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
    logStartupInfo(context.getParent() == null);
    logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
    beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof DefaultListableBeanFactory) {
    ((DefaultListableBeanFactory) beanFactory)
    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.lazyInitialization) {
    context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    // Load the sources
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));
    listeners.contextLoaded(context);
    }
  1. 最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext

  2. 遍历调用所有SpringApplicationRunListenercontextLoaded()方法。

  3. 调用ApplicationContextrefresh()方法,完成IoC容器可用的最后一道工序。

  4. 查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。

  5. 正常情况下,遍历执行SpringApplicationRunListenerfinished()方法、(如果整个过程出现异常,则依然调用所有SpringApplicationRunListenerfinished()方法,只不过这种情况下会将异常信息一并传入处理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//获取SpringApplicationRunListeners,并进行执行staring()
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
//获取配置环境
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
//打印Banner
Banner printedBanner = printBanner(environment);
//创建ApplicationContext
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//初始化initializer,遍历listeners的context方法
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}

try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}

参考:

面试官:能说下 SpringBoot 启动原理吗? (qq.com)

本文标题:日常学习回顾与汇总

文章作者:wsylp

发布时间:2020年03月22日 - 17:03

最后更新:2021年05月08日 - 14:05

原始链接:http://wsylp.github.io/2020/03/22/日常学习回顾与汇总/

许可协议: 本文为 wsylp 版权所有 转载请保留原文链接及作者。

-------------本文结束感谢阅读-------------