美文网首页
Java8新特性--Stream

Java8新特性--Stream

作者: 任未然 | 来源:发表于2020-04-14 16:11 被阅读0次

一. 概述

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);
    }

相关文章

  • Stream流

    Stream流 java8新特性 Stream定义 A sequence of elements supporti...

  • Stream API

    Stream 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! Stream API Java...

  • java 8 stream 流详细教程

    1 基本特性 Java8的API中添加了一个新的特性: 流,即stream。stream是将数组或者集合的元素视为...

  • JAVA8新特性:Stream与Lambda表达式

    一、Stream学习 在学习lambda表达式之前,我们需要先了解Stream这个java8的新特性。 Strea...

  • Java8新特性系列(流性能)

    上期介绍了Java8中Stream的新特性,本期我们将测试下stream与parallelStream的性能以及应...

  • java8新特性

    java8新特性 原创者:文思 一、特性简介 速度更快 代码更少,增加了Lambda 强大的Stream API ...

  • 03_Java8_Lamda表达式学习

    Java8 的新特性:Lambda表达式、强大的 Stream API、全新时间日期 API、Concurrent...

  • parallelStream使用不当引发的血案

    Stream简洁 众所周知,java8的新特性中出了lambda表达式之外最受人关注的还有stream一系列的ap...

  • Java8新特性Stream

    声明转载自:http://www.importnew.com/11908.html#streams Stream ...

  • JAVA8新特性:Stream

    1.筛选与切片: 测试结果 2.映射: 接受lambda,作用到每一个元素,并得到新值1.大小写转换 2.提取每个...

网友评论

      本文标题:Java8新特性--Stream

      本文链接:https://www.haomeiwen.com/subject/ddjtvhtx.html