Java8新特性--Stream

一. 概述

Java 流是来自源的支持聚合操作的一系列元素。 流不存储元素。 元素是按需计算的。 元素是从数据源(如集合,数组或 I / O 资源)中消耗的。
流聚合操作类似于 SQL 操作。 我们可以对流应用过滤,映射,缩小,匹配,搜索或排序操作。 流允许链接多个流操作。 与使用外部迭代的集合不同,流在内部进行迭代。

二. 示例

2.1 预设测试数据

@Slf4j
public class Test {
    @Data
    public static class User {
        private Integer id;
        private Integer age;
        private String userName;
        private String edu;
    }

    static private List<User> users = new ArrayList<>();

    static {
        User u1 = new User();
        u1.setId(1001);
        u1.setAge(18);
        u1.setUserName("小1");
        u1.setEdu("001");

        User u2 = new User();
        u2.setId(1001);
        u2.setAge(16);
        u2.setUserName("小2");
        u2.setEdu("002");

        User u3 = new User();
        u3.setId(1003);
        u3.setAge(19);
        u3.setUserName("小3");
        u3.setEdu("001");

        User u4 = new User();
        u4.setId(1004);
        u4.setAge(20);
        u4.setEdu("003");
        users.add(u1);
        users.add(u2);
        users.add(u3);
        users.add(u4);
    }

2.2 List转Map

2.2.1 以实体的某个属性为key, 实体为value, 转成一个Map

    /**
     * 以实体的某个属性为key, 实体为value, 转成一个Map
     */
    @Test
    public void test1() {
        //将List转换为Map
        Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(User::getId,
                Function.identity()));
        System.out.println(JSON.toJSONString(userMap));
    }

说明: 如果key存在重复, 会报错, 解决方案保留其中一个

    /**
     * 以实体的某个属性为key, 某个属性为value, 转成一个Map
     * 出现重复key问题时: 合并value
     */
    @Test
    public void test3() {
        //将List转换为Map,解决key冲突的问题。
        Map<String, User> userMap = users.stream().
                //User对象的edu属性作为key,但是会存在key相同的情况
                        collect(Collectors.toMap(User::getEdu,
                        //value的值
                        Function.identity(),
                        //合并两个value值:k1是旧值,k2是新值。
                        (k1, k2) -> {
                            log.info(JSON.toJSONString(k1));
                            log.info(JSON.toJSONString(k2));
                            return k2;
                        }));
        System.out.println(userMap);
    }

2.2.2 以实体的某个属性为key, 某个属性为value, 转成一个Map

    /**
     * 以实体的某个属性为key, 某个属性为value, 转成一个Map
     */
    @Test
    public void test2() {
        //将List转换为Map
        Map<Integer, String> userMap = users.stream().collect(Collectors.toMap(User::getId,
                User::getEdu));
        System.out.println(JSON.toJSONString(userMap));
    }

说明: 当value为空时, 会报错, 解决方案: 用list去接受value

/**
     * 测试以实体的某个属性为key, 某个属性为value, 转成一个Map
     * 出现重复value为null问题时, 用list去接收value
     * 出现key重复时, 合并value值
     */
    @Test
    public void test4() {
        //将List转换为Map,解决key冲突的问题。
        Map<Integer, List<String>> collect = users.stream().
                //User对象的edu属性作为key,但是会存在key相同的情况
                        collect(Collectors.toMap(User::getId,
                        //value的值,是集合的结构
                        p -> {
                            //获取value值
                            List<String> users = new ArrayList<>();
                            users.add(p.getUserName());
                            return users;
                        },
                        //集合合并
                        (List<String> k1, List<String> k2) -> {
                            k1.addAll(k2);
                            return k1;
                        }));
        System.out.println(collect);
    }

2.3 List 进行分组

2.3.1 List分组, key为某个属性, value为实体类

    /**
     * List分组
     */
    @Test
    public void test5() {
        Map<String, List<User>> collect = users.stream().
                collect(Collectors.groupingBy(User::getEdu));
        System.out.println(collect);
    }

2.3.2 List分组, key为某个属性, value为某个属性

    /**
     * List分组, value是某个值
     */
    @Test
    public void test6() {
        Map<String, List<String>> collect = users.stream().
                collect(Collectors.groupingBy(User::getEdu,
                        Collectors.mapping(User::getUserName, Collectors.toList())));
        System.out.println(collect);
    }

2.4 List过滤

    /**
     * list过滤, 过滤年龄大于18的数据
     */
    @Test
    public void test7() {
        List<User> collect = users.stream().filter(p -> p.getAge() > 18).collect(Collectors.toList());
        System.out.println(collect);
    }

2.5 计算求和

/**
     * 年龄累加
     */
    @Test
    public void test8() {
        Integer reduce = users.stream().map(User::getAge).reduce(0, (o1, o2) -> o1 + o2);
        System.out.println(reduce);
    }

2.6 查找极值

2.6.1 查找最大值

    /**
     * 查找最大值
     */
    @Test
    public void test9() {
        Optional<User> collect = users.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge)));
        collect.ifPresent(user -> System.out.println(user.getAge()));
    }

2.6.2 查找最小值

/**
     * 查找最小值值
     */
    @Test
    public void test10() {
        Optional<User> collect = users.stream().collect(Collectors.minBy(Comparator.comparing(User::getAge)));
        collect.ifPresent(user -> System.out.println(user.getAge()));
    }


2.7 去重

/**
     * 去除id重复的值
     */
    @Test
    public void test11() {
        ArrayList<User> collect = users.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparingInt(User::getId))), ArrayList::new
            )
        );
        System.out.println(collect);
    }

    /**
     * putIfAbsent() 方法是
     *      如果 key对应的value值不存在, key value 添加到 map 中,并返回 null
     *      如果 key对应的value值已存在, key value 不再添加到 map 中, 并返回原 value
     *
     * 故 newKey(这里的newKey对应user对象中的name的值), 如果(newKey, Boolean.TRUE) 在map中已存在,
     * putIfAbsent(newKey, Boolean.TRUE) 会返回 Boolean.TRUE (Boolean.TRUE 被final修饰,故其地址值唯一, 可用作比较)
     * 然后判断是否等于 null, 返回false, filter接收到结果为false的Predicate并将该值过滤掉
     * @param keyExtractor
     * @param <T>
     * @return
     */
    private static <T> Predicate<T> distinctByVariable(Function<? super T, ?> keyExtractor) {
        HashMap<Object, Boolean> map = new HashMap<>();
        return t->map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
// 根据id和用户名去重
    @Test
    public void test12(){
        List<User> userList = users.stream().filter(distinctByVariable(u -> {
            return u.getUserId() + u.getUsername();
        })).collect(Collectors.toList());
        userList.forEach(s-> System.out.println(s.getUserId()+"-"+s.getUsername()));
    }

2.8 集合元素校验

/**
* 判断tweet 是否包含集合里的某个元素
*/
    @Test
    public void teat1(){
        final List<String> keywords = Arrays.asList("brown", "fox", "dog", "pangram");
        final String tweet = "The quick brown fox jumps over a lazy dog. #pangram http://www.rinkworks.com/words/pangrams.shtml";

        boolean match = keywords.stream().anyMatch(tweet::contains);
        System.out.println(match);
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容