美文网首页
Java | Stream

Java | Stream

作者: tingshuo123 | 来源:发表于2018-09-25 19:05 被阅读12次

    简介

    Stream流 是 JDK1.8 加入的新特性,Stream流跟I/O流不同,Stream流用于操作数据源(集合、数组等)所生成的元素序列。

    Stream 有几个特点:

    • 它不会存储元素
    • 延迟执行,Stream 会等到需要结果时才会执行
    • 不会改变数据源(使用map方法可以通过对象引用还改变源数据)
    • 对 Stream 的操作是以 lamnda 表达式为参数
    • 可以是无限的,用 Stream 可以轻松表示全体自然数,这是集合类不可能做到的。
    • stream的聚合、消费或收集操作只能进行一次,再次操作会报错,Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了

    使用 Stream 有三个步骤:

    1. 创建一个Stream流
    2. 中间操作
    3. 终止操作
    创建
            // 1. 通过Collections系列集合提供的stream() 或 parallelStream()
            List<String> list = new ArrayList<>();
            Stream<String> stream01 = list.stream();
            
            // 2. 通过Arrays中的静态方法stream()获取数组流
            String[] strList = new String[10];
            Stream<String> stream02 = Arrays.stream(strList);
            
            // 3. 通过Stream类中的静态方法
            Stream<String> stream03 = Stream.of(strList);
            
            // 4. 迭代
            Stream<Integer> stream04 = Stream.iterate(0, (x) -> (x + 1));
            stream04.limit(10).forEach(System.out::println);
            
            // 5. 生成
            Stream<Double> stream05 = Stream.generate(() -> Math.random());
            stream05.limit(10).forEach(System.out::println);
    
    
    中间操作

    数据源:

            List<Human> list = new ArrayList<>();
            list.add(new Human("小王", 31, "男"));
            list.add(new Human("小黑", 24, "女"));
            list.add(new Human("小张", 10, "男"));
            list.add(new Human("胖虎", 15, "男"));
            list.add(new Human("小王", 31, "男"));
            list.add(new Human("胖虎", 15, "男"));
    

    获取Stream

    Stream<Human> stream = list.stream();
    

    过滤,获取大于二十岁的:

    stream.filter(item -> item.getAge() > 20).forEach(System.out::println);
    
    

    切片,利用skiplimit方法 配合使用实现切片

    // 切片,获取下标 [2,4) 的元素
    stream.skip(2).limit(3).forEach(System.out::println);
    
    

    映射,将函数作用在流的每个元素上

    // 所有人年龄加 1
    stream.map(item ->{item.setAge(item.getAge() + 1); return item;}).forEach(System.out::println);
    

    扁平化,例如将字符数组的字符转换为字母,并将重复字母去掉

    List<String> words = Arrays.asList("Hello", "Wrold");
            words.stream()
                .map(word -> word.split(""))
                .flatMap((Arrays::stream))  // 扁平化,把map(Arrays::stream)生成的单个流合并成一个流
                .distinct()
                .forEach(System.out::println);
    

    去重

    // 利用hashcode 跟 equals 作为重复判断依据
    stream04.distinct().forEach(System.out::println);
    

    还可以将多个中间操作配合使用,比如加入有业务需要 无重复的列出所有已成年男性,我们就可以这样写

            stream
                .filter(item -> item.getAge() > 18 && "男".equals(item.getSex()))  // 过滤掉未成年及女生
                .distinct()  // 去重,是利用HashCode与equals方法去重
                .forEach(System.out::println);  // 终止操作
    

    在上面的示例中 .forEach() 就是终止操作

    将Strea生成一个新的集合
    
    // 转换为ArrayList
    Stream<Integer> stream01 = Stream.iterate(0, x -> (x + 1));
    stream01.limit(10).collect(Collectors.toList())
    
    // 转换为HashSet
    Stream<Integer> stream02 = Stream.iterate(0, x -> (x + 1));
    stream02.limit(10).collect(Collectors.toSet())
    
    

    用 Stream 表示全体自然数(其实就是上面迭代的那个例子)

    // 全体自然数
    Stream<Integer> stream = Stream.iterate(0, x -> (x + 1));
    // 取前十个
    stream.limit(10).forEach(System.out::println);
    

    利用函数式接口 Supplier 实现

    public class Natural implements Supplier<Integer> {
        
        private Integer number = 0;
        // 获取自然数
        @Override
        public Integer get() {
            
            return this.number++;
        }
        
    }
    
        @Test
        public void test03() {
            
            Stream<Integer> stream = Stream.generate(new Natural());
            stream.limit(10).forEach(System.out::println);
        }
    

    package stream;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    import org.junit.Test;
    
    
    
    public class StreamDemo {
        
        /*
         * 获取Stream的方式
         */
        
        @Test
        public void test01() {      
            // 1. 通过Collections系列集合提供的stream() 或 parallelStream()
            List<String> list = new ArrayList<>();
            Stream<String> stream01 = list.stream();
            
            
            // 2. 通过Arrays中的静态方法stream()获取数组流
            String[] strList = new String[10];
            Stream<String> stream02 = Arrays.stream(strList);
            
            // 3. 通过Stream类中的静态方法
            Stream<String> stream03 = Stream.of(strList);
            
            // 4. 迭代
            Stream<Integer> stream04 = Stream.iterate(0, (x) -> (x + 2));
            stream04.limit(10).forEach(System.out::println);
            
            // 5. 生成
            Stream<Double> stream05 = Stream.generate(() -> Math.random());
            stream05.limit(10).forEach(System.out::println);
        }
        
        /*
         * 中间API
         */
        @Test
        public void test02() {
            List<Human> list = new ArrayList<>();
            list.add(new Human("小王", 31, "男"));
            list.add(new Human("小黑", 24, "女"));
            list.add(new Human("小张", 10, "男"));
            list.add(new Human("胖虎", 15, "男"));
            list.add(new Human("小王", 31, "男"));
            list.add(new Human("胖虎", 15, "男"));
            
            // 获取流
            Stream<Human> stream = list.stream();
            
    //      list.get(1).setAge(45);
            
            /*
             *  中间操作
             */
            
            // 过滤
            Stream<Human> stream01 = list.stream();
            System.out.println("============== 过滤 ================");
            stream01.filter(item -> item.getAge() > 20).forEach(System.out::println);
            
            // 切片,取下标 [2,4) 的元素
            Stream<Human> stream02 = list.stream();
            System.out.println("=============== 切片 ===============");
            stream02.skip(2).limit(3).forEach(System.out::println);
            
            
            // 去重
            Stream<Human> stream04 = list.stream();
            System.out.println("=============== 去重 ===============");
            stream04.distinct().forEach(System.out::println);
            
            // 映射,将函数作用于每个元素
            Stream<Human> stream05 = list.stream();
            System.out.println("=============== 映射 ===============");
            stream05.map(item ->{item.setAge(item.getAge() + 1); return item;}).forEach(System.out::println);
            
            // 中间操作返回的还是Stream,所以可以将多个中间操作组合使用
            Stream<Human> stream06 = list.stream();
            System.out.println("=============== 配合使用 ===============");
            stream06
                .filter(item -> item.getAge() > 18 && "男".equals(item.getSex()))  // 过滤掉未成年及女生
                .distinct()  // 去重,是利用HashCode与equals方法去重
                .forEach(System.out::println);  // 终止操作
            
            
            System.out.println("=============== 查看数据是否被改变 ===============");
            for (Human human : list) {
                System.out.println(human);
            }
        }
        
        /**
         * 自然数一
         */
        @Test
        public void test03() {
            
            Stream<Integer> stream = Stream.generate(new Natural());
            stream.limit(10).forEach(System.out::println);
        }
        /**
         * 自然数二
         */
        @Test
        public void test04() {
            Stream<Integer> stream = Stream.iterate(0, x -> (x + 1));
            stream.limit(10).forEach(System.out::println);
        }
        
        
        @Test
        public void test05() {
            
            // 转换为ArrayList
            Stream<Integer> stream01 = Stream.iterate(0, x -> (x + 1));
            System.out.println(stream01.limit(10).collect(Collectors.toList()).getClass());
            
            // 转换为HashSet
            Stream<Integer> stream02 = Stream.iterate(0, x -> (x + 1));
            System.out.println(stream02.limit(10).collect(Collectors.toSet()).getClass());
        }
        
        /**
         * 分组
         */
        @Test
        public void test06() {
            List<Human> list = new ArrayList<>();
            list.add(new Human("小王", 31, "男"));
            list.add(new Human("小黑", 24, "女"));
            list.add(new Human("小张", 10, "男"));
            list.add(new Human("胖虎", 15, "女"));
            list.add(new Human("小王", 31, "男"));
            list.add(new Human("胖虎", 15, "女"));
            
            Stream<Human> stream = list.stream();
            
            Map<String, List<Human>> map = stream.collect(Collectors.groupingBy(Human::getSex));
            System.out.println(map.size() + ": " + map.keySet());
            System.out.println(map.get("男"));
            System.out.println(map.get("女"));
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Java | Stream

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