java tricky

1、根据枚举的name获取枚举类:

private static SmsProviderType fromName(String spName) {
  return Stream.of(SmsProviderType.values()).filter(sp -> StringUtils.equals(sp.name(), spName)).findFirst().orElse(null);
}

2、字符串转成int(注意给默认值):NumberUtils.toInt

3、collect(Collectors.joining()) 表示把所有字符串连接起来

4、把null转成empty:nullToEmpty()方法

5、joiner.join可以用分隔符把元素连接在一起

6、实体类转为Map形式:
obj -> jsonStr -> map

7、Optional

Optional.ofNullable(...) 入参为null则返回null,否则返回入参
ofNullable(...).ifPresent() 如果ofNullable的结果不是空,则调用ifPresent
Optional.orElse(value) 如果optional保存的是null,返回value。如果保存的不是null,返回option自己的值
Optional.orElseGet(...) 和orElse一样,只是入参是对象
一般从stream中选出个体,就要调用stream的findFirst()方法,然后orElse
firstNonEmpty(T... values)方法,第一个入参不为空则返回 为空则判断后面的 以此类推
isPresent() 返回boolean,如果值存在则方法会返回true,否则返回 false
anyMatch(): stream中任何一个元素满足即返回true
allMatch(): stream中所有元素都满足即返回true
.findAny().isPresent() 和 anyMatch的含义一样

8、forEach和forEachOrder区别:两者完成的功能类似,主要区别在并行处理上,forEachOrdered()将始终按照流(stream)中元素的遇到顺序执行给定的操作,而forEach()方法是不确定的。

9、sorted中可以把Comparator.comparing()的结果作为入参。Comparator.comparing().thenComparing() 可以定义多个排序规则

10、Exception: e.getClass().getSimpleName()可以拿到具体异常的类型

11、Sets.difference(set1, set2) 可以获取元素:在set1中存在但是在set2中不存在。Set的retainAll方法:求交集
12、@RestController注解相当于@ResponseBody + @Controller

13、idea或eclipse的jvm arguments加入 -Dfuck.abc="1234" 在代码中System.getProperty("fuck.abc")可以获取这个值。-D是用来在启动java程序时设置系统属性的
接口中的default方法会被实现类直接继承

14、Random r = new Random() nextInt(bound) 会生成0到bound的值 每次不一样
Random r = new Random(100) 指定种子后,nextInt(bound) 会生成0到bound的值 每次都一样

15、去掉字符串指定的前缀:StringUtils.removeStart(fullNumber, "+")

16、日期转换,SimpleDateFormat线程不安全,要使用LocalDateTime和DateTimeFormatter

localDatetime和毫秒数转化
LocalDateTime end = LocalDateTime.of(2020, 3, 3, 18, 38, 00);
System.out.println(end.toInstant(ZoneOffset.of("+8")).toEpochMilli());

// 使用localDatetime,进行Date和字符串转换

public static final DateTimeFormatter DATE_FORMATTER_YYYYMMDD = DateTimeFormatter.ofPattern("yyyyMMdd");
//  字符串转Date
private Date parseDateStrToDate(@Nonnull String dateStr) {
  LocalDate localDate = LocalDate.parse(dateStr, DATE_FORMATTER_YYYYMMDD);
  LocalDateTime localDateTime = localDate.atStartOfDay();
  Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
  return date;
}
// Date转字符串
private String parseDateToDateStr(@Nonnull Date date) {
  LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
  return localDateTime.format(DATE_FORMATTER_YYYYMMDD);
}

localDatetime校验日期字符串是否符合格式

TemporalAccessor startTimeTemporal = DATE_FORMATTER_YYYYMMDD.parseUnresolved(request.getStartDate(), new ParsePosition(0));
commonParamCheck(startTimeTemporal == null, "开始日期格式不正确,正确格式为yyyyMMdd");

 

//把yyyy-MM-dd HH:mm:ss转化为Date类型
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date myDate2 = dateFormat2.parse("2020-04-25 05:20:01");
System.out.println(myDate2);
System.out.println(myDate2.getTime());

//把Date类型转化为yyyyMMdd字符串

SimpleDateFormat resultFormat = new SimpleDateFormat("yyyyMMdd");
Date date = new Date();
String result = resultFormat.format(date);

17、编码

http的queryString中内容(即?后的内容)和www-form-urlencoded form表单中的内容,经过http请求后会自动被urlEncode编码。urlencode会把/转为%2F,+转为%2B

如果某个字符串需要放入http请求参数中,比如想把某个字符串放在?后, 需要把字符串经过Base64.encodeBase64URLSafeString, 否则会有字符丢失。

Base64非url safe的编码结果,会有+等内容。

Base64.encodeBase64URLSafeString() 方法可以实现+转化为-,/转化为_ 并去掉==。

Base64.encodeBase64URLSafeString()和Base64.encodeBase64String() 生成的字符串 用Base64.decodeBase64() 生成的结果是一样的

对于url safe编码,不管编码多少次,都能用Base64.decodeBase64成功解码

base64编码会让数据扩大1/3

18、IOUtils读取文件

//读取file

String photoPath = "abc";
File photo = new File(photoPath);
byte[] bytes = FileUtils.readFileToByteArray(photo);

//读取inputStream

List<String> words = IOUtils.readLines(ChengYuClickCaptchaTest.class.getResourceAsStream("/words.txt"), "UTF-8")

19、

retrofit2 Response 拿到所有response header:
Headers headersFromResponse = httpRsult.headers();
拿到指定header:
String requestId = String.valueOf(headersFromResponse.get("X-Ca-Request-Id"));

20、retrofit2的http相关注解

@QueryMap Map<String, Integer> map 可传多个参数,都以?形式拼接

如果url中?sig=... @Query("sig") 可传入一个参数对应

@HeaderMap 表示http头部传多个参数

如果@POST("/{indexes}/{type}), @Path("indexes") String indexes 即表示传入参数
@Body 可传入requestBody

21、jdk8 stream

peek: 不能修改流中的元素,只能对元素进行打印输出或者改变引用类型的属性。peek入参是consumer
filter(strategy -> strategy != null) 可用filter(Objects::nonNull)代替

stream代替for循环:IntStream.range(0, 100).forEach()

22、ImageIO生成图片

ImageIO.read可以传入InputStream对象,生成BufferedImage即图片,参考验证码中台ShadowLineamentGeneratorTest
也可以传入file对象

22、查看数据或图片大小:转为byte[]数组,数组长度即代表多少byte,除以1024可得出kb 

23、try (ByteArrayInputStream in = new ByteArrayInputStream(image)) try-with-resource可以自动关闭流

24、

@ExceptionHandler此注解使用在方法级别,声明对Exception的处理逻辑。可以指定目标Exception
@ResponseBody此注解用在请求handler方法上。和@RequestBody作用类似,用于将方法的返回对象直接输出到http响应中。
@RestControllerAdvice此注解用于class上,相当于同时引入了@ControllerAdvice和@ResponseBody两个注解。

在Spring里,我们可以使用@ControllerAdvice来声明一些全局性的东西,最常见的是结合@ExceptionHandler注解用于全局异常的处理。
@ExceptionHandler注解标注的方法:用于捕获Controller中抛出的不同类型的异常,从而达到异常全局处理的目的;
@ControllerAdvice("com.cmos.edcreg.web.controller") 可以声明该类要处理的包路径 

ResponseBodyAdvice 接口是在 Controller 执行 return 之后,在 response 返回给客户端之前,执行的对 response 的一些处理,可以实现对 response 数据的一些统一封装或者加密等操作。比如可以实现ResponseBodyAdvice接口,在实现类中获取api controller的返回值。
详见:https://www.cnblogs.com/goloving/p/15045736.html

25、java对象转成json成立的基本条件只需要有get方法

public class ResultView<DATA> {
public long getTimestamp() {
return System.currentTimeMillis();
}

public String getHostname() {
return HostInfo.getHostName();
}
}

则ObjectMapperUtils.toJSON(resultView)的结果是{hostname":"MacBook-Pro.local","timestamp":1650543262512},所以get方法可以把java对象可自动转为json

26、ajax JSON.stringify 后端用@RequestBody方式接收,参数必须用实体类或者Map<String, Object>接收

ajax参数 contentType表示告诉服务器请求数据的类型
dataType表示告诉服务器,我要想什么类型的数据

27、@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8"):
private Date createTime;
表示序列化时,将createTime字段转为yyyy-MM-dd HH:mm:ss格式

28、@JsonValue: 序列化时,将枚举序列化为code或name,反序列化时,由code或name反序列化成枚举

public enum GridElement {
/**
* 商业化元素
*/
BUSINESS_ELEMENT(6, "商业化元素"),
;

private int intValue;
private String desc;

@JsonValue
public String getDesc() {
return desc;
}
}

表示BUSINESS_ELEMENT序列化的结果是「商业化元素」,也可以由「商业化格元素」反序列化得到BUSINESS_ELEMENT

29、@JsonUnwrapped注解:将嵌套的对象平铺展开
https://juejin.cn/post/7067812048419160071

30、hive解析json:https://blog.csdn.net/qq_34105362/article/details/80454697

get_json_object(response_detail, '$.body.messages[0].status') = 6

mysql解析json:https://blog.csdn.net/unity_zyc/article/details/80654442

31、java类转为json字符串,下列条件需要满足一个:

a、对应字段需要有set和get方法,否则该字段转化的结果为空。
b、如果没有get和set方法,可以用@JsonProperty注解,也可以达到将类转为json字符串效果

32、jackson在反序列化时,默认使用对象的默认构造函数,如果默认构造函数不存在,jackson会报错。

33、@JsonProperty和@JSONField注解

作用:此注解用于属性上,作用是把该属性的名称A序列化为另外一个名称B,反序列化时可以把新名称B转换为属性名称A

区别:@JsonProperty位于jackson包中,搭配ObjectMapper().writeValueAsString(Object) 和ObjectMapper().readValue(str, Class)使用

@JSONField位于fastjson包中,搭配JSON.toJSONString(Object) 和 JSON.parseObject(str, Class)使用

34、在某字段上注释@JsonIgnore,可以在json序列化时忽略此字段

35、@JsonCreator注解其作用是,指定对象反序列化时的构造函数或者工厂方法,如果默认构造函数无法满足需求,或者说我们需要在构造对象时做一些特殊逻辑,可以使用该注解。该注解需要搭配@JsonProperty使用。

@JsonCreator
public Person(@JsonProperty("age") int age, @JsonProperty("name") String name) {
this.age = age;
this.name = name;
}

如果不使用JsonCreator,那么需要提供无参构造函数以及对应的setter方法

36、json序列化:SerializationFeature.FAIL_ON_EMPTY_BEANS的值默认为true,该属性的意思是,如果一个对象中没有任何的属性,那么在序列化的时候就会报错。如果设置mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS),那么序列化就不会报错了。在类上面加注解@JsonIgnoreProperties(ignoreUnknown = true) 也可以解决此错误

37、@JsonIgnoreProperties(value = {"name","age"}) 可以注解在类上面,意味着忽略了name和age属性,在序列化的时候,会忽略这两个属性,只序列化其他属性

38、@JsonIgnoreProperties(ignoreUnknown = true) 主要用在反序列化上。正常情况下,如果我们json串中有一些key值和我们的POJO对象不匹配,那么将会抛出异常。

比如json串中有个key名称为height222,pojo中字段为height111,反序列化就会抛异常。如果加上此注解则不会抛异常了。使用 mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 也可以达到同样的目的

39、@JsonSerialize:json序列化注解,用于字段或get方法上,作用于getter()方法,将java对象序列化为json数据

@JsonDeserialize:json反序列化注解,用于字段或set方法上,作用于setter()方法,将json数据反序列化为java对象

40、@JsonInclude:

JsonJsonInclude.Include.ALWAYS 这个是默认策略,任何情况下都序列化该字段,和不写这个注解是一样的效果。
JsonJsonInclude.Include.NON_NULL这个最常用,即如果加该注解的字段为null,那么就不序列化这个字段了。
JsonJsonInclude.Include.NON_EMPTY 这个属性包含NON_NULL,NON_ABSENT之后还包含如果字段为空也不序列化。这个也比较常用
JsonJsonInclude.Include.NON_DEFAULT 这个也好理解,如果字段是默认值的话就不序列化

public class Employee2 {
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private String name;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private String dept;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private Integer salary;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private boolean fullTime;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private List<String> phones;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private Date dateOfBirth;
}

public class ExampleMain2 {
public static void main(String[] args) throws IOException {
Employee2 employee = new Employee2();
employee.setName("Trish");
employee.setFullTime(false);
employee.setPhones(new ArrayList<>());
employee.setSalary(Integer.valueOf(0));
employee.setDateOfBirth(new Date(0));

ObjectMapper om = new ObjectMapper();
String jsonString = om.writeValueAsString(employee);
System.out.println(jsonString);
}
}

输出结果是{"name":"Trish"},因为Employee2的其他字段都是默认值

41、@RequestParam可以从request里面取出请求参数

如果是get,则@RequestParam可以取出url?后的参数,例如:?token=xxx,则后端用@RequestParam(value = "token")承接
如果是post,则@RequestParam可以取出curl -d或者--data-raw 指定的参数,如:
curl -v 'https://g-zt.snackvideo.com/rest/zt/captcha/sliding/config' \
--data-raw 'captchaSession=abc' \
--compressed
则后端用@RequestParam(value = "captchaSession")承接

除了用注解,server也可以用request.getParameter(“参数名”)取出请求参数

42、

@POST("/{indexes}/{type}/_search")
search(@Path("indexes") String indexes, @Path("type") String type, @Body RequestBody body);
@Path表示请求路径中的参数,@Body表示请求body

43、request.getParameter方法:接收post请求参数,发送端content-Type必须设置为application/x-www-form-urlencoded;否则会接收不到 

44、计算机器的qps:

单线程执行时间500ms 机器上有200线程
qps:1000 / 500 * 200 = 400

qps和并发数的计算关系:
单线程执行时间200ms,并发数300,qps = 1000 / 200 * 300 = 1500

45、Broken pipe分析

java.io.IOException: Broken pipe
Broken pipe产生原因分析
1.当访问某个服务突然服务器挂了,就会产生Broken pipe
2.客户端读取超时关闭了连接,这时服务器往客户端再写数据就发生了broken pipe异常!(如果线程池打满,线程都处于block状态,也会产生Broken pipe
,如果向serveletResponse中写入数据时没flush,可能导致response缓冲区一直没填满,导致客户端读取超时关闭连接,产生Broken pipe)

1.问题一分析服务器为什么挂了。
2.问题二使用jps/jstack分析线程栈,看是不是有线程阻塞。

46、数组转为流:Arrays.stream或者Stream.of

flatMap:即对流中每个元素进行平铺后,形成多个流合在一起

47、泛型中ResultView<?> 问号 表示赋值的类型不确定

48、map的computeIfAbsent和putIfAbsent

java computeIfAbsent:对hashMap中指定key的值进行重新计算,如果不存在这个key,则添加到hashMap中。如果存在这个key,则返回次key对应的value
HashMap<String, Integer> prices = new HashMap<>();
// 往HashMap中添加映射项
prices.put("Shoes", 200);
prices.put("Bag", 300);
prices.put("Pant", 150);
prices.computeIfAbsent("Shirt", key -> 280);
{Pant=150, Shirt=280, Bag=300, Shoes=200}

 

java putIfAbsent:如果所指定的key在HashMap中存在,返回和这个key对应的value, 如果所指定的key不在HashMap 中,则返回 null。
HashMap<Integer, String> sites = new HashMap<>();

// 往 HashMap 添加一些元素
sites.put(1, "Google");
sites.put(2, "Runoob");
sites.put(3, "Taobao");
// HashMap 不存在该key
sites.putIfAbsent(4, "Weibo");
sites.putIfAbsent(2, "Wiki");

此时map的结果为1=Google, 2=Runoob, 3=Taobao, 4=Weibo}

49、可以在类中定义Supplier,延迟加载。对于会消耗较多资源的对象:这不仅能够节省一些资源,同时也能够加快对象的创建速度,从而从整体上提升性能

private static final Supplier<PhoneNumberUtil> PHONE_NUMBER_UTIL_SUPPLIER = memoize(PhoneNumberUtil::getInstance);

50、把单个对象封装成list:Collections.singleton

51、ApplicationRunner接口:springboot中提供的,该接口中只有一个run方法,他执行的时机是:spring容器启动完成之后,就会紧接着执行这个接口实现类的run方法。在启动时候初始化一些信息 , 比如数据库连接 , 或者自定义的一些配置

52、ksboot yml指定服务启动端口:

server:
port: 8080

53、stream把list按字段聚合成map

Map<Integer, List<LiveBenefits>> type2List = allBenefits.stream().collect(Collectors.groupingBy(LiveBenefits::getType));

54、idea code style设置:https://blog.csdn.net/A_Java_Dog/article/details/115617705


posted @ 2023-06-25 17:28  MarkLeeBYR  阅读(51)  评论(0编辑  收藏  举报