Java8 Stream 使用

filter(过滤)

该操作n的函数,当返回false的元素将会被排除掉。

举例:假如我们100个客户,需要筛选出年龄大于18岁的客户。

 List<SysUser> collect = userList.stream()
                .filter(user -> user.getAge() > 18)
                .collect(Collectors.toList());

去重

distinct

该操作将会排除掉重复的元素。

 List<SysUser> collect = userList.stream()
                .distinct()
                .collect(Collectors.toList());

也可结合别的方法使用。如下:去掉集合中大于5的重复值。

List<Integer> collect = Stream.of(1, 2, 5, 6, 7, 8, 9, 7, 2)
                .filter(num -> num > 5)
                .distinct()
                .collect(Collectors.toList());

输出:

[6, 7, 8, 9]

使用 collectingAndThen() 和 toCollection() 方法

这个方法可以根据元素的某个属性或者多个属性来去重,比如 name 或者 name+address。这个方法会使用 TreeSet 来排序元素,所以不能保持原来的顺序。

//根据name属性去重
List<User> lt = list.stream().collect(
        collectingAndThen(
                toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))),
                ArrayList::new)
);
System.out.println("去重后的:" + lt);

Map

List<KnowledgeQuest> distinctList = knowledgeQuestList.stream()
    .collect(Collectors.toMap(
        KnowledgeQuest::getKnowkey, // 使用 knowkey 作为 Map 的键
        Function.identity(),        // 使用 KnowledgeQuest 对象自身作为值
        (existing, replacement) -> replacement)) // 如果出现重复的 knowkey,用新值替换旧值
    .values()
    .stream()
    .collect(Collectors.toList());

limit(限量)

该方法限制流只返回指定个数的元素。

List<Integer> collect = Stream.of(1, 2, 5, 6, 7, 8, 9, 7, 2)
                .limit(5)
                .collect(Collectors.toList());

输出:

[1, 2, 5, 6, 7]

skip(跳过)

扔掉前指定个数的元素;配合limit使用可以达到翻页的效果。

List<Integer> collect = Stream.of(1, 2, 5, 6, 7, 8, 9, 7, 2)
                .skip(2)
                .limit(5)
                .collect(Collectors.toList());

输出:

[5, 6, 7, 8, 9]

map

该方法提供一个函数,流中的每个元素都会应用到这个函数上,返回的结果将形成新类型的流继续后续操作。

举例:假如我们100个客户,需要筛选出年龄大于18岁的客户,打印出他们的名字

userList.stream().filter(user-> user.getRoleId()>18).map(SysUser::getName).forEach(System.out::println);

相当于

for (SysUser sysUser : userList) {
    if (sysUser.getAge() > 18) {
        String name = sysUser.getName();
        System.out.println(name);
    }
}

在调用map之前流的类型是Stream,执行完map之后的类型是Stream

过滤并获取名字列表

List<String> userNameList = userList.stream().filter(user-> user.getRoleId()>18).map(SysUser::getName)..collect(Collectors.toList());

获取Id和名字的map

Map<Long, String> userIdNameMap = userList.stream().collect(Collectors.toMap(SysUser::getId, SysUser::getName));

统计

# 统计
IntSummaryStatistics statistics = userList.stream().mapToInt(SysUser::getAge).summaryStatistics();
// 获取和值
long totalAge= statistics.getSum();
// 获取平均值
double avaAge= statistics.getAverage();

# 求和
int totalAge = userList.stream().mapToInt(SysUser::getAge).sum();

filterMap

groupingBy(分组)

对元素按照条件进行分组。

List<String> list = Arrays.asList("apple", "banana", "orange");
Map<Integer, List<String>> grouped = list.stream().collect(Collectors.groupingBy(fruit -> fruit.length()));

分组计数

List<User> userList = new ArrayList<>();
userList.add(new User("张","张三"));
userList.add(new User("张","张四"));
userList.add(new User("张","张五"));
userList.add(new User("李","李一"));
userList.add(new User("李","李二"));
Map<String, Integer> groupCount = userList.stream()
        .collect(Collectors.toMap(User::getFirstName, el -> 1, Integer::sum));
System.out.println(groupCount);
// {张=3, 李=2}

即姓张的有3个,姓李的有两个。

详解: 将该集合的stream流用Collectors对象转成Map,用User对象的firstName作为Key,默认键值为1,在处理键冲突的函数中,将上一次的值与默认值1相加。比如处理第一个姓张的人的时候,默认值为1,处理第二个也是姓张的人的时候默认值也是1,将1和1相加得2,(即有两个姓张的人了),处理第三个姓张的人的时候,将上次的结果2与第三个姓张返回的默认值1相加,得3,以此类推...得到处理结果。

sorted(排序)

对所有的元素进行排序。

List<Integer> collect5 = Stream.of(1, 2, 5, 6, 7, 8, 9, 7, 2)
                .sorted(Integer::compareTo)
                .collect(Collectors.toList());

输出:

[1, 2, 2, 5, 6, 7, 7, 8, 9]

排序方式

自然序排序:

list.stream().sorted() 

自然序逆序:

list.stream().sorted(Comparator.reverseOrder())

Comparator排序:

list.stream().sorted(Comparator.comparing(Student::getAge)) 

Comparator逆序:

list.stream().sorted(Comparator.comparing(Student::getAge).reversed())

JSONArray按字段排序:

jsonArray.sort(Comparator.comparing(obj -> ((JSONObject) obj).getString("cdn").length()).reversed());

倒序写法:

jsonArray.sort(Comparator.comparing(obj -> obj.getIntValue("count")).reversed());

这样写 reversed 会报错,需要指定类型,如下:

jsonArray.sort(Comparator.comparing((JSONObject obj) -> obj.getIntValue("count")).reversed());

使用list的排序方式:

list.sort(Comparator.comparing(Integer::intValue));
 
list.sort(Comparator.comparing(Integer::intValue).reversed());
 
list.sort(Comparator.comparing(Student::getAge));
 
list.sort(Comparator.comparing(Student::getAge).reversed());

Map排序

Map<String, List<EditionInfo>> collect = list.stream()
    .collect(Collectors.groupingBy(EditionInfo::getPinyinKey))
    .entrySet().stream()
    .sorted(Map.Entry.comparingByKey())
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        (e1, e2) -> e1,
        LinkedHashMap::new
    ));

使用 Collectors.groupingBy 方法将 list 按照 pinyinKey 分组。
将分组后的 Map 转换为 entrySet 的流。
使用 sorted(Map.Entry.comparingByKey()) 对 entrySet 按键进行自然升序排序。
使用 Collectors.toMap 方法将排序后的 entrySet 收集到一个新的 LinkedHashMap 中,以保证键的顺序。

MAX(取最大值)

传统写法

 public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        Integer max = list.stream().max((a, b) -> {
            if (a > b) {
                return 1;
            } else return -1;
        }).get();

        System.out.println(max);
    }

stream 简化写法

int max = list.stream().max((a, b) -> a > b ? 1 : -1).get();

JSON List 取最大值

List<JSONObject> list= new ArrayList<>();
int max = list.stream().max((a, b) -> a.getIntValue("count") > b.getIntValue("count") ? 1 : -1).get().getIntValue("count");

工具类

## 计算list去重后的数量

    /**
     * 计算list去重后的数量
     *
     * @param list
     * @param keyExtractor
     * @param filters
     * @param <T>
     * @return
     */
    public static <T> long countDistinctByKey(List<T> list, Function<T, ?> keyExtractor, Predicate<T>... filters) {
        Predicate<T> combinedFilter = t -> true; // 默认条件是 always true
        for (Predicate<T> filter : filters) {
            combinedFilter = combinedFilter.and(filter); // 组合多个条件
        }

        return list.stream()
                .filter(combinedFilter) // 应用组合后的过滤条件
                .collect(Collectors.toMap(
                        keyExtractor,          // 提取键
                        Function.identity(),   // 取值为自身
                        (existing, replacement) -> replacement)) // 如果出现重复的键,使用新值替换旧值
                .size(); // 计算去重后的数量
    }

使用

long knowSize = countDistinctByKey(knowledgeQuestList, KnowledgeQuest::getKnowkey, kq -> kq.getRight()==1);

参考

https://blog.csdn.net/qq_38989725/article/details/109313270
https://blog.csdn.net/qq_20009015/article/details/90634905
https://blog.csdn.net/qq_30312047/article/details/114583063
https://blog.csdn.net/weixin_45313494/article/details/130801973

本文链接: https://jianz.xyz/index.php/archives/176/

1 + 8 =
快来做第一个评论的人吧~