Fork me on GitHub

Synchronize 关键字原理

https://juejin.im/post/5a5c488e518825733a30ae9d

众所周知 Synchronize 关键字是解决并发问题常用解决方案,有以下三种使用方式:

  • 同步普通方法,锁的是当前对象。
  • 同步静态方法,锁的是当前 Class 对象。
  • 同步块,锁的是 () 中的对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 同步普通方法
public synchronized void run() {

}

// 同步静态方法
public synchronized static void run() {

}

// 同步块
public void test() {
synchronized(this){

}
}

良好文档的4条原则(翻译)

原文地址: The 4 Tenets of Good Documentation

我最近和一个我带的初级开发人员讨论代码文档,并提出了良好文档应该包括的四件事。在向我的学员讲过这一点之后,他们惊讶于为什么以前没有人如此简洁地说过。所以我决定写下这些原则,以防读者也看不到它们。

好的代码文档必须告诉下一个开发人员(即使是同一个人)以下四点信息:

  • 目的:为什么编写代码(是库,代码段,方法或类)
  • 功能:代码在做什么,
  • 形式:代码如何实现其功能,以及
  • 用法:如何使用代码。

在本文的其余部分中,我将使用 PieChart 类作为示例,该类的编写目的是在屏幕上显示饼图。这是一个非常简单的概念,它完全封装了可能会被重用的单个功能。

目的:为什么要编写代码

为什么创建这个 PieChart 类?在我们的示例中,它封装了向用户显示饼图所需的所有代码。在我们的应用程序中,我们将显示很多饼图,因此,最好有一个编写良好的类来处理它们。因此,此类的简单目的是使显示饼图更易于编码。

一般来说,这是最容易编写的文档。一方面,这纯粹是观点。编写该类的原因是你想要或需要编写它。你只需要将其目的传达给下一个开发人员。这样,你可以让下一个人看到它,以了解它为什么对你创建的整个项目或库很重要,他们将更好地掌握如何在代码中使用它。此外,文档的这一部分不必冗长。它只需要足够的信息告诉开发人员到底是什么。

在文档的这一部分中,你还应该列出编写此代码的所有假设。在这里,你可能要列出此代码的替代方案,这些替代方案可能无法满足你的特定要求。

1
2
3
目的:

PieChart 封装了显示饼图的功能,给用户一个可重用的类。

功能:这段代码在做什么

这是你编写的代码的高级描述。在我们的 PieChart 类示例中,代码将获取用户数据并将其显示为饼图。但是,该描述过于简洁,实际上只是”目的”部分的重复。

我们需要做的是解释 PieChart 的所有部分都在做什么。在提供表格文档时,可以将其分解为多个部分并进行解释。不过,对于复杂的代码,最好对功能进行汇总,并与代码原理的解释分开。

1
2
3
功能:

PieChart 接收用户数据并将其转换为可显示的格式,然后呈现给用户。饼图使用本地图形库创建,并使用提供的字符串进行描述。饼图可以在屏幕范围内创建为任意大小,并且可以放置在屏幕上的任何位置,只要它们完全在屏幕范围内即可。饼图将使用一组计算出的颜色创建,以提供各部分之间的对比。如果需要,也可以设置颜色。

形式:此代码的工作方式

现在我们需要深入研究代码。这是我们在这里解释所使用的所有微妙技巧,所使用的所有复杂算法以及代码进行的所有假设的地方。并不是每个方法或属性都需要单独文档化,特别是如果它们的名称是见名知意的。但是,复杂的方法和方法参数绝对应该如此,特别是当可以使用编辑器自动完成查看注释时。

这里的文档应该是这样的水平:如果要让其他人去看(或者如果你要在6个月后再回来查看它),不会有关于它如何工作的问题。这可以说是最华丽的赞美了。

在这里,你还需要解释为什么选择一种算法而不是另一种算法,尤其是当你使用的算法是非标准算法时。对于大多数类型的软件,有许多标准实践,如果你的代码将要偏离这些标准,请提供充分的文档说明其原因和方式。我知道作为开发人员,我们有多喜欢在我们的代码中利用巧妙的技巧。但是,如果你没有足够地证明这种聪明才智,那么没人会理解或信任你的所作所为。

以下是 PieChart 的一种方法 DrawChart() 的一个很好注释的示例(在此缩写为空格)。

1
2
3
4
5
6
7
8
9
10
11
12
13
格式:

/ *
此方法DrawChart()包含用于
在屏幕上绘制图表的所有图形代码。它希望从类属性中知道大小
(半径),中心位置,数据数组,颜色数组和
描述数组。没有这些,该
方法将失败。绘制循环:根据数据计算圆弧,从中心到圆弧
起点绘制线,绘制圆弧,从圆弧末端到中心绘制线,填充
颜色,创建描述字符串视图,基于
圆弧旋转视图,绘制字符串视图。该方法将在失败时引发错误。
* /
func DrawChart()

用法:如何使用此代码

最后,我们需要描述如何使用代码。对于某些代码,这是可选的,但前提是用法简单,明显且易于从代码中推断出来。通常只有使用简单方法或高度描述枚举之类的代码时才如此。其他所有内容均应使用,并在可能的情况下以自动完成编辑器可以理解注释以及自文档库可以读取它的方式添加注释。

1
2
3
4
5
6
7
8
用法:

PieChart.init(Array userData [],Array userColors [],Array
description [],double radius,point centerPoint)userData是一个值数组(双精度),将用于
计算饼图的百分比部分。userColors是一个可选的颜色数组,
每个值与一个颜色匹配。descriptions是一个可选的字符串数组,显示在
每个楔形中,每个值与一个匹配。radius是饼图的半径。centerPoint是饼图的中心,是一个点结构
(双x,双y)。

第五条宗旨:乐趣

编写或阅读文档通常都不是很有趣。如果做得正确,文档能提供很多信息,但文档通常很枯燥,有时很难理解。我喜欢在我的注释中搞些幽默,我鼓励你也这样做。一个无伤大雅的,有目的的双关语或基于上下文的笑话常常受到读者的赞赏。不过要注意政策。一些老板对此不满意。

结论

好的文档是成为优秀开发人员的一部分。如果没有其他原因,我鼓励每个开发人员养成为代码写文档的习惯,他们将能够理解自己所写的内容。而且,我向你保证,如果你勤奋地编写良好的文档,你的同事和合作者将为此而喜欢你。

Spring Boot 使用枚举类型作为请求参数

本文作者: xkcoding

原文链接: https://xkcoding.com/2019/01/30/spring-boot-request-use-enums-params.html

1. 场景

在我们实际开发中,枚举类型应用十分广泛,可以避免在项目中定义大量的『魔法值』变量。但是,在 web 开发中,如何将枚举对象作为请求参数传进 Controller,做到类型自动转换?直接使用 @RequestParam@RequestBody 断然是不够的,这里就需要我们自定义 Converter 来实现类型转化了。

2. 需求

比如一个用户对象,里面的性别属性,我们定义一个枚举类型 Gender

GenderEnum.java

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
/**
* <p>
* 性别枚举
* </p>
*
* @package: com.xkcoding.springboottest.constants.enums
* @description: 性别枚举
* @author: yangkai.shen
* @date: Created in 2019-01-30 11:06
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
@Getter
public enum GenderEnum {
/**
* 男
*/
MALE(0),
/**
* 女
*/
FEMALE(1);

/**
* 性别编码
*/
private Integer code;

GenderEnum(int code) {
this.code = code;
}

}

请求对象封装 QueryRequest

QueryRequest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* <p>
* 请求参数
* </p>
*
* @package: com.xkcoding.springboottest.controller.enum_test
* @description: 请求参数
* @author: yangkai.shen
* @date: Created in 2019-01-30 14:02
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
@Data
public class QueryRequest {
private GenderEnum gender;
}

在 Controller 层直接使用如下方式,期望参数自动进行类型转换

EnumTestController.java

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
/**
* <p>
* 测试参数是枚举类型,自动转换
* </p>
*
* @package: com.xkcoding.springboottest.controller.enum_test
* @description: 测试参数是枚举类型,自动转换
* @author: yangkai.shen
* @date: Created in 2019-01-30 13:56
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
@Slf4j
@RestController
@RequestMapping("/enum")
public class EnumTestController {

@GetMapping("/get")
public Dict testGet(QueryRequest request) {
log.info("【get-request】= {}", JSONUtil.toJsonStr(request));
return Dict.create().set("get-request", request);
}

@PostMapping("/post")
public Dict testPost(@RequestBody QueryRequest request) {
log.info("【post-request】= {}", JSONUtil.toJsonStr(request));
return Dict.create().set("post-request", request);
}

}

这么写的时候,gender 只能接收到 MALEFEMALE 这样的参数,除此以外,均会报类型不匹配的错误信息,此时是无法处理 01 这样的参数的。

需求:

  1. 接收到 MALEFEMALE 这样的参数,可以自动转为对应的枚举值;
  2. 接收到 01 这样的参数,也可以自动转为对应的枚举值。

3. 解决

此时,本文的『主角』Converter 就可以隆重登场了。

注意,Converterorg.springframework.core.convert.converter.Converter ,别导错包了。

IntegerCodeToGenderEnumConverter.java

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
/**
* <p>
* 编码 -> 性别 转换器
* </p>
*
* @package: com.xkcoding.springboottest.config.convert
* @description: 编码 -> 性别 转换器
* @author: yangkai.shen
* @date: Created in 2019-01-30 11:14
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
public class IntegerCodeToGenderEnumConverter implements Converter<Integer, GenderEnum> {
private Map<Integer, GenderEnum> enumMap = Maps.newHashMap();

public IntegerCodeToGenderEnumConverter() {
for (GenderEnum genderEnum : GenderEnum.values()) {
enumMap.put(genderEnum.getCode(), genderEnum);
}
}

@Override
public GenderEnum convert(Integer source) {
GenderEnum genderEnum = enumMap.get(source);
if (ObjectUtil.isNull(genderEnum)) {
throw new IllegalArgumentException("无法匹配对应的枚举类型");
}
return genderEnum;
}
}

其实这里已经可以实现类型转换了,但是引出另外一个问题,当我们的枚举类特别多的时候,我们就需要写很多个 自定义的 Converter 来满足类型转化。

所以我们不使用上面直接使用 Converter 的这种方法,我们引入 ConverterFactory 来解决这个问题。

3.1. 抽取公共枚举接口

以后的枚举类都需要实现这个接口

BaseEnum.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* <p>
* 通用枚举接口
* </p>
*
* @package: com.xkcoding.springboottest.constants
* @description: 通用枚举接口
* @author: yangkai.shen
* @date: Created in 2019-01-30 11:04
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
public interface BaseEnum {
/**
* 获取枚举编码
*
* @return 编码
*/
Integer getCode();
}

3.2. 调整 GenderEnum 枚举类

GenderEnum.java

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
/**
* <p>
* 性别枚举
* </p>
*
* @package: com.xkcoding.springboottest.constants.enums
* @description: 性别枚举
* @author: yangkai.shen
* @date: Created in 2019-01-30 11:06
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
@Getter
public enum GenderEnum implements BaseEnum {
/**
* 男
*/
MALE(0),
/**
* 女
*/
FEMALE(1);

/**
* 性别编码
*/
private Integer code;

GenderEnum(int code) {
this.code = code;
}

}

3.3. 创建通用 Integer -> Enum 的 Converter 类

IntegerToEnumConverter.java

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
/**
* <p>
* 枚举编码 -> 枚举 转化器
* </p>
*
* @package: com.xkcoding.springboottest.config.convert
* @description: 枚举编码 -> 枚举 转化器
* @author: yangkai.shen
* @date: Created in 2019-01-30 11:21
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
public class IntegerToEnumConverter<T extends BaseEnum> implements Converter<Integer, T> {
private Map<Integer, T> enumMap = Maps.newHashMap();

public IntegerToEnumConverter(Class<T> enumType) {
T[] enums = enumType.getEnumConstants();
for (T e : enums) {
enumMap.put(e.getCode(), e);
}
}

@Override
public T convert(Integer source) {
T t = enumMap.get(source);
if (ObjectUtil.isNull(t)) {
throw new IllegalArgumentException("无法匹配对应的枚举类型");
}
return t;
}
}

3.4. 创建对应的自定义 ConverterFactory 工厂类

IntegerCodeToEnumConverterFactory.java

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
/**
* <p>
* 编码 -> 枚举 转化器工厂类
* </p>
*
* @package: com.xkcoding.springboottest.config.convert.factory
* @description: 编码 -> 枚举 转化器工厂类
* @author: yangkai.shen
* @date: Created in 2019-01-30 11:09
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
public class IntegerCodeToEnumConverterFactory implements ConverterFactory<Integer, BaseEnum> {
private static final Map<Class, Converter> CONVERTERS = Maps.newHashMap();

/**
* 获取一个从 Integer 转化为 T 的转换器,T 是一个泛型,有多个实现
*
* @param targetType 转换后的类型
* @return 返回一个转化器
*/
@Override
public <T extends BaseEnum> Converter<Integer, T> getConverter(Class<T> targetType) {
Converter<Integer, T> converter = CONVERTERS.get(targetType);
if (converter == null) {
converter = new IntegerToEnumConverter<>(targetType);
CONVERTERS.put(targetType, converter);
}
return converter;
}
}

3.5. 创建通用 String -> Enum 的 Converter 类和对应的 ConverterFactory 工厂类

因为 Post 请求可以对传入的 json 属性定义类型,但是 Get 请求后台接收到的参数都是 String 类型,因此需要在创建一个 Converter 类

阅读更多...

ARTS-7

ARTS是由左耳朵耗子陈皓在极客时间专栏《左耳听风》中发起的一个每周学习打卡计划。

1
2
3
4
5
6
7
Algorithm:至少做一个 LeetCode 的算法题。主要为了编程训练和学习。

Review:阅读并点评至少一篇英文技术文章。主要为了学习英文,如果你英文不行,很难成为技术高手。

Tip:学习至少一个技术技巧。主要是为了总结和归纳你日常工作中所遇到的知识点。

Share:分享一篇有观点和思考的技术文章。主要为了输出你的影响力,能够输出你的价值观。

Algorithm(算法)

leetcode394

题目链接:https://leetcode-cn.com/problems/decode-string/

参考视频:https://www.youtube.com/watch?v=Qoz3ujccNQY

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a2[4] 的输入。

示例:

1
2
3
s = "3[a]2[bc]", 返回 "aaabcbc".
s = "3[a2[c]]", 返回 "accaccacc".
s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".

答案

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
public class Solution {

/*
s = "3[a2[c]]"

accaccacc
*/
public String decodeString(String s) {
// 存储重复的次数
Deque<Integer> numStack = new ArrayDeque<>();
// 存String
Deque<String> strStack = new ArrayDeque<>();


StringBuilder tail = new StringBuilder();
int n = s.length();
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
// 如果是数字
if (Character.isDigit(c)) {
int num = c - '0';
// 判断下一位是否也是数字
while (i + 1 < n && Character.isDigit(s.charAt(i + 1))) {
num = num * 10 + s.charAt(i+1) - '0';
i++;
}
numStack.push(num);
} else if (c == '['){
// 遇到左括号,将tail变为字符串存到strStack
strStack.push(tail.toString());
// 清空 tail
tail = new StringBuilder();
} else if (c == ']') {
// 弹出 strStack 赋值给 tmp a
StringBuilder tmp = new StringBuilder(strStack.pop());
// 获取重复次数
int repeatedTimes = numStack.pop();
for (int j = 0; j < repeatedTimes; j++) {
tmp.append(tail);
}
tail = tmp;
} else {
tail.append(c);
}
}
return tail.toString();
}
}

Review(点评)

The 4 Tenets of Good Documentation

良好文档的四个原则

好的代码文档必须告诉下一个开发人员(即使是同一个人)以下四点信息:

  • 目的:为什么编写代码(是库,代码段,方法或类)
  • 功能:代码在做什么
  • 形式:代码如何实现其功能
  • 用法:如何使用代码。

Tip(技巧)

实际项目中,会用VO类返回数据给前端数据,有时候如果VO有字段是LocalDatatime,返回的时间数据中间可能会带有T字符,比如”2019-10-11T11:11:11”,这个时候在时间字段上加上@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 注解即可。

1
2
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;

Share(分享)

排序算法

JDK13新特性详解

原文地址: https://my.oschina.net/mdxlcj/blog/3107021

1、switch优化更新

JDK11以及之前的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break; case THURSDAY:
case SATURDAY:
System.out.println(8);
break;
case WEDNESDAY:
System.out.println(9);
break;
}

JDK12版本

1
2
3
4
5
6
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}

JDK13版本

1
2
3
4
5
6
7
8
9
static void howMany(int k) {
System.out.println(
switch (k) {
case 1 -> "one"
case 2 -> "two"
default -> "many"
}
);
}

2、文本块升级

2.1、html例子

JDK13之前

1
2
3
4
5
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";

JDK13优化的

1
2
3
4
5
6
7
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";

2.2、SQL变化

JDK13之前

1
2
3
String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
"WHERE `CITY` = 'INDIANAPOLIS'\n" +
"ORDER BY `EMP_ID`, `LAST_NAME`;\n";

JDK13

1
2
3
4
5
String query = """
SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
WHERE `CITY` = 'INDIANAPOLIS'
ORDER BY `EMP_ID`, `LAST_NAME`;
""";

2.3、解释

文本块

1
2
3
4
5
"""
line 1
line 2
line 3
"""

相当于字符串文字

1
"line 1\nline 2\nline 3\n"

3、动态CDS档案

目标:

提高应用程序类 - 数据共享(AppCDS)的可用性。消除了用户进行试运行以创建每个应用程序的类列表的需要。

-Xshare:dump

使用类列表由该选项启用的静态归档应继续工作。这包括内置类加载器和用户定义的类加载器的类。

4、取消使用未使用的内存

摘要:

增强ZGC以将未使用的堆内存返回给操作系统。

动机:

ZGC目前没有取消提交并将内存返回给操作系统,即使该内存长时间未使用。对于所有类型的应用程序和环境,此行为并非最佳, 尤其是那些需要关注内存占用的应用程序和环境 例如:通过使用支付资源的容器环境。应用程序可能长时间处于空闲状态并与许多其 他应用程序共享或竞争资源的环境。应用程序在执行期间可能具有非常不同的堆空间要求。

例如,启动期间所需的堆可能大于稳态执行期间稍后所需的堆。HotSpot中的其他垃圾收集器,如G1和Shenandoah,今天提供 了这种功能,某些类别的用户发现它非常有用。将此功能添加到ZGC将受到同一组用户的欢迎。

5、重新实现旧版套接字API

摘要:

使用更简单,更现代的实现替换java.net.Socket和java.net.ServerSocketAPI 使用的底层实现,易于维护和调试。新的实 现很容易适应用户模式线程,也就是光纤,目前正在Project Loom中进行探索。

动机:

在java.net.Socket和java.net.ServerSocketAPI,以及它们的底层实现,可以追溯到JDK 1.0。实现是遗留Java和C代 码的混合,维护和调试很痛苦。该实现使用线程堆栈作为I/O缓冲区,这种方法需要多次增加默认线程堆栈大小。该实现使用本机数据 结构来支持异步关闭,这是多年来微妙可靠性和移植问题的根源。该实现还有几个并发问题,需要进行大修才能正确解决。在未来的光 纤世界环境中,而不是在本机方法中阻塞线程,当前的实现不适用于目的。

6、FileSystems.newFileSystem新方法

核心库/ java.nio中添加了FileSystems.newFileSystem(Path,Map )方法

添加了三种新方法java.nio.file.FileSystems,以便更轻松地使用将文件内容视为文件系统的文件系统提供程序。

阅读更多...

我希望在我开始编程之前就知道的30件事(翻译)

原作者: Jun Wu

原文地址: 30 Things I Wish I Knew When I Started Programming

译者: 高行行

如果你想成为一名程序员,此列表可以帮你走在正确的道路上

编程并非易事。每年都有许多人从美国顶尖的计算机科学专业毕业,这是任何人都可以从事的最具竞争力的职业之一。同时,编程生涯令人兴奋。随着技术的进步,行业每天都有创新。对于喜欢它的人来说,编程成为了他们热爱的工作。

当我在15年前开始担任程序员时,我希望有人让我坐下来,并告诉我这份名单上的所有内容。此列表可以为任何新程序员节省很多精力。此列表是你随着编程职业发展可能遇到事情的列表。即使这些观点中的某些观点可能与你现在无关,但有一天你会看到其中的智慧。

1. 你不需要学位来编程,但是你需要知识

我曾与许多没有获得计算机科学硕士学位或计算机科学学士学位的程序员一起工作。编程是不依赖学位的少数职业之一。但是,编程是知识密集型的职业。如果要开始从事编程职业,则必须 阅读这十本必不可少的书。这十本书将涵盖计算机科学的基本概念以及如何在项目团队中工作。在编写功能代码的基础上,对基本概念有扎实的了解,为你的技术技能打下坚实的基础,将使你能够进行技术面试并与你的同事进行交流。

2. 解决问题的技巧使编程更具创造力

大多数人都以为编程就是解析和解决问题的技能。这是部分正确的。编程还涉及很多创造力。通常,有很多方法可以编写给定的代码。当你设计出最简单有效的编码方法时,便会产生创意。

3. 你无法学到一切

有数百种编程语言。某些编程领域为特定的职业铺平了道路:Web开发人员,前端开发人员,后端开发人员,软件工程师,数据库开发人员等。确定要成为什么样的开发人员,然后学习这个特定职位的所有技术和技能。

4. 你不需要成为机器人。如果你是人类会更好

记住,首先你是人类,其次你才是程序员。刚开始编程时,很容易迷失在代码中。有时候,在完成项目的所有里程碑之前,我不会离开计算机。但是你是一个人。你需要大笑、哭泣,减轻压力并与他人交谈。通过管理自己的生活以最大程度地增加工作之外的乐趣和激情,你将为你程序员工作带来更多的创造力。

5. 编程全部与应用知识有关。与记忆无关

与研究不同,在研究中你要发明和创造新的知识领域,而编程则只不过是应用现有知识。书籍、研究论文、在线文章和学习视频会成为你经常使用的资源。无需记住任何内容。你总是可以获取资源来找到答案。在你从事项目越多时,记忆会自然而然地出现。

6. 你每天都会处理冒名顶替综合症

注:冒名顶替症候群(英语:Impostor syndrome),亦称为冒名顶替现象(英语:impostor phenomenon)、骗子症候群(英语:fraud syndrome)。这个名称是在1978年由临床心理学家克兰斯博士(英语:Pauline R. Clance)与因墨斯(英语:Suzanne A. Imes)所提出,用以指称出现在成功人士身上的一种现象。患有冒名顶替症候群的人无法将自己的成功归因于自己的能力,并总是担心有朝一日会被他人识破自己其实是骗子这件事。他们坚信自己的成功并非源于自己的努力或能力,而是凭借著运气、良好的时机,或别人误以为他们能力很强、很聪明,才导致他们的成功。即使现实环境中的证据指明,他们确实具备优秀才能,他们还是认为自己只是骗子,不值得获得成功。有研究显示,冒名顶替症候群在高成就女性当中较为常见;同时也有研究指出男性与女性的盛行率没有差异

编程是所有“聪明”的人似乎都倾向于的职业。除非你是天才,否则你将像我一样每天都遭受冒名顶替综合症。当你每天体验它时,你往往会想出一种应对它的方法。对我而言,我一直将它作为学习新事物的动力。我已经学会了客观看待,并且乐于每天改进一点。

7. 你必须拥有成为程序员之外的生活。否则,你将沉迷于编程

有时你会宅在家里。但是,要成为一个快乐的程序员,你必须主动寻求计算机屏幕之外的生活。通常,你事业的成功取决于你遇到的人。当你是程序员时,人际网至关重要。要成为程序员,除了要成为一名程序员以外,还要有个性。当你可以尽情享受自己的激情时,你最好的工作就会来到。

8. 如果你与某人结对编程,你将更快地学习编程

在你职业生涯的开始,你将很容易向世界敞开大门,并阅读那十本有关编程的书,以建立你的计算机科学基础。你猜怎么了?如果找到一个好友,你的学习就会更快。我花了一半的时间阅读编程书籍,和一个伙伴一起从事一个项目。当你与某人结对编程时,程序的所有“缺陷”就会显现出来。你的代码将受到批评。你将学习编写高效的代码,因为有人在看。你将想找出最好的做事方式,因为你的好友也在学习。当你作为程序员工作时,总是有人在检查你的代码。你永远不会一个人编程。现在该习惯了。

9. 你不需要擅长数学和科学

在技术行业中,你会遇到各种各样的超级巨星程序员,他们在毕生的通识教育之后发现程序设计的逻辑思维方面很有吸引力。有很多画家和作家在一边追求艺术一边进行生动的编程。要成为一名优秀的程序员,你所需要的就是持久性。编程是艰苦的工作。但是一旦有了这些,任何人都可以阅读编程书籍并掌握基础知识。在该行业工作一段时间后,有很多人学习数学。最终,这些人甚至可以理解复杂的算法并在没有任何形式的数学教育的情况下实现它们。

10. 你需要成为全明星的“学习者”

程序员是一个精通学习的人。你可能没有开始成为一名精通学习的人。但是你会到达那里。有时你的工作场所会要求你在六个月内学习三种编程语言。那就是技术创新的状态。作为程序员,我们每天学习。学习就像呼吸。如果你不习惯每天学习,你将被迫习惯。

11. 你将沉迷于完成项目

编码成瘾是一件实事。在你编程生涯中的某个时候,你将体验通宵的编程马拉松。在完成里程碑之后,你才想入睡。你会忘记吃饭,喝酒,甚至从办公桌上站起来,因为你的大脑正在处理大量信息。没关系。完成后,到户外散步。外出度假。

12. 你将花费一整天寻找一个微小的错误

大多数时候,在编程项目中,许多部分相互依赖。通常,你将发现自己无法继续前进,除非你修复了系统中潜伏的一个小错误。作为程序员,除非发现此错误,否则你将对整个项目感到压力。你将整日坐在计算机旁寻找它。你将在晚上梦见代码,直到找到它。

13. 你将花费大部分时间来搜寻没人能回答的答案

如果你使用一种流行的语言进行编程,则可以在线找到遇到的大多数问题的答案。但是,也有例外。有时,没有人遇到你遇到的问题。在这种情况下,参考编程书籍并在编程板块上四处询问通常会为你指明正确的方向。

14. 你将阅读一本设计模式书

是否毕业于该国最好的计算机科学程序都没关系。在每个程序员的职业生涯中,都有一段时间你会坐下来,从头到尾阅读《Head First设计模式》。对于新程序员来说,这可能是最该读的书之一。你还在等什么?拿起并翻阅。

15. 你将学会迷恋确切的拼写

在每个程序员的职业生涯中的某个时候,你都会用自己喜欢的语言编写足够的代码,以自己的方式做事。这包括为变量,类甚至数据库中的表提供命名规约的确切拼写。你将仔细检查这一点。你想要的最后一件事是一些bug,因为你拼错了一个名字。请记住,如果你有充分的理由,那么可以沉迷于事物。如果你没有充分的理由,那只是重复的行为。

16. 你会放弃

我放弃了多少次?我甚至不能统计。有时,你遇到的是你无法解决的问题。有时变得如此困难,以至于你只想退出。有时工作环境会让你想辞职。你的激情取决于你的坚持不懈。这是你经过测试的时间。你在这里停留还是要去?我总是回来。有时,经过几年不编写任何代码后,我总是回来当一个新人,准备处理一个项目。它成为家园,是你冒险的跳板。

17. 你将重新启动

如果你相信更高的权力,那么你将能够与之建立联系。每次,当我看到人们回到编程时,通常不是因为钱。它始终是出于对编程的热爱。当你看到像以前一样喜欢编程的人,你会羡慕不已。你不能放手,然后,突然,你又回到了一个项目。当你知道自己是一名真正的程序员时。你在自己的内心中知道自己生活和呼吸代码。

18. 你将回到某种形式的学校学习“正确”的做事方式

即使是从精英计算机科学硕士课程毕业的最好的程序员,也将在工作中继续他们的教育。实际上,在职培训是大型技术公司工作的最佳福利之一。公司将向你发送“昂贵的”课程和研讨会,以培训你掌握他们要用的最新技术。如果碰巧你仍然在工作中学习掌握的不够,则可以接触许多在线编码学院和youtube视频,以提高自己的技能。

19. 你会被你不想为之工作的人雇用

即使你是普通的程序员,有时也会有某些公司需要你的技能。他们面试你时,请记住,你也在面试他们。根据公司的文化,你可能会发现自己想对一揽子包装说“不”。作为程序员,你将工作很长时间。找到适合你的公司文化几乎至关重要。幸福导致更好的工作。如果需要你的技能,其他公司将为你服务。除非有必要,否则请不要安顿下来。

20. 你将进行技术面试

技术面试不是开玩笑。高级程序员通常会很有趣地编写技术面试问题。通常,这些问题由于某种原因而特别困难。如果你未能通过技术面试,那就不是世界末日。当然,它并没有说明你的编程能力。它只会测试你的知识库。尝试看向光明的一面。如果你的人际交往能力大放异彩,管理人员就会记住你。如果他们喜欢你,而你不适合担任此职位,他们可能仍然会要求你担任其他职位。

21. 你会被告知你很棒

在你的职业生涯中,有时你会觉得自己是明星。依赖你完成项目的经理会告诉你你真伟大,以此来激励你。你会觉得自己处在世界之巅。请记住,它们会让你变得自我。保持平常心。总是有新技术要学习。总是有比你更好的新程序员。

22. 你会被告知你什么都不知道

有时候,你会觉得自己一无所知。对项目感到沮丧的人会将矛头指向你,告诉你你一无所知。也许他们这样做是为了将你放在你的位置。但是,既然你正在阅读本文,你将大步向前。因为你可能比你想像的要了解得多。每一天过去,你都会比前一天学到更多。一年后,人们会仰望你。继续吧,一段时间后,你甚至可能会得到那些告诉你你一无所知的人的尊重。

23. 你将要与你欣赏的其他程序员竞争

编程最令人敬畏的方面之一是竞争。我喜欢和我佩服的人一起编程。当你可以编写你所敬佩的程序员认为值得的代码时,你会觉得自己刚刚中了彩票。编程竞赛总是很有趣。这与谁是最好的无关。这更多地是关于彼此相互学习。

24. 你会不理解同事刚才说的一句话

首先,这可能会每周一次或每月一次。在你从事新的编程工作时,你将不会理解同事刚才说的话。这可能有两个原因。在你的一生中,你只是无法理解他们的口音。在这种情况下,请其他同事翻译。无法理解某人的讲话没有什么可耻的。很有可能,其他同事也需要几年的时间来适应这种口音。另一个原因是你的同事所说的话完全超出了你的理解范围。没关系,毕竟,你的同事是专家。请你的同事以图片形式解释所有这些。你将为此准备一把椅子。可能需要一段时间。

25. 看着你去年编写的意大利面条代码你会感到羞耻

这事儿常常发生。开始时,我因Perl代码而受到批评。代码记录良好,也设计得很好,但是我用一种很难读的语言写的。所以,我写了意大利面条代码。但是,每年,无论我多么努力,我仍然会找到一些意大利面条式的代码,这些代码我会迅速整理完成。程序员就是这样做的。我们修复并修补问题。这没有什么可耻的。当你意识到是谁编写的时,请退后一步并对其进行修复。

26. 当你病得无法看另一行代码时,你将在数据库项目中避难

这条英语没太看懂 🤣

当你进行长时间编程时,会发生这种情况。已经两个月了。你需要休息一下。但是,你喜欢这种动力,所以你可以继续前进。然后你意识到SQL很有趣。你无法弄清楚为什么看不到另一行代码。但是以某种方式,将数据放入数据库并将其取出是一件令人高兴的事情。你完全陶醉于完全合乎逻辑语言的简单性。

27. 你会对黑客马拉松爱恨交加

黑客马拉松如今很普遍。程序员进入团队并相互竞争。在此过程中,将在几个小时内进行大量学习。你会喜欢友善的黑客马拉松。你会讨厌它以最高速度打字时出现的腕管综合症。你还会因为工作中拥挤的房间以及活动期间感觉到的过度刺激而讨厌它。

28. 阅读研究论文时,你会认为自己听不懂英语

你会说英语吗?好吧,大多数人会说是的。但是,我向你保证,你将一遍又一遍地阅读一些研究论文,并意识到这太麻烦了。对我而言,在我学习大学数学基础之前,大多数有关算法的研究论文似乎像一片巨大的树林。然后,突然之间,一切似乎都有意义。

29. 你将会购买耳机

在你的职业生涯的某个时刻,当你全神贯注于代码时,你会意识到任何噪音都会干扰你的感觉。拥有可以消除外部噪音的优质耳机,可以让你在拥挤的房间内集中精力工作。在某些时候,你还会发现音乐可以帮助你编码。我在编码生涯的早期就发现音乐的节奏可以帮助我流畅地编码。即使是现在,当我需要提高工作效率时,我也会喜欢一些音乐。

30. 你将去异地。如果你很幸运,它将在拉斯维加斯。

在你职业生涯的某个时刻,你位于对你的公司非常重要的开发人员小组的内部。这是你将被邀请到异地的时候。这个异地可能是技术专业人员一起社交的地方。高层管理人员可能会借此机会认识你。不要误会我的意思。现在不是时候变得无忧无虑而喝醉了。现在是时候与你的同龄人进行社交和人际交往。如果幸运的话,地点将在拉斯维加斯。有时,它还会包括与其他公司的技术人员举行的会议或会议。

ARTS-6

ARTS是由左耳朵耗子陈皓在极客时间专栏《左耳听风》中发起的一个每周学习打卡计划。

1
2
3
4
5
6
7
Algorithm:至少做一个 LeetCode 的算法题。主要为了编程训练和学习。

Review :阅读并点评至少一篇英文技术文章。主要为了学习英文,如果你英文不行,很难成为技术高手。

Tip:学习至少一个技术技巧。主要是为了总结和归纳你日常工作中所遇到的知识点。

Share:分享一篇有观点和思考的技术文章。主要为了输出你的影响力,能够输出你的价值观。

Algorithm(算法)

leetcode 414. 第三大的数

https://leetcode-cn.com/problems/third-maximum-number/

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
public class Solution {
public int thirdMax(int[] nums) {
// 存储最大
Integer max1 = null;
// 存储第二大
Integer max2 = null;
// 存储第三大
Integer max3 = null;
for (Integer num : nums) {
// 去重,如果已经存在就跳过
if (num.equals(max1) || num.equals(max2) || num.equals(max3)) continue;
// 先比较最大的,成功就把值向后传递,把第三大的丢掉 当 max1 == null 时直接将 num 赋值给 最大值max1
if (max1 == null || num > max1) {
max3 = max2;
max2 = max1;
max1 = num;
} else if (max2 == null || num > max2) { // 第一个判断没中,判断是不是第二大的,注意值不能等于最大,这是为了防止重复 当 max2 == null 时直接将 num 赋值给 第二大值 max2
max3 = max2;
max2 = num;
} else if (max3 == null || num > max3) { // 同上 当 max3 == null 时直接将 num 赋值给 第三大值 max3
max3 = num;
}
}
return max3 == null ? max1 : max3; // 判断第三大的数存不存在, 不存在返回最大数.
}
}

Review(点评)

我希望在我开始编程之前就知道的30件事(翻译)

Tip(技巧)

inner join 可以改为使用where进行隐形连接

SELECT * FROM A ,B WHERE A.ID = B.ID 是比较常用的2个表关联。where是隐形连接,而inner join是比较符合数据库语言发展的显性连接。而且,更详细的资料表明:常用数据库会自动把where转换成inner join 。

Share(分享)

走进JVM Java内存布局

  • Copyrights © 2015-2023 高行行
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信