forked from HappySnailSunshine/JavaInterview
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUtils.md
More file actions
3361 lines (2051 loc) · 99.8 KB
/
Copy pathUtils.md
File metadata and controls
3361 lines (2051 loc) · 99.8 KB
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Utils
> 这一部分内容是一些比较碎的知识,有常用工具类,
## 目录
[TOC]
# BigDecimal
## 为什么要用这个?
既然要处理小数用 double 不可以吗,为什么要用这个?
**个人理解:**
- 不用double是因为在计算类似金额等要求精度非常高的数据是,double不精确。
- 由于我已经工作了一段时间了,对实际企业开发有了一些理解,我以前做过一个交易所项目,里面有很多钱的交易,有金额,冻结金额等等很多,工程款,缴纳金额,欠费金额等,每一分钱都不能少,所以需要一个精度很高的类型来记录金额。
> 参考:https://www.cnblogs.com/zhangyinhua/p/11545305.html
>
> https://blog.csdn.net/haiyinshushe/article/details/82721234
## Bigdecimal 初始化
**推荐用字符串初始化**
这里对比了两种形式,第一种直接value写数字的值,第二种用string来表示
```java
BigDecimal num1 = new BigDecimal(0.005);
BigDecimal num2 = new BigDecimal(1000000);
BigDecimal num3 = new BigDecimal(-1000000);
//尽量用字符串的形式初始化
BigDecimal num12 = new BigDecimal("0.005");
BigDecimal num22 = new BigDecimal("1000000");
BigDecimal num32 = new BigDecimal("-1000000");
```
## BigDecimal的加减乘除运算:
我们对其进行加减乘除绝对值的运算
我这里承接上面初始化Bigdecimal分别用string和数进行运算对比
```java
//加法
BigDecimal result1 = num1.add(num2);
BigDecimal result12 = num12.add(num22);
//减法
BigDecimal result2 = num1.subtract(num2);
BigDecimal result22 = num12.subtract(num22);
//乘法
BigDecimal result3 = num1.multiply(num2);
BigDecimal result32 = num12.multiply(num22);
//绝对值
BigDecimal result4 = num3.abs();
BigDecimal result42 = num32.abs();
//除法
BigDecimal result5 = num2.divide(num1,20,BigDecimal.ROUND_HALF_UP);
BigDecimal result52 = num22.divide(num12,20,BigDecimal.ROUND_HALF_UP);
```
从上到下分别输出:
```java
加法用value结果:1000000.005000000000000000104083408558608425664715468883514404296875
加法用string结果:1000000.005
减法value结果:-999999.994999999999999999895916591441391574335284531116485595703125
减法用string结果:-999999.995
乘法用value结果:5000.000000000000104083408558608425664715468883514404296875000000
乘法用string结果:5000.000
绝对值用value结果:1000000
绝对值用string结果:1000000
除法用value结果:199999999.99999999583666365766
除法用string结果:200000000.00000000000000000000
```
这里出现了差异,这也是为什么初始化建议使用string的原因。
### 注意
1)System.out.println()中的数字默认是double类型的,double类型小数计算不精准。
2)使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的!
因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。这一点在BigDecimal类的构造方法注释中有说明。
完整的test代码如下:
```java
import java.math.BigDecimal;
import java.util.Scanner;
public class TestThree {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal(0.005);
BigDecimal num2 = new BigDecimal(1000000);
BigDecimal num3 = new BigDecimal(-1000000);
//尽量用字符串的形式初始化
BigDecimal num12 = new BigDecimal("0.005");
BigDecimal num22 = new BigDecimal("1000000");
BigDecimal num32 = new BigDecimal("-1000000");
//加法
BigDecimal result1 = num1.add(num2);
BigDecimal result12 = num12.add(num22);
//减法
BigDecimal result2 = num1.subtract(num2);
BigDecimal result22 = num12.subtract(num22);
//乘法
BigDecimal result3 = num1.multiply(num2);
BigDecimal result32 = num12.multiply(num22);
//绝对值
BigDecimal result4 = num3.abs();
BigDecimal result42 = num32.abs();
//除法
BigDecimal result5 = num2.divide(num1,20,BigDecimal.ROUND_HALF_UP);
BigDecimal result52 = num22.divide(num12,20,BigDecimal.ROUND_HALF_UP);
System.out.println("加法用value结果:"+result1);
System.out.println("加法用string结果:"+result12);
System.out.println("减法value结果:"+result2);
System.out.println("减法用string结果:"+result22);
System.out.println("乘法用value结果:"+result3);
System.out.println("乘法用string结果:"+result32);
System.out.println("绝对值用value结果:"+result4);
System.out.println("绝对值用string结果:"+result42);
System.out.println("除法用value结果:"+result5);
System.out.println("除法用string结果:"+result52);
}
}
```
### 乘法
#### 保留两位小数
```java
//价税合计金额=金额+金额*税率 这里填负数(且保留两位小数) 这里不用计算啦 保存之前计算过啦
BigDecimal bigDecimal = new BigDecimal("65.4067");
BigDecimal bigDecimal2 = bigDecimal.setScale(2,BigDecimal.ROUND_HALF_UP);
System.out.println(bigDecimal2);
```
### 除法
**除法divide() 参数使用:**
使用除法函数在divide的时候要设置各种参数,要精确的小数位数和舍入模式,不然会出现报错
我们可以看到divide函数配置的参数如下
**即为 (BigDecimal divisor 除数, int scale 精确小数位, int roundingMode 舍入模式)**
可以看到舍入模式有很多种BigDecimal.ROUND_XXXX_XXX, 具体都是什么意思呢?
计算1÷3的结果(最后一种ROUND_UNNECESSARY在结果为无限小数的情况下会报错)
#### 八种舍入模式解释如下
1、ROUND_UP
舍入远离零的舍入模式。
在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。
注意,此舍入模式始终不会减少计算值的大小。
2、ROUND_DOWN
接近零的舍入模式。
在丢弃某部分之前始终不增加数字(从不对舍弃部分前面的数字加1,即截短)。
注意,此舍入模式始终不会增加计算值的大小。
3、ROUND_CEILING
接近正无穷大的舍入模式。
如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;
如果为负,则舍入行为与 ROUND_DOWN 相同。
注意,此舍入模式始终不会减少计算值。
4、ROUND_FLOOR
接近负无穷大的舍入模式。
如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;
如果为负,则舍入行为与 ROUND_UP 相同。
注意,此舍入模式始终不会增加计算值。
5、ROUND_HALF_UP
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。
如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。
注意,这是我们大多数人在小学时就学过的舍入模式(四舍五入)。
6、ROUND_HALF_DOWN
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。
如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同(五舍六入)。
7、ROUND_HALF_EVEN
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;
如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。
此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。
如果前一位为奇数,则入位,否则舍去。
以下例子为保留小数点1位,那么这种舍入方式下的结果。
1.15>1.2 1.25>1.2
8、ROUND_UNNECESSARY
断言请求的操作具有精确的结果,因此不需要舍入。
如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。
## BigDecimal转换成int
```java
BigDecimal b=new BigDecimal(45.45);
int a = b.intValue();
```
## BigDecima比较大小
```java
BigDecimal a = new BigDecimal (101);
BigDecimal b = new BigDecimal (111);
//使用compareTo方法比较
//注意:a、b均不能为null,否则会报空指针
if(a.compareTo(b) == -1){
System.out.println("a小于b");
}
if(a.compareTo(b) == 0){
System.out.println("a等于b");
}
if(a.compareTo(b) == 1){
System.out.println("a大于b");
}
if(a.compareTo(b) > -1){
System.out.println("a大于等于b");
}
if(a.compareTo(b) < 1){
System.out.println("a小于等于b");
}
```
## BigDecima 判断是否为0
**1.我之前用来判断Bigdecimal类型是否等于0的方法**
```java
equals(BigDecimal.ZERO)
```
用equals方法和BigDecimal.ZERO进行比较。
**2.上面方法存在的问题**
有一天,调用这个这句代码的时候,传入的确实是0,但却返回false
查看源代码发现:
Bigdecimal的equals方法不仅仅比较值的大小是否相等,首先比较的是scale(scale是bigdecimal的保留小数点位数,比如 new
Bigdecimal("1.001"),scale为3),也就是说,不但值得大小要相等,保留位数也要相等,equals才能返回true。
Bigdecimal b = new Bigdecimal("0") 和 Bigdecimal c = new Bigdecimal("0.0"),用equals比较,返回就是false。
Bigdecimal.ZERO的scale为0。
所以,用equals方法要注意这一点。
**3.用b.compareTo(BigDecimal.ZERO)==0,可以比较是否等于0,返回true则等于0,返回false,则不等于0**
# 各种基本类型相互转换
## Short 转换为Integer
```java
Integer number = Integer.valueOf(orderGoods.getNumber());
```
## Double转换为long,int,float,byte,short
```java
System.out.println(new Double(3.5).longValue());
System.out.println(new Double(3.5).intValue());
System.out.println(new Double(3.5).floatValue());
System.out.println(new Double(3.5).byteValue());
System.out.println(new Double(3.5).shortValue());
```
结果:
```java
3
3
3.5
3
3
```
## 将Double转换为long(亲测有效)
```java
@Test
public void test6(){
Double d = 11.91;
Long l = Math.round(d); //首先四舍五入 去掉小数后位数
String str = String.valueOf(l);
System.out.println(str);
Long ll = Long.parseLong(str);
System.out.println(ll);
}
@Test
public void test7(){
Double d = 11.91;
String str = String.valueOf(d); //首先转换为string类型
System.out.println(str);
Long ll = new Double(str).longValue(); //然后将str转换为double类型,再用Double的方法,将其转换为long类型
System.out.println(ll);
}
```
# 时间类相关
## LocalDateTime
商城项目目前用的是这个当前时间:
```
orderGoods.setAddTime(LocalDateTime.now());
```
LocalDateTime Java.time 处理时间的新类
处理日期 计算天数,推荐java.time 包 或者 org.joda
https://blog.csdn.net/wsywb111/article/details/86543637
### 时间戳和日期转换:
```java
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
/**
* 时间戳转换成日期格式字符串
* @param seconds 精确到秒的字符串
* @param formatStr
* @return
*/
public static String timeStamp2Date(String seconds,String format) {
if(seconds == null || seconds.isEmpty() || seconds.equals("null")){
return "";
}
if(format == null || format.isEmpty()){
format = "yyyy-MM-dd HH:mm:ss";
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(new Date(Long.valueOf(seconds+"000")));
}
/**
* 日期格式字符串转换成时间戳
* @param date 字符串日期
* @param format 如:yyyy-MM-dd HH:mm:ss
* @return
*/
public static String date2TimeStamp(String date_str,String format){
try {
SimpleDateFormat sdf = new SimpleDateFormat(format);
return String.valueOf(sdf.parse(date_str).getTime()/1000);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 取得当前时间戳(精确到秒)
* @return
*/
public static String timeStamp(){
long time = System.currentTimeMillis();
String t = String.valueOf(time/1000);
return t;
}
public static void main(String[] args) {
String timeStamp = timeStamp();
System.out.println("timeStamp="+timeStamp); //运行输出:timeStamp=1470278082
System.out.println(System.currentTimeMillis());//运行输出:1470278082980
//该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数
String date = timeStamp2Date(timeStamp, "yyyy-MM-dd HH:mm:ss");
System.out.println("date="+date);//运行输出:date=2016-08-04 10:34:42
String timeStamp2 = date2TimeStamp(date, "yyyy-MM-dd HH:mm:ss");
System.out.println(timeStamp2); //运行输出:1470278082
}
}
```
Pgsql 需要根据时间段查创建时间是否在这个范围内:
```xml
//济宁报装这么写的
<if test="startDate != null and startDate != ''">
and to_char(create_at,'yyyy-MM-dd') <![CDATA[>=]]> #{startDate}
</if>
<if test="endDate != null and endDate != ''">
and to_char(create_at,'yyyy-MM-dd') <![CDATA[<=]]> #{endDate}
</if>
<if test="startMonth != null and startMonth != ''">
and to_char(create_at,'yyyy-MM') <![CDATA[>=]]> #{startMonth}
</if>
<if test="endMonth != null and endMonth != ''">
and to_char(create_at,'yyyy-MM') <![CDATA[<=]]> #{endMonth}
</if>
```
### 字符串和时间的转换
```java
//1.把日期转换成字符串
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test01 {
public static void main(String[] args) {
Date date = new Date(); //获取当前时间
System.out.println(date.getClass().getName()); //打印date数据类型
System.out.println(date); //打印当前时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sdf.format(date); //将Date类型转换成String类型
System.out.println(format.getClass().getName());//打印format数据类型
System.out.println(format); //打印当前时间
}
}
结果:
java.util.Date
Tue Dec 26 19:31:48 CST 2017
java.lang.String
2017-12-26 19:31:48
//2,把字符串转换成日期
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test01 {
public static void main(String[] args) {
String time = "1994-11-24 07:11:24";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date = sdf.parse(time);
System.out.println(date);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
Thu Nov 24 07:11:24 CST 1994
//3.对日期加减操作,获得之前,之后的时间。
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
long dateTime = date.getTime(); //将date类型转换成long类型进行计算
System.out.println(sdf.format(date)); //以字符串打印当前时间
long time = (60*60+5)*1000; //60个60分钟加5分钟,乘以1000,一小时零五分转换成毫秒
dateTime = dateTime + time; //将当前时间加上一小时零五分
System.out.println(sdf.format(new Date(dateTime))); //打印一小时零五分之后的时间
}
}
结果:
2018-01-07 08:52:21
2018-01-07 09:52:26
```
## 用时间年月日时分秒生成id
```java
//工单编号 年月日 时分秒
Date data = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String code = simpleDateFormat.format(data);
```
参考:https://blog.csdn.net/qq_35077107/article/details/100898877?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-1
https://www.cnblogs.com/zhengchenhui/p/6076442.html
# 日志相关
```java
private final Log logger = LogFactory.getLog(OrderJob.class);
logger.info("系统开启定时任务检查订单是否已经超期自动确认收货");
```
如果不想每次写代码的时候都写下面这句,**可以用注解@Slf4j;**
```java
private final Logger logger = LoggerFactory.getLogger(当前类名.class);
```
这个注解是lombok里面的注解,是可以少写一些代码。用这个 还需要在idea里面装lombok插件。
导入依赖
```xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version><!--版本号自己选一个就行-->
</dependency>
```
然后就可以直接用啦:
```java
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_Ok(@PathVariable("id") Integer id){ //这里的@PathVariable("id")意思是获取上面的路径中的id
String result = paymentService.paymentInfo_OK(id);
log.info("*******result:" + result);
return result;
}
}
```
参考:https://www.jianshu.com/p/6e137ee836a1
# 数据库相关
## bean 数据库和bean不对应
```java
@TableField(exist = false) //注解
```
## 数据库加锁
修改订单状态 加锁 乐观锁 避免 同时请求 修改数据库错误
```java
order.setOrderStatus(OrderUtil.STATUS_REFUND);
if (orderService.updateWithOptimisticLocker(order) == 0) {
return ResponseUtil.updatedDateExpired();
}
```
# 加密相关
## MD5
```java
String pwd = SecureUtil.md5( StrUtil.addSuffixIfNot( password, AppConst.PASSWORD_ENCRYPTION));
```
## 验证电话号码,邮箱
```java
//发送验证码 判断是否是合适的电话号码
Object object = AuthUtils.isOkMobile(phoneNumber);
if (object != null){
return object;
}
//发送验证码 判断是否是合适的邮箱
Object object = AuthUtils.isOkEmail(email);
if (object != null){
return object;
}
//检查验证码
Object object = AuthUtils.checkCode(captcha,code);
if (object != null) {
return object;
}
//检查邮箱是否注册
Object emailRegistered = AuthUtils.checkEmailRegistered(litemallUser,email);
if (emailRegistered != null) {
return emailRegistered;
}
//检查电话号码是否注册
Object mobileRegistered = AuthUtils.checkMobileRegistered(litemallUser,mobile);
if (mobileRegistered != null) {
return mobileRegistered;
}
```
# Hutool
集合工具类:
文档 : http://hutool.mydoc.io/#text_319437
1.集合是创建
```java
List<Map> rows = CollectionUtil.newArrayList();
```
2.密码加密
```java
user.setPassword(SecureUtil.md5(StrUtil.addSuffixIfNot(dto.getPassword(), BizConst.BIZ_SECRET_CODE)));
```
# Guava
谷歌下面的一个类库 很强大,里面有很多方法 好像还挺强大 学一下
参考:http://ifeve.com/google-guava/ 这个好
参考:https://www.cnblogs.com/wwxzdl/p/11150907.html
## 1. 基本工具 [Basic utilities]
让使用Java语言变得更舒适
1.1 [使用和避免null](http://ifeve.com/using-and-avoiding-null/):null是模棱两可的,会引起令人困惑的错误,有些时候它让人很不舒服。很多Guava工具类用快速失败拒绝null值,而不是盲目地接受
1.2 [前置条件](http://ifeve.com/google-guava-preconditions/): 让方法中的条件检查更简单
1.3 [常见Object方法](http://ifeve.com/google-guava-commonobjectutilities/): 简化Object方法实现,如hashCode()和toString()
1.4 [排序: Guava强大的”流畅风格比较器”](http://ifeve.com/google-guava-ordering/)
1.5 [Throwables](http://ifeve.com/google-guava-throwables/):简化了异常和错误的传播与检查
## 2. 集合[Collections]
Guava对JDK集合的扩展,这是Guava最成熟和为人所知的部分
2.1 [不可变集合](http://ifeve.com/google-guava-immutablecollections/): 用不变的集合进行防御性编程和性能提升。
2.2 [新集合类型](http://ifeve.com/google-guava-newcollectiontypes/): multisets, multimaps, tables, bidirectional maps等
2.3 [强大的集合工具类](http://ifeve.com/google-guava-collectionutilities/): 提供java.util.Collections中没有的集合工具
2.4 [扩展工具类](http://ifeve.com/google-guava-collectionhelpersexplained/):让实现和扩展集合类变得更容易,比如创建`Collection的装饰器,或实现迭代器`
## 3. [缓存](http://ifeve.com/google-guava-cachesexplained)[Caches]
Guava Cache:本地缓存实现,支持多种缓存过期策略
## 4. [函数式风格](http://ifeve.com/google-guava-functional/)[Functional idioms]
Guava的函数式支持可以显著简化代码,但请谨慎使用它
## 5. 并发[Concurrency]
强大而简单的抽象,让编写正确的并发代码更简单
5.1 [ListenableFuture](http://ifeve.com/google-guava-listenablefuture/):完成后触发回调的Future
5.2 [Service框架](http://ifeve.com/google-guava-serviceexplained/):抽象可开启和关闭的服务,帮助你维护服务的状态逻辑
## 6. [字符串处理](http://ifeve.com/google-guava-strings/)[Strings]
非常有用的字符串工具,包括分割、连接、填充等操作
## 7. [原生类型](http://ifeve.com/google-guava-primitives/)[Primitives]
扩展 JDK 未提供的原生类型(如int、char)操作, 包括某些类型的无符号形式
## 8. [区间](http://ifeve.com/google-guava-ranges/)[Ranges]
可比较类型的区间API,包括连续和离散类型
## 9. [I/O](http://ifeve.com/google-guava-io/)
简化I/O尤其是I/O流和文件的操作,针对Java5和6版本
## 10. [散列](http://ifeve.com/google-guava-hashing/)[Hash]
提供比`Object.hashCode()`更复杂的散列实现,并提供布鲁姆过滤器的实现
## 11. [事件总线](http://ifeve.com/google-guava-eventbus/)[EventBus]
发布-订阅模式的组件通信,但组件不需要显式地注册到其他组件中
## 12. [数学运算](http://ifeve.com/google-guava-math/)[Math]
优化的、充分测试的数学工具类
## 13. [反射](http://ifeve.com/guava-reflection/)[Reflection]
Guava 的 Java 反射机制工具类
## 限流
在学习秒杀的时候,用到限流的知识,用到这里面的一个类Ratelimiter
参考:https://ifeve.com/guava-ratelimiter/ 这里面是令牌桶算法
其他限流操作:
参考:https://zhuanlan.zhihu.com/p/71721495
https://www.zhihu.com/question/65502802
# Lombok
idea中需要安装插件lombok
## 1 Lombok背景介绍
官方介绍如下:
```
Project Lombok makes java a spicier language by adding 'handlers' that know how to build and compile simple, boilerplate-free, not-quite-java code.
```
大致意思是Lombok通过增加一些“处理程序”,可以让java变得简洁、快速。
## 2 Lombok使用方法
Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。
Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。
Lombok的使用跟引用jar包一样,可以在官网(https://projectlombok.org/download)下载jar包,也可以使用maven添加依赖:
```
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
```
接下来我们来分析Lombok中注解的具体用法。
### 2.1 @Data
**这个最牛皮,加了这个注解以后,就不再需要setter和getter方法啦!**
@Data注解在类上,会为类的所有属性自动生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
官方实例如下:
```java
import lombok.AccessLevel;
import lombok.Setter;
import lombok.Data;
import lombok.ToString;
@Data
public class DataExample {
private final String name;
@Setter(AccessLevel.PACKAGE) private int age;
private double score;
private String[] tags;
@ToString(includeFieldNames=true)
@Data(staticConstructor="of")
public static class Exercise<T> {
private final String name;
private final T value;
}
}
```
如不使用Lombok,则实现如下:
```java
import java.util.Arrays;
public class DataExample {
private final String name;
private int age;
private double score;
private String[] tags;
public DataExample(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
public void setScore(double score) {
this.score = score;
}
public double getScore() {
return this.score;
}
public String[] getTags() {
return this.tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
@Override
public String toString() {
return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";
}
protected boolean canEqual(Object other) {
return other instanceof DataExample;
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof DataExample)) return false;
DataExample other = (DataExample) o;
if (!other.canEqual((Object)this)) return false;
if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
if (this.getAge() != other.getAge()) return false;
if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
return true;
}
@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final long temp1 = Double.doubleToLongBits(this.getScore());
result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());