Stream流的应用
插入一个题外知识:Optional类
1、去重
1、按照对象的某个属性去重
1)借助工具类实现
//去重工具类
public class StreamEx {
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}
//实现,result类型为List<Map<String, Object>>,后文同,不再复述
result = list.stream().filter(StreamEx.distinctByKey(x -> x.get("code"))).collect(Collectors.toList());
2)普通去重
result = list.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(
Comparator.comparing(e -> e.get("accountCount"))
)), ArrayList::new));
2、按照对象的多个属性去重
//根据list对象的ruleCode,和version去重
result = list.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(e -> e.get("ruleCode") + "#" + e.getString("version")))), ArrayList::new));
2、提取某个字段成为新的list
// 数据说明:data类型为List<Map<String, Object>>
// 功能说明:提取data中的bizCode字段成为一个新的list,且避免了空指针问题
List<String> bizCodeList = Optional.ofNullable(data.getString("bizCode"))
.map(bizCode -> Arrays.asList(bizCode.split(",")))
.orElse(Collections.emptyList());
3、字段求和
// 数据说明:data类型为List<Map<String, Object>>,bizCodeList为List<String>
// 功能说明:去除esData集合中各条属性不包含于bizCodeList的数据,然后将剩下的数据取出transCnt字段进行累加求和,如果transCnt字段为空则赋值0
int totalTransCnt = data.stream()
.filter(es -> bizCodeList.contains(es.getString("bizCode")))
.mapToInt(es -> Optional.ofNullable(es.getInteger("transCnt")).orElse(0))
.sum();
4、求最大/最长/最小/最短/符合条件个数
// 求list中最长的元素(最短把max换成min即可,下面相同)
List<String> list1 = Arrays.asList("tigger", "lion", "dog", "panda", "giraffe");
Optional<String> maxLength = list1.stream().max(Comparator.comparing(String::length));
System.out.println("list中最长的元素为:" + maxLength.get());
// 求list中最大的元素
List<Integer> list2 = Arrays.asList(1, 5, 10, 9, 102, 58);
Optional<Integer> max = list2.stream().max(Comparator.comparing(Integer::intValue));
System.out.println("list中最大的元素为:" + max.get());
// 求list中比5大的个数
long count = list2.stream().filter(e -> e > 5).count();
System.out.println("list比5大的元素个数有:" + count + "个");
5、求和、求乘积、求最值
// list类型List<Map<String, Object>>
// 求和、求乘积、求最值
Optional<Integer> sum1 = list.stream().map(e -> e.getInteger("salary")).reduce((a, b) -> a + b);
Optional<Integer> sum2 = list.stream().map(e -> e.getInteger("salary")).reduce(Integer::sum);
Optional<Integer> product = list.stream().map(e -> e.getInteger("salary")).reduce((x, y) -> x * y);
Optional<Integer> max1 = list.stream().map(e -> e.getInteger("salary")).reduce(Integer::max);
Optional<Integer> max2 = list.stream().map(e -> e.getInteger("salary")).reduce((x, y) -> x > y ? x : y);
6、排序
//数据说明:data为List<Map<String, Object>>,QueryData为Map<String, Object>
//升序
data.stream().sorted(Comparator.comparing(e -> e.getInteger("count"), Comparator.naturalOrder())).collect(Collectors.toList());
//降序
data.stream().sorted(Comparator.comparing(e -> e.getInteger("count"), Comparator.reverseOrder())).collect(Collectors.toList());
//多字段排序 如果无法推断e类型的情况下,需要手动指定类型,如下面的QueryData,否则会报错:无法解析 'Object' 中的方法 'getXXXXX'
queryData = queryData.stream().sorted(Comparator.comparing((QueryData e) -> e.getInteger("transNum")).reversed().thenComparing(e -> e.getString("createAt"), Comparator.reverseOrder())).collect(Collectors.toList());