2

记录下 Java Stream 的一些高效操作

 1 year ago
source link: https://nicksxs.me/2022/05/15/%E8%AE%B0%E5%BD%95%E4%B8%8B-Java-Lambda-%E7%9A%84%E4%B8%80%E4%BA%9B%E9%AB%98%E6%95%88%E6%93%8D%E4%BD%9C/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

记录下 Java Stream 的一些高效操作

我们日常在代码里处理一些集合逻辑的时候用到 Stream 其实还挺多的,普通的取值过滤集合一般都是结合 ide 的提示就能搞定了,但是有些不太常用的就在这记录下,争取后面都更新记录下来。

自定义 distinctByKey 对结果进行去重

stream 中自带的 distinct 只能对元素进行去重
比如下面代码

public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(1);
        list.add(2);
        list = list.stream().distinct().collect(Collectors.toList());
        System.out.println(list);
    }

结果就是去了重的

[1, 2]

但是当我的元素是个复杂对象,我想根据对象里的某个元素进行过滤的时候,就需要用到自定义的 distinctByKey 了,比如下面的想对 userId 进行去重

public static void main(String[] args) {
        List<StudentRecord> list = new ArrayList<>();
        StudentRecord s1 = new StudentRecord();
        s1.setUserId(11L);
        s1.setCourseId(100L);
        s1.setScore(100);
        list.add(s1);
        StudentRecord s2 = new StudentRecord();
        s2.setUserId(11L);
        s2.setCourseId(101L);
        s2.setScore(100);
        list.add(s2);
        StudentRecord s3 = new StudentRecord();
        s3.setUserId(12L);
        s3.setCourseId(100L);
        s3.setScore(100);
        list.add(s3);
        System.out.println(list.stream().distinct().collect(Collectors.toList()));
    }
    @Data
    static class StudentRecord {
        Long id;
        Long userId;
        Long courseId;
        Integer score;
    }
[StudentRecord(id=null, userId=11, courseId=100, score=100), StudentRecord(id=null, userId=11, courseId=101, score=100), StudentRecord(id=null, userId=12, courseId=100, score=100)]

因为对象都不一样,所以就没法去重了,这里就需要用

public static <T> Predicate<T> distinctByKey(
            Function<? super T, ?> keyExtractor) {

        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

然后就可以用它来去重了

System.out.println(list.stream().filter(distinctByKey(StudentRecord::getUserId)).collect(Collectors.toList()));
[StudentRecord(id=null, userId=11, courseId=100, score=100), StudentRecord(id=null, userId=12, courseId=100, score=100)]

但是说实在的这个功能感觉应该是 stream 默认给实现的

使用 java.util.stream.Collectors#groupingBy 对 list 进行分组

这个使用场景还是蛮多的,上面的场景里比如我要对 userId 进行分组,就一行代码就解决了

System.out.println(list.stream().collect(Collectors.groupingBy(StudentRecord::getUserId)));
{11=[StudentRecord(id=null, userId=11, courseId=100, score=100), StudentRecord(id=null, userId=11, courseId=101, score=100)], 12=[StudentRecord(id=null, userId=12, courseId=100, score=100)]}

很方便的变成了以 userId 作为 key,以相同 userIdStudentRecordList 作为 valuemap 结构


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK