美文网首页
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