Stream API使用简介

Java8中添加了对于Stream API的支持,Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用sql执行的数据库查询。也可以使用Stream API来并行执行操作,Stream API提供了一种高效且易于使用的处理数据的方式。

流(Stream)是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。

Stream自己不会存储元素。Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

     

流的操作过程,创建流,中间操作,终止条件,只有声明终止条件,流才会触发执行。

对应Stream接口

A sequence of elements supporting sequential and parallel aggregate operations.

public interface Stream<T> extends BaseStream<T, Stream<T>> {

准备测试数据  准备一个实体类以及相应的集合列表

@Data
public class Dog implements Comparable<Dog> {

    private Integer size;

    private String name;

    private Integer age;

    private Integer price;

    public Dog(){}

    public Dog(String name){
        this.name = name;
    }

    public Dog(Integer size, Integer age){
        this.size = size;
        this.age = age;
    }

    public Dog(Integer size, String name, Integer age, Integer price) {
        this.size = size;
        this.name = name;
        this.age = age;
        this.price = price;
    }

    @Override
    public int compareTo(Dog o) {
        return this.age - o.age;
    }
}
List<Dog> dogs = Arrays.asList(
        new Dog(1, "d1", 2, 5),
        new Dog(2, "d2", 3, 6),
        new Dog(3, "d3", 4, 2),
        new Dog(4, "d4", 1, 3),
        new Dog(1, "d5", 2, 5),
        new Dog(2, "d6", 3, 6),
        new Dog(3, "d7", 4, 2),
        new Dog(4, "d8", 1, 3));

Stream创建

Stream创建主要有以下方法

1.Collection

集合类流创建

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
    return StreamSupport.stream(spliterator(), true);
}

2.Arrays

数组流创建

public static <T> Stream<T> stream(T[] array) {
    return stream(array, 0, array.length);
}

3.Stream

创建其他形式流,例如迭代,生成等

public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
    Objects.requireNonNull(f);
    final Iterator<T> iterator = new Iterator<T>() {
        @SuppressWarnings("unchecked")
        T t = (T) Streams.NONE;

        @Override
        public boolean hasNext() {
            return true;
        }

        @Override
        public T next() {
            return t = (t == Streams.NONE) ? seed : f.apply(t);
        }
    };
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
            iterator,
            Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
}
public static<T> Stream<T> generate(Supplier<T> s) {
    Objects.requireNonNull(s);
    return StreamSupport.stream(
            new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}

测试如下:

        //创建Stream
        //1.Collection stream() parallelStream()
        List<Dog> list = new ArrayList<>();
        Stream<Dog> stream = list.stream();
        Stream<Dog> stream2 = list.parallelStream();

        //2.Arrays  stream()数组流
        Dog[] dogarr = new Dog[10];
        Stream<Dog> stream3 = Arrays.stream(dogarr);

        List<Dog> dog = stream3.collect(Collectors.toList());
        System.out.println(dog);

        //3.Stream 静态of方法
        Stream<String> stream4 = Stream.of("acv", "dsf", "cdv");

        //4.无限流
        Stream<Integer> stream5 = Stream.iterate(0, (x) -> x + 2);
        //stream5.forEach(System.out::println);

        //Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);

        dogs.stream().forEach(System.out::println);
        System.out.println("==============");

中间操作

1.筛选切片

按照某种规则进行过滤筛选

/**
 * Returns a stream consisting of the elements of this stream that match
 * the given predicate.
Stream<T> filter(Predicate<? super T> predicate);
/**
 * Returns a stream consisting of the elements of this stream, truncated
 * to be no longer than {@code maxSize} in length.
Stream<T> limit(long maxSize);
/**
 * Returns a stream consisting of the remaining elements of this stream
 * after discarding the first {@code n} elements of the stream.
 * If this stream contains fewer than {@code n} elements then an
 * empty stream will be returned.
Stream<T> skip(long n);
/**
 * Returns a stream consisting of the distinct elements (according to
 * {@link Object#equals(Object)}) of this stream.
Stream<T> distinct();

测试如下:

        //1.筛选和切片
        //filter 根据条件过滤
        dogs.stream().filter((x) -> x.getSize() > 1).forEach(System.out::println);
        //limit 限制返回个数
        dogs.stream().filter((x) -> x.getSize() > 1).limit(2).forEach(System.out::println);
        //skip 跳过n个元素 从之后的元素流  若不足n个,则返回空流
        dogs.stream().filter((x) -> x.getSize() > 1).skip(2).forEach(System.out::println);
        //distinct 去重  根据元素的hashcode和equals方法来去重
        dogs.stream().distinct().forEach(System.out::println);

2.映射

将流中每一个元素进行处理并返回

/**
 * Returns a stream consisting of the results of applying the given
 * function to the elements of this stream.
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
/**
 * Returns a stream consisting of the results of replacing each element of
 * this stream with the contents of a mapped stream produced by applying
 * the provided mapping function to each element.  Each mapped stream is
 * {@link java.util.stream.BaseStream#close() closed} after its contents
 * have been placed into this stream.  (If a mapped stream is {@code null}
 * an empty stream is used, instead.)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

测试:

        //2.映射
        //map 传入一个函数  应用于每一个元素  返回一个新元素
        dogs.stream().map((d) -> d.getSize()).forEach(System.out::println);
        //flatMap 传入一个函数  应用于每一个元素产生一个流  返回所有元素产生流的合流
        dogs.stream().flatMap((d) -> splitStr(d.getName())).forEach(System.out::println);

3.排序

将流中元素按照某种规则排序

/**
 * Returns a stream consisting of the elements of this stream, sorted
 * according to natural order.  If the elements of this stream are not
 * {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown
 * when the terminal operation is executed.
Stream<T> sorted();
/**
 * Returns a stream consisting of the elements of this stream, sorted
 * according to the provided {@code Comparator}.
Stream<T> sorted(Comparator<? super T> comparator);

测试

//3.排序
//自然排序  按照Comparable
dogs.stream().sorted().forEach(System.out::println);

//定制排序  Comparator
dogs.stream().sorted((d1, d2) -> Integer.compare(d1.getSize(),             
        d2.getSize())).forEach(System.out::println);dogs.stream().sorted(Comparator.comparingInt(Dog::getSize)).forEach(System.out::println);

终止操作

1.查找匹配

//1.查找与匹配
//是否匹配所有元素
dogs.stream().allMatch((d) -> d.getSize() == 1);
//是否至少匹配任意一个元素
dogs.stream().anyMatch((d) -> d.getSize() > 1);
//是否没有元素匹配
dogs.stream().noneMatch((d) -> d.getSize() < 100);
//返回任意一个元素
dogs.stream().findAny();
//返回第一个元素
dogs.stream().findFirst();
//总数量
dogs.stream().count();
//最大值
dogs.stream().max(Comparator.comparingInt(Dog::getSize));
//最小值
dogs.stream().min(Comparator.comparingInt(Dog::getSize));

2.归约

/**
 * Performs a <a href="package-summary.html#Reduction">reduction</a> on the
 * elements of this stream, using the provided identity value and an
 * <a href="package-summary.html#Associativity">associative</a>
 * accumulation function, and returns the reduced value.  This is equivalent
 * to:
 * <pre>{@code
 *     T result = identity;
 *     for (T element : this stream)
 *         result = accumulator.apply(result, element)
 *     return result;
 * }</pre>
 *
 * but is not constrained to execute sequentially.
T reduce(T identity, BinaryOperator<T> accumulator);
        //2.归约
        //reduce 将流中元素反复结合得到新的值
        List<Integer> ll = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        System.out.println(ll.stream().reduce(1, (x, y) -> x * y));

        Integer sum = dogs.stream().map((d) -> d.getSize()).reduce(0, Integer::sum);
        System.out.println(sum);

3.收集

/**
 * Performs a <a href="package-summary.html#MutableReduction">mutable
 * reduction</a> operation on the elements of this stream using a
 * {@code Collector}.  A {@code Collector}
 * encapsulates the functions used as arguments to
 * {@link #collect(Supplier, BiConsumer, BiConsumer)}, allowing for reuse of
 * collection strategies and composition of collect operations such as
 * multiple-level grouping or partitioning.
<R, A> R collect(Collector<? super T, A, R> collector);
        //3.收集
        //将流转换为其他形式
        List<String> nl = dogs.stream().map((d) -> d.getName()).collect(Collectors.toList());
        List<Dog> dl = dogs.stream().filter((d) -> d.getSize()>1).collect(Collectors.toList());
        System.out.println(dl);

        Set<String> sl = dogs.stream().map((d) -> d.getName()).collect(Collectors.toSet());

        HashSet<String> hsl = dogs.stream().map((d) -> d.getName()).collect(Collectors.toCollection(HashSet::new));

        //对应于sql语法
        //总数 平均值
        System.out.println(dogs.stream().collect(Collectors.counting()));

        System.out.println(dogs.stream().collect(Collectors.averagingInt(Dog::getSize)));

        //分组
        Map<Integer, List<Dog>> m = dogs.stream().collect(Collectors.groupingBy(Dog::getSize));
        System.out.println(m);

        //多级分组
        Map<Integer, Map<Integer, List<Dog>>> mm = dogs.stream().collect(Collectors.groupingBy(Dog::getSize, Collectors.groupingBy(Dog::getAge)));
        System.out.println(mm);

        //分区
        Map<Boolean, List<Dog>> pm = dogs.stream().collect(Collectors.partitioningBy((d) -> d.getSize() > 2));
        System.out.println(pm);

        //链接
        String join = dogs.stream().map((d) -> d.getName()).collect(Collectors.joining());
        System.out.println(join);

        String join2 = dogs.stream().map((d) -> d.getName()).collect(Collectors.joining(",", "pre", "suf"));
        System.out.println(join2);

使用收集类函数,可以将流转换为其他形式,同时进行相应的计算处理,例如分组,分区,连接等。

总之,使用Stream API来操作集合对象还是比较爽的,可以少些很多代码,但是过于使用复杂语法会导致代码阅读难度较大。

参考资料:尚硅谷_Java8新特性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值