进入新公司几个月,陆陆续续使用到了Java8的新技术,其中流使用的最多,在处理集合方面非常方便,下面是是我工作中常用到的Java8的功能。

Lambda表达式和forEach循环

1
2
3
4
5
6
7
if (CollectionUtils.isNotEmpty(prizes)) {
prizes.forEach(x -> {
if (PrizeType.BOOK.equals(x.getPrizeType())) {
books.add(getByActivityId(x.getPrizeId()));
}
});
}

当循环遍历的数据很多时(1000条以上),Java8中的for循环新能要强于普通的for循环。

集合创建

1
2
3
if (CollectionUtils.isEmpty(memberList)) {
return ImmutableList.of();
}

使用Guava的ImmutableList.of()创建的是不可变集合,这样有利于节省空间。

Java8常用的集合操作

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
//filter过滤
List<RedeemActivity> redeemActivitiesOfPrize = activities.stream()
.filter(x -> activityIdsOfPrize.contains(x.getId())).collect(Collectors.toList());
//使用流降序排序
userCOS.stream() .sorted(Comparator.comparing(userCO::getCreateDate).reversed()).collect(Collectors.toList());
//通过昵称获取userId列表
List<String> userIds = users.stream().collect(() -> new ArrayList<String>(), (list, user) -> list.add(user.getId()), (list1, list2) -> list1.addAll(list2));
List<String> orderNos = orderStatus.stream().map(OrderDetail::getOrderNo).collect(toList());
//Optional.ofNullable使用
List<CommodityActivityRule> excludedCommodityActivityRules = Optional.ofNullable(commodityActivityRules)
.orElseGet(ArrayList::new).stream()
// 排除当前活动
.filter(commodityActivityRule -> !commodityActivityRule.getActivity().getId().equals(activityId))
.collect(Collectors.toList());
//对象不为null时使用of,对象可能为null也可能不为null时用ofNullable
//orElseGet:对象不为null不会重新创建;orElse:对象为不为null也会重新创建
Optional.of(marketingConfigRepository.listAll(new MarketingConfig())).orElseGet(ArrayList::new).stream()
.filter(marketingConfig -> excludedMarketingConfigTypes.contains(marketingConfig.getType()))
.map(MarketingConfig::getId).collect(Collectors.toList());
//返回对象的时候可以用
Optional.ofNullable(usageRules).orElseGet(ArrayList::new)
//BigDecimal累加
BigDecimal commodityAmount = orderDetails.stream().map(OrderDetail::getCommodityAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
//判断Optional里面是否有值
Optional<GradeThresholdInfoCO> nextOptional = gradeThresholdList.stream().filter(x -> x.getLevel() != null && x.getLevel() == level + 1).findFirst();
if (nextOptional.isPresent()) {
return nextOptional.get();
}
//findFirst()
List<Cookie> targetCookies = Optional.ofNullable(cookies).orElseGet(ArrayList::new).stream()
.filter(e -> "jsessionid".equalsIgnoreCase(e.getName())).collect(Collectors.toList());
log.info("Cookie名称为:{}的值为:{}", "jsessionid",
Optional.ofNullable(targetCookies).orElseGet(ArrayList::new).get(0).getValue());
Optional<Cookie> first = Optional.ofNullable(cookies).orElseGet(ArrayList::new).stream()
.filter(e -> "jsessionid".equalsIgnoreCase(e.getName())).findFirst();
if (first.isPresent()) {
log.info("Cookie名称为:{}的值为:{}", "jsessionid",
first.get().getValue());
}
//流大小比较
Optional<Optional<Integer>> maxLevelOptional = ruleList.stream().map(x -> x.getEarningRuleMap().keySet().stream().max((o1, o2) -> o1.compareTo(o2))).max((o1, o2) -> {
Integer value1 = o1.isPresent() ? o1.get() : 0;
Integer value2 = o2.isPresent() ? o2.get() : 0;
return value1.compareTo(value2);
});
//日期获取最值(最大,最小)
Optional<ActivityVO> max = activityVOS.stream().max(Comparator.comparing(ActivityVO::getEndDate));
Optional<ActivityVO> min = activityVOS.stream().min(Comparator.comparing(ActivityVO::getStartDate));
Date maxEndDate = max.get().getEndDate();
Date minStartDate = min.get().getStartDate();
//groupingBy分组1
Map<PrizeType, List<RedeemActivityPrize>> prizeTypeAndPrizesMap = redeemActivityPrize.stream().collect(Collectors.groupingBy(RedeemActivityPrize::getPrizeType));
List<RedeemActivityPrize> couponPrizes = prizeTypeAndPrizesMap.get(PrizeType.COUPON);
List<RedeemActivityPrize> presentPrizes = prizeTypeAndPrizesMap.get(PrizeType.PRESENT);
//groupingBy分组2
prizes.stream().collect(Collectors.groupingBy(RedeemActivityPrize::getPrizeId))
.forEach((prizeId, activityPrizes) -> {
List<String> activityIdsOfPrize = activityPrizes.stream()
.map(RedeemActivityPrize::getRedeemActivityId).collect(Collectors.toList());
List<RedeemActivity> redeemActivitiesOfPrize = activities.stream()
.filter(x -> activityIdsOfPrize.contains(x.getId())).collect(Collectors.toList());
List<RedeemActivityBriefCO> briefCOS = ModelConvertorHelper.convertList(redeemActivitiesOfPrize,
RedeemActivityBriefCO.class);
RedeemUsedPresentCO co = new RedeemUsedPresentCO();
co.setPresentId(prizeId);
co.setActivities(briefCOS);
result.add(co);
});
//Java8 Function函数的使用
//T-入参类型,R-出参类型
private static <T, R> List<R> transform(List<T> list, Function<T, R> fx) {
List<R> result = new ArrayList<>();
for (T element : list) {
result.add(fx.apply(element));
}
return result;
}
List<Integer> namesLength = transform(names, String::length);
//集合添加..
Stream.of(task1, task2, task3, task4, task5).collect(toList())
//显示前几位的集合数据
tasks.stream().filter(task -> task.getType() == TaskType.READING).sorted(comparing(Task::getCreatedOn)).map(Task::getTitle).
limit(n).collect(toList());
//Java8循环遍历
couponIds.forEach(x -> {
RedeemActivityPrize presentRedeem = new RedeemActivityPrize();
presentRedeem.setRedeemActivityId(redeemActivityId);
presentRedeem.setPrizeType(PrizeType.COUPON);
presentRedeem.setPrizeId(x);
redeemActivityPrizeList.add(presentRedeem);
});

Spring创建对象

1
2
private final static ActivityRepository redeemActivityRepository = SpringContextHolder
.getBean(ActivityRepository.class);

除了@Autowired生成对象,Spring其他生成对象的方式。

BigDecimal使用注意

1
2
3
你可能认为java中用new BigDecimal(0.1)创建的BigDecimal应该等于0.1(一个是1的无精度的值,一个是有精度的值),但实际上精确的是等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能被double精确的表示(下面大概描述一下原理)。因此,传入构造函数的值不是精确的等于0.1。
当遇到需要涉及到精确计算的时候,如上面代码所示,要注意该构造函数是一个精确的转换,它无法得到与先调用Double.toString(double)方法将double转换成String,再使用BigDecimal(String)构造函数一样的结果。如果要达到这种结果,应该使用new BigDecimal(String value) 或 BigDecimal.valueof(double value)

使用SecureRandom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
由于java.util.Random类依赖于伪随机数生成器,因此该类和相关的java.lang.Math.random()方法不应用于安全关键应用程序或保护敏感数据。 在这种情况下,应该使用依赖于加密强随机数生成器(RNG)的java.security.SecureRandom类。
PRNG(伪随机数):
伪随机数, 计算机不能生成真正的随机数,而是通用一定的方法来模拟随机数。伪随机数有一部分遵守一定的规律,另一部分不遵守任何规律。
RNG(随机数):
随机数是由“随机种子”产生的,“随机种子”是一个无符号整形数。
反例:
Random random = new Random(); // Questionable use of Random
byte bytes[] = new byte[20];
random.nextBytes(bytes);
正例:
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];

Java8 List转Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//1.这里有个实体对象(员工对象)
public class Employee {
// member variables
private int empId;
private String empName;
private int empAge;
private String empDesignation;
//2.比如式样员工对象的empId作为key,值是员工姓名
Map<Integer, String> mapOfEmployees = employees.stream().collect(
Collectors.toMap(e -> e.getEmpId(),e -> e.getEmpName()));
//3.Map的Key是empId,整个对象为Map的值,但如果List中有重复的empId,映射到Map时,Key时不能重复的
Map<Integer, String> mapOfEmployees = employees.stream().collect(
Collectors.toMap(
e -> e.getEmpId(),
e -> e.getEmpName(),
(e1, e2) -> e1 )); // Merge Function
//4.将List转换为Map - 使用TreeMap对键进行自然排序
Map<Integer, String> mapOfEmployees = employees.stream().collect(
Collectors.toMap(
e -> e.getEmpId(),
e -> e.getEmpName(),
(e1, e2) -> e1 , // Merge Function
TreeMap<Integer, String>::new)); // Map Supplier
//如果你的TreeMap实现需要加入比较器,将上面代码中TreeMap<Integer, String>::new替换成:() -> new TreeMap<Integer, String>(new MyComparator())