Stream实战用例1
Java8 Stream 代码少,功能强大,实乃效率利器。这里我列举自己常用的Stream使用示例。
一.流式赋值
1. 从一个List转到另一个List
objectList = objectList .stream().map(object -> {
Object objectNew = new Object();
BeanUtils.copyProperties(object, objectNew);
objectNew.setVar("Value");
return objectNew;
}).collect(Collectors.toList());
2. 简单赋值
// 单个
objectList.forEach(object -> object.setVar("Value"));
// 多个
objectList.forEach(object -> {
object.setVar("Value");
object.setVar2("dfsfsd");
});
二.统计计算
// BigDecimal求和
public static void main(String[] args) {
List<Invoice> invoices = Arrays.asList(
new Invoice("I1001", BigDecimal.valueOf(9.99), BigDecimal.valueOf(1)),
new Invoice("I1002", BigDecimal.valueOf(19.99), BigDecimal.valueOf(1.5)),
new Invoice("I1003", BigDecimal.valueOf(4.888), BigDecimal.valueOf(2)),
new Invoice("I1004", BigDecimal.valueOf(4.99), BigDecimal.valueOf(5)),
new Invoice("I1005", BigDecimal.valueOf(.5), BigDecimal.valueOf(2.3))
);
//增加非空校验
BigDecimal sum = invoices.stream()
.map(x -> x.getQty().multiply(x.getPrice())) // map
.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); // reduce
System.out.println(sum); // 75.851
System.out.println(sum.setScale(2, RoundingMode.HALF_UP)); // 75.85
}
// 计数
long count = ls.stream().filter(s -> s.length() == 3).count();
3. 自定义Predicate进行复杂逻辑filter
复杂的逻辑过滤,可以写一个谓语判断
Predicate<TestObject> showIndicatorPre = adjustByCityUtil -> {
boolean isShow = false;
BigDecimal score = adjustByCityUtil.getScore();
BigDecimal benchmarkScore = adjustByCityUtil.getBenchmarkScore();
String scoreAdjustReason = adjustByCityUtil.getScoreAdjustReason();
if( score != null) {
if (benchmarkScore != null) {
isShow = !(benchmarkScore.compareTo(score) == 0);
} else if (StringUtils.isNotBlank(scoreAdjustReason)) {
isShow = true;
}
}
return isShow;
};
List<TestObject> adjustByCityUtils = entry.getValue();
if(CollectionUtils.isNotEmpty(adjustByCityUtils)) {
List<TestObject> collect = adjustByCityUtils.stream().filter(showIndicatorPre).collect(Collectors.toList());
entry.setValue(collect);
}
...
4.List转Map
@Data
public class Person {
private Integer idNum;
private String name;
private Integer age;
}
List<Person> personList = Arrays.asList(
new Person(1, "Jack", 3),
new Person(2, "Mary", 4),
new Person(3, "Harry", 6),
new Person(4, "Ali", 6)
);
// 4.0 只需要List中的两个元素,一个作key,一个为value
Map<Integer,String> testMap = personList .stream()
.collect(Collectors.toMap(Person::getIdNum, Person::getName));
// List每个元素的key不相同,value是一个列表中的一个元素
Map<String, Person> testMap2 = personList .stream()
.collect(Collectors.toMap(Person::getName, a -> a, (k1, k2) -> k1));
// List中的 key有相同的,value是一个List,将 同Key的进行分组
// 1. 不保持查询顺序的分组
Map<Integer, List<Person>> personSameAgeMap = personList .stream()
.collect(Collectors.groupingBy(Person::getAge));
// 2. 保持查询顺序的分组
使用LinkedHashMap来保证Map中的Key的先后顺序与在List中的先后顺序保持一致
LinkedHashMap<String, List<Person>> personSameAgeMap2= personList.stream()
.collect(Collectors.groupingBy(Person::getAge, LinkedHashMap::new, Collectors.toList()));
BTW:
List转Map主要是为了搜索匹配方便,从n的复杂度变成1的复杂度。
组织形式变了,但是里面元素还是没变,因此对Map中任何一个元素的值的修改,
都会永久的修改,无论是List,还是在Map中。
5.遍历搜索查看列表中是否有任何一个符合的数据
● filter 搭配 findAny(findFirst) 搭配 isPresent()
/**
* 判断每列表中是否有大于6岁的人
* @param indicatorCityScoreList
* @return
*/
private boolean validateAllPersonAgeIsLargerThanTwo(List<Person> personList) {
Optional<Person> any = personList.stream()
.filter(i -> (i.getAge() > 6)).findAny();
if(any.isPresent()) {
return false;
}
return true;
}
未完待续。。。