Java-8-Stream接口

Java-8-Stream接口

interface Stream

思维导图:

在这里插入图片描述

生成 Stream

Stream.of

静态方法(源码):


    public static<T> Stream<T> of(T t) {
        return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
    }

    public static<T> Stream<T> of(T... values) {
        return Arrays.stream(values);
    }



使用
public class M1 {


    public static void main(String[] args) {

//        /*************流的来源*************/
        // 1、of方法
        //      of(T... values):返回含有多个T元素的Stream
        //      of(T t):返回含有一个T元素的Stream

        Stream<String> stream1 = Stream.of(
                "a","b","c","d","e"
        );

        stream1.forEach(System.out::println);

        System.out.println("--------------------");

        String[] strings = {"a","45","a"};

        Stream<String> stream2 = Stream.of(strings);

        stream2.forEach(System.out::println);

    }
}

generate与iterate

源码:

public static<T> Stream<T> generate(Supplier<T> s) {
       //...
}


public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f){
                //...      
}
generate

public class M2 {


    public static void main(String[] args) {

        // generator方法,返回一个无限长度的Stream,其元素由Supplier接口的提供。

        Stream<String> stream1 = Stream.generate(
                () ->
                        "A"
        );

//        stream1.forEach(System.out::println);

        Stream<Double> stream2 = Stream.generate(
                ()->
                        Math.random()
        );

//        stream2.forEach(System.out::println);

        Stream<String> stream3 = Stream
                .generate(() -> "love")
                .limit(10);

        stream3.forEach(System.out::println);
        
    }
}


iterate

public class M3 {

    public static void main(String[] args) {

        //  iterate方法,返回的也是一个无限长度的Stream,与generate方法不同的是,其是通过函数f迭代对给指定的元素种子而产生无限连续有序Stream,其中包含的元素可以认为是:seed,f(seed),f(f(seed))无限循环
        Stream<Integer> stream1 = Stream.iterate(
                1,integer -> integer + 2
        );

        stream1.limit(10).forEach(System.out::println);

        System.out.println("---------------------");
        //生成一个等差数列

        Stream.iterate(0, n -> n + 3).limit(10). forEach(x -> System.out.print(x + " "));


    }
}


合并Stream

源码:


 public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
        //...       
}
使用

public class M4 {


    public static void main(String[] args) {

        Stream<Integer> stream1 = Stream.of(
                1,2,3,4,56
        );

        Stream<Integer> stream2 = Stream.of(
                11,258,5689
        );

        Stream<Integer> stream3 = Stream.concat(stream1,stream2);

        stream3.forEach(System.out::println);

        System.out.println("---------");

//        合并多个流(Streams)


        Stream<Integer> first = Stream.of(1, 2);
        Stream<Integer> second = Stream.of(3,4);
        Stream<Integer> third = Stream.of(5, 6);
        Stream<Integer> fourth = Stream.of(7,8);

        Stream<Integer> resultingStream = Stream.concat(first,Stream.concat(second,Stream.concat(third, fourth)));

        resultingStream.forEach(System.out::println);

        System.out.println("---------");


        //合并stream并保留唯一性

        Stream<Integer> firstStream = Stream.of(1, 2, 3, 4, 5, 6);
        Stream<Integer> secondStream = Stream.of(4, 5, 6, 7, 8, 9);

        Stream<Integer> resultingStream_1 = Stream.concat(firstStream, secondStream)
                .distinct();

        resultingStream_1.forEach(System.out::println);


    }
}


中间操作—filter

源码:


Stream<T> filter(Predicate<? super T> predicate);


使用

public class M1 {


    public static void main(String[] args) {

        //filter 对原Stream按照指定条件过滤,过滤出满足条件的元素。

        List<Integer> integers = Create_Data.supply_Integers();

        Predicate<Integer> predicate = integer ->
                integer > 15;

        // 通过传递predicate

        integers.stream()
                .filter(predicate)
                .forEach(System.out::println);


        System.out.println("---------------------------");
        // 直接使用Lambda

        integers.stream()
                .filter(integer -> integer > 75 && integer < 85)
                .forEach(System.out::println);



        System.out.println("---------------------------");


        List<Integer> list  = Arrays.asList(3, 12, 23, 44, 20, 10, 17, 8);

        System.out.println("---List with even Numbers---");

        List<Integer> evenList = list.stream()
                .filter(integer -> integer % 2 ==0)
                .collect(Collectors.toList());


        evenList.forEach(System.out::println);

        System.out.println("\n---List with odd Numbers---");
        List<Integer> oddList = list.stream().filter(i -> i%2 == 1)
                .collect(Collectors.toList());
        oddList.forEach(s -> System.out.print(s+" "));


    }
}


中间操作—map

源码:


//Returns a stream consisting of the elements of this stream that match the given predicate.
<R> Stream<R> map(Function<? super T, ? extends R> mapper);


map方法,它会接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素(使用映射一词,是因为它和转换类似,但其中的细微差别在于它是“创建一个新版本”而不是去“修改”)

使用

public class M1 {


    public static void main(String[] args) {

        //map方法将对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素。

        List<String> strings = Create_Data.supply_Strings(1,10);

        System.out.println(strings);

        System.out.println("");

        strings.stream()
                .map(s -> s.toLowerCase())
                .forEach(System.out::println);


        System.out.println("----------------");

        List<Person> personList = Create_Data.supply_Persons();

        List<Integer> ages = personList.stream()
                .map(Person::getAge)
                .collect(Collectors.toList());

        ages.forEach(System.out::println);

        System.out.println("---------------");

        Stream<Integer> stream = Stream.of(1,2,4,5,6,8);

        stream.map(integer -> integer * integer)
                .forEach(System.out::println);

    }
}

中间操作—mapToInt mapToLong mapToDouble

为了提高处理效率,官方已封装好了,三种变形:mapToDouble,mapToInt,mapToLong,将原Stream中的数据类型,转换为double,int或者long类型。

源码:


IntStream mapToInt(ToIntFunction<? super T> mapper);

LongStream mapToLong(ToLongFunction<? super T> mapper);


DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);


使用


public class M2 {

    public static void main(String[] args) {

        Stream<String> stream1 = Stream.of("ass,","jdjjfjf","145445");

        Stream<Integer> stream2 = Stream.of(1,2556,4556,4556,4559,55);

        // 打印每个字符串的长度
        stream1.mapToInt(String::length).forEach(System.out::println);

        System.out.println("-----------------------------------");
        
        // 计算总和
        int sum = stream2.mapToInt(Integer::intValue).sum();

        System.out.println(sum);
        
    }


}

中间操作—flatMap

源码:



<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);


map 生成的是个 1:1 映射,每个输入元素,都按照规则转换成为另外一个元素。还有一些场景,是一对多映射关系的,这时需要 flatMap

使用

public class M1 {


    public static void main(String[] args) {

        Stream<List<Integer>> inputStream = Stream.of(
                Arrays.asList(1),
                Arrays.asList(2, 3),
                Arrays.asList(4, 5, 6)
        );

        // 把所有元素统一放入一个List里面
//
//        inputStream.map(integers -> integers)
//                .forEach(System.out::println);
        //输出
        //[1]
        //[2, 3]
        //[4, 5, 6]

        //可以看到Map操作无法完成这个任务  它的输出是一个个的小流

        System.out.println("------------------");

        inputStream.flatMap(integers -> integers.stream())
                .forEach(System.out::println);


        System.out.println("-----------------------------------");

        /**
         *      Stream flatMap with Array
         *     Here we will use flatMap with array. I am creating a two dimensional array with integer data. Finally we will find out even numbers.
         *     1. Sample Array
         *     {{1,2},{3,4},{5,6}}
         *     2. After flatMap(row -> Arrays.stream(row))
         *     {1,2,3,4,5,6}
         *     3. After filter(num -> num%2 == 0)
         *     {2,4,6}
         *     Now find the example.
         */

        Integer[][] data = {{1,2},{3,4},{5,6}};


        Arrays.stream(data)
                .flatMap(row -> Arrays.stream(row))
                .filter(num -> num % 2 == 0)
                .forEach(System.out::println);

        System.out.println("-----------------------------------");


        List<List<Integer>> out = new ArrayList<>();

        List<Integer> inner1 = Create_Data.supply_Integers();

        List<Integer> inner2 = Create_Data.supply_Integers();

        List<Integer> inner3 = Create_Data.supply_Integers();

        out.add(inner1);out.add(inner2);out.add(inner3);

        out.stream()
                .flatMap(r -> r.stream())
                .forEach(System.out::println);

        System.out.println("-----------------------------------");



        List<String> list1 = Arrays.asList("AAA","BBB");
        List<String> list2 = Arrays.asList("CCC","DDD");

        Stream.of(list1,list2)
                .flatMap(list -> list.stream())
                .forEach(System.out::println);



    }
}

中间操作—flatMapToInt flatMapToLong flatMapToDouble

flatMap也提供了针对特定类型的映射操作:flatMapToDouble(Function<? super T,? extends DoubleStream> mapper),flatMapToInt(Function<? super T,? extends IntStream> mapper),flatMapToLong(Function<? super T,? extends LongStream> mapper)

源码:


IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);


LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);



DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);


使用


public class M2 {

    public static void main(String[] args) {

        double[][] data = {{1.5,2.4},{3.2,4.4},{5.2,6.8}};


        Arrays.stream(data)
                .map( doubles -> doubles)
                .forEach(System.out::println);

        //[D@7cca494b
        //[D@7ba4f24f
        //[D@3b9a45b3

        System.out.println("--------------------------------");

        Arrays.stream(data)
                .flatMapToDouble(r -> Arrays.stream(r))
                .forEach(System.out::println);

        //1.5
        //2.4
        //3.2
        //4.4
        //5.2
        //6.8

        System.out.println("--------------------------------");


        int[][] data1 = {{1,2},{3,4},{5,6}};


        IntStream intStream = Arrays.stream(data1)
                .flatMapToInt(row -> Arrays.stream(row));

        System.out.println(intStream.sum());


    }
}


中间操作—distinct

源码:



Stream<T> distinct();


distinct()使用hashCode()和equals()方法来获取不同的元素。因此,我们的类必须实现hashCode()和equals()方法。如果distinct()正在处理有序流,那么对于重复元素,将保留以遭遇顺序首先出现的元素,并且以这种方式选择不同元素是稳定的。在无序流的情况下,不同元素的选择不一定是稳定的,是可以改变的。distinct()执行有状态的中间操作。在有序流的并行流的情况下,保持distinct()的稳定性是需要很高的代价的,因为它需要大量的缓冲开销。如果我们不需要保持遭遇顺序的一致性,那么我们应该可以使用通过BaseStream.unordered()方法实现的无序流

使用

public class M1 {

    public static void main(String[] args) {


        List<String> list = Arrays.asList("AA", "BB", "CC", "BB", "CC", "AA", "AA");

        list.stream()
                .distinct()
                .forEach(System.out::println);


    }
}



public class Book {


    private String name;
    private int price;
    public Book(String name, int price) {
        this.name = name;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public int getPrice() {
        return price;
    }
    @Override
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        final Book book = (Book) obj;
        if (this == book) {
            return true;
        } else {
            return (this.name.equals(book.name) && this.price == book.price);
        }
    }
    @Override
    public int hashCode() {
        int hashno = 7;
        hashno = 13 * hashno + (name == null ? 0 : name.hashCode());
        return hashno;
    }
}


public class DistinctByProperty {


    //distinct() does not provide distinct elements by property or key. It works on the basis of hashCode() and equals(). If we want distinct element by a property or key, we can achieve it by a work around code. Find the code snippet.


    public static void main(String[] args) {



        List<Book> list = new ArrayList<>();
        {
            list.add(new Book("Core Java", 200));
            list.add(new Book("Core Java", 300));
            list.add(new Book("Learning Freemarker", 150));
            list.add(new Book("Spring MVC", 200));
            list.add(new Book("Hibernate", 300));
        }
        list.stream().filter(distinctByKey(b -> b.getName()))
                .forEach(b -> System.out.println(b.getName()+ "," + b.getPrice()));
    }
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object,Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

}



中间操作—sorted

源码:


/**
    * 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.
    */

//它使用自然顺序对流的元素进行排序。元素类必须实现Comparable接口。
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);

使用

public class M1 {


    public static void main(String[] args) {

        List<Integer> integerList = Create_Data.supply_Integers();

        System.out.println(integerList);

        System.out.println("------------------");

        List<Integer> l1  = integerList.stream().sorted().collect(Collectors.toList());

        System.out.println(l1);

        System.out.println("------------------");

        //自然序逆序元素,使用Comparator 提供的reverseOrder() 方法

        List<Integer> l2 = integerList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

        System.out.println(l2);

        System.out.println("------------------");

        List<Student> students = Student.supply_S();

        List<Student> list = students.stream()
                .sorted(Comparator.comparing(Student::getAge))
        .collect(Collectors.toList());

        System.out.println(list);
        
    }
}

public class Student {

    private static Random random = new Random();

    private String name;

    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static List<Student> supply_S(){
        List<Student> list = new ArrayList<>();

        for (int i = 0; i < 12; i++) {
            list.add(new Student(i+"",random.nextInt(100)));
        }
        return list;
    }
}


中间操作—peek

源码:


    //      * @apiNote This method exists mainly to support debugging, where            you want
    //  * to see the elements as they flow past a certain point in a pipeline:
    //  * <pre>{@code
    //  *     Stream.of("one", "two", "three", "four")
    //  *         .filter(e -> e.length() > 3)
    //  *         .peek(e -> System.out.println("Filtered value: " + e))
    //  *         .map(String::toUpperCase)
    //  *         .peek(e -> System.out.println("Mapped value: " + e))
    //  *         .collect(Collectors.toList());
    Stream<T> peek(Consumer<? super T> action);

使用


public class M1 {

    public static void main(String[] args) {

        Stream.of("one", "two", "three", "four")
                .filter(e -> e.length() > 3)
                .peek(e -> System.out.println("Filtered value: " + e))
                .map(String::toUpperCase)
                .peek(e -> System.out.println("Mapped value: " + e))
                .collect(Collectors.toList());


        System.out.println("--------------------");

        List<Integer> l1 = Create_Data.supply_Integers();

        l1.stream()
                .peek(integer -> System.out.println(integer))
        .limit(5)
        .forEach(System.out::println);


        System.out.println("--------------------");

        List<Integer> list = Arrays.asList(10,11,12);
        list.stream().peek(i->System.out.println(i*i)).collect(Collectors.toList());
        
    }
}

中间操作—limit

源码:


    Stream<T> limit(long maxSize);


使用

public class M1 {


    public static void main(String[] args) {

        List<String> list = Arrays.asList("AA","BB","CC","DD","EE");
        list.stream().limit(3).forEach(s->System.out.println(s));

        System.out.println("-------------");

        List<Integer> l2 = Create_Data.supply_Integers();

        l2.stream()
                .limit(5)
                .forEach(System.out::println);

    }
}

中间操作—skip

源码:



    Stream<T> skip(long n);


使用

public class M1 {


    public static void main(String[] args) {

        List<String> list = Arrays.asList("AA","BB","CC","DD");

        //跳过前两个
        list.stream().skip(2).forEach(s->System.out.println(s));


    }
}

终端操作—forEach

源码:


    void forEach(Consumer<? super T> action);

使用

public class M1 {


    public static void main(String[] args) {

        List<Integer> integers = Create_Data.supply_Integers();

        integers.stream()
                .forEach(integer -> System.out.println(integer + "'号"));

    }
}

终端操作—forEachOrdered

源码:


    void forEachOrdered(Consumer<? super T> action);


使用
public class M2 {


    public static void main(String[] args) {

        Stream.of("AAA,","BBB,","CCC,","DDD,").parallel().forEach(System.out::print);
        System.out.println("\n______________________________________________");
        Stream.of("AAA,","BBB,","CCC,","DDD").parallel().forEachOrdered(System.out::print);
        System.out.println("\n______________________________________________");
        Stream.of("DDD,","AAA,","BBB,","CCC").parallel().forEachOrdered(System.out::print);


    }
}


对于forEachOrdeed ,当stream 为parallel的时候,尽管是多个线程,并行处理的。但是还是会按照他source原有的顺序输出,,底层是通过happensbefore原则保证了它的内存可见性

终端操作—toArray

源码:


    Object[] toArray();


    //  * The generator function takes an integer, which is the size of the
    //  * desired array, and produces an array of the desired size.  This can be
    //  * concisely expressed with an array constructor reference:
    <A> A[] toArray(IntFunction<A[]> generator);


使用


public class M1 {

    public static void main(String[] args) {

        Stream<String> stream1 = Stream.of(
                "a","dkkdk","1241","kdkdi","lpp"
        );

        Object[] objects1 = stream1.toArray();

        for(Object o:objects1){
            System.out.println(o);
        }

        System.out.println("--------------------");

        List<Integer> integers = Create_Data.supply_Integers();

        Object[] objects2 = integers.stream()
                .toArray();


        for(Object o:objects2){
            System.out.println(o);
        }

        System.out.println("--------------------");

        Object[] ob = Stream.of("A","B","C","D").toArray();
        for (Object o : ob) {
            System.out.println(o.toString());
        }


    }
}




public class M2 {


    public static void main(String[] args) {

        List<Person> people = Person.supply_S();

        Person[] peoplearray = people.stream()
                .filter(person -> person.getGender().equals("male"))
                .toArray(Person[]::new);

        for (Person person:peoplearray){
            System.out.println(person);
        }

        System.out.println("------------------");

        Integer[] integers = Stream.of(1, 2, 3, 4, 5).toArray(Integer[]::new);
        
    }
}


终端操作—reduce

源码:



    //  * @apiNote Sum, min, max, average, and string concatenation are all special
    //  * cases of reduction. Summing a stream of numbers can be expressed as:
    //  *
    //  * <pre>{@code
    //  *     Integer sum = integers.reduce(0, (a, b) -> a+b);
    //  * }</pre>
    //  *
    //  * or:
    //  *
    //  * <pre>{@code
    //  *     Integer sum = integers.reduce(0, Integer::sum);
    //  * }</pre
    T reduce(T identity, BinaryOperator<T> accumulator);

    Optional<T> reduce(BinaryOperator<T> accumulator);


     <U> U reduce(U identity,
                 BiFunction<U, ? super T, U> accumulator,
                 BinaryOperator<U> combiner);


先看第一个

官方API文档有这样一段:


U result = identity;
for (T element : this stream)
    result = accumulator.apply(result, element)
return result;

这就是一个累加器概念的体现:

一个reduce操作(也称为折叠)接受一系列的输入元素,并通过重复应用操作将它们组合成一个简单的结果


public class M1 {


//      * <pre>{@code
//     *     U result = identity;
//     *     for (T element : this stream)
//     *         result = accumulator.apply(result, element)
//                *     return result;
//     * }</pre>

    public static void main(String[] args) {

        List<Integer> l1 = Arrays.asList(1,2,3,4,5);

        //计算1,2,3,4,5 的和,并且初始值为3
        //也就是计算3+1+2+3+4+5
        System.out.println(
                l1.stream().reduce(
                        3,(i1,i2)->i1+i2
                )
        );

        System.out.println("------------------------");

        // 拆开分解

        BinaryOperator<Integer> f1 = (x,y)->x+y;

        Integer identity = 3;

        Integer result = identity;

        for (Integer integer:l1){

            result = f1.apply(result,integer);
        }

        System.out.println(result);

        //其实两种方式背后的思维方式是一样的
        //那就是
        //结果重新作为一个参数,不断地参与到运算之中,直到最后结束

        //只要能够理解了累计运算的概念
        //就可以完全理解Stream 中reduce方法
        //他就是一个不断累计运算的过程

        System.out.println("------------------------");
//计算 1*1*2*3*4*5 = 120
        System.out.println(
                l1.stream()
                .reduce(1,(x,y)->x*y)
        );

    }
}


第二个

因为存在stream为空的情况,所以第二种实现并不直接方法计算的结果,而是将计算结果用Optional来包装,我们可以通过它的get方法获得一个Integer类型的结果,而Integer允许null。第一种实现因为允许指定初始值,因此即使stream为空,也不会出现返回结果为null的情况,当stream为空,reduce为直接把初始值返回

使用


public class M2 {

//    This is equivalent to:
//       *     boolean foundAny = false;
//     *     T result = null;
//     *     for (T element : this stream) {
//     *         if (!foundAny) {
//     *             foundAny = true;
//     *             result = element;
//     *         }
//     *         else
//     *             result = accumulator.apply(result, element);
//     *     }
//     *     return foundAny ? Optional.of(result) : Optional.empty();
    public static void main(String[] args) {

        List<Integer> l1 = Create_Data.supply_Integers();

        System.out.println(l1);

        System.out.println("----------------------");

        System.out.println(
                l1.stream()
                .reduce((x,y) -> x + y)
                .get()
        );
    }
}


第三种

  • 与两个参数的reduce不同的地方在于类型
  • 双参数的返回类型为T Stream类型为T
  • 三参数的返回类型为U Stream类型为T 有了更大的发挥空间 T可能为U 也可能不是U

第三个参数用于在并行计算下 合并各个线程的计算结果

使用

public class M3 {

    public static void main(String[] args) {

        ArrayList<Integer> newList = new ArrayList<>();

        ArrayList<Integer> accResult_ = Stream.of(2, 3, 4)
                .reduce(newList ,
                        (acc, item) -> {
                            acc.add(item);
                            System.out.println("item: " + item);
                            System.out.println("acc+ : " + acc);
                            System.out.println("BiFunction");
                            return acc;
                        }, (acc, item) -> null);
        System.out.println("accResult_: " + accResult_);

//item: 2
//acc+ : [2]
//BiFunction
//item: 3
//acc+ : [2, 3]
//BiFunction
//item: 4
//acc+ : [2, 3, 4]
//BiFunction
//accResult_: [2, 3, 4]
    }
}


第三个参数定义的规则并没有执行。这是因为reduce的第三个参数是在使parallelStream的reduce操作时,合并各个流结果的,本例中使用的是stream,所以第三个参数是不起作用的。上述示例,提供一个只有一个元素1的arrayList,通过累加器迭代,将stream中的数据添加到arrayList中

终端操作—collect

源码:


//          This
//      * produces a result equivalent to:
//      * <pre>{@code
//      *     R result = supplier.get();
//      *     for (T element : this stream)
//      *         accumulator.accept(result, element);
//      *     return result;
//      * }</pre>


// * For example, the following will accumulate strings into an {@code ArrayList}:
//      * <pre>{@code
//      *     List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add,
//      *                                                ArrayList::addAll);
//      * }</pre>
//      *
//      * <p>The following will take a stream of strings and concatenates them into a
//      * single string:
//      * <pre>{@code
//      *     String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,
//      *                                          StringBuilder::append)
//      *                                 .toString();
 <R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);



//    * @apiNote
//      * The following will accumulate strings into an ArrayList:
//      * <pre>{@code
//      *     List<String> asList = stringStream.collect(Collectors.toList());
//      * }</pre>
//      *
//      * <p>The following will classify {@code Person} objects by city:
//      * <pre>{@code
//      *     Map<String, List<Person>> peopleByCity
//      *         = personStream.collect(Collectors.groupingBy(Person::getCity));
//      * }</pre>
//      *
//      * <p>The following will classify {@code Person} objects by state and city,
//      * cascading two {@code Collector}s together:
//      * <pre>{@code
//      *     Map<String, Map<String, List<Person>>> peopleByStateAndCity
//      *         = personStream.collect(Collectors.groupingBy(Person::getState,
//      *                                                      Collectors.groupingBy(Person::getCity)));
//      * }</pre>
 <R, A> R collect(Collector<? super T, A, R> collector);




第一个

supplier:一个能创造目标类型实例的方法。accumulator:一个将当元素添加到目标中的方法。combiner:一个将中间状态的多个结果整合到一起的方法(并发的时候会用到)

使用

public class M1 {

    public static void main(String[] args) {

        Stream<String> stream1 = Stream.of("asas","kdkkd","pp[p[","12121","O");

//        List<String> l1 = stream1.collect(ArrayList::new,ArrayList::add,ArrayList::addAll);

//        System.out.println(l1);

        System.out.println("--------------------");



        String concat1 = stream1.collect(StringBuilder::new, StringBuilder::append,
                 StringBuilder::append)
                    .toString();

        System.out.println(concat1);

        System.out.println("--------------------------------");

        List<Integer> l2 = Create_Data.supply_Integers();

        System.out.println(l2);

        System.out.println("--------------------------------");

        // 找出偶数 放入新的集合
        List<Integer> res1 = l2.stream()
                .filter(integer ->  integer % 2 == 0)
                .collect(
                        ()->new ArrayList<>(),
                        (list,item)->list.add(item),
                        (x,y)->x.addAll(y)
                );

        System.out.println(res1);

        System.out.println("--------------------------------");

        /* 或者使用方法引用 */

        List<Integer> res2 =l2.stream()
                .filter(integer ->  integer % 2 == 0)
                .collect(
                        ArrayList::new, List::add, List::addAll
                );

        System.out.println(res2);

    }
}


上面例子:

  • 第一个函数生成一个新的ArrayList(最后返回的也是这个)

  • 第二个函数的第一个参数是前面生成的ArrayList对象,第二个参数是stream中包含的元素,函数体就是把stream中的元素加入ArrayList对象中。第二个方法被反复调用直到原stream的元素被消费完毕

第二个

使用

public class M2 {


    public static void main(String[] args) {

        List<Integer> l1 = Create_Data.supply_Integers();

        List<Integer> res1 = l1.stream()
                .filter(integer -> integer>55)
                .collect(Collectors.toList());

        System.out.println(res1);

        /*输出*/
//        [79, 89, 65, 98, 74, 90, 75, 61]


    }
}


终端操作—min

源码:


    Optional<T> min(Comparator<? super T> comparator);

使用

public class M1 {


    public static void main(String[] args) {

        List<Integer> l1 = Create_Data.supply_Integers();

        System.out.println(l1);

        System.out.println("------------------------------");

        System.out.println(
                l1.stream()
                .min(Integer::compareTo).get()
        );

        System.out.println("------------------------------");


        System.out.println(
                l1.stream()
                .min(Comparator.comparing(Function.identity())).get()
        );

        List<String> strings1 = Create_Data.supply_Strings(10,5);

        System.out.println("------------------------------");

        System.out.println(strings1);

        System.out.println("------------------------------");


        System.out.println(
                strings1.stream()
                .min(Comparator.comparing(Function.identity())).get()
        );

        System.out.println("------------------------------");

        List<Person> personList = Person.supply_S();

        System.out.println(personList);

        System.out.println("------------------------------");


        System.out.println(
                personList.stream()
                .min(Comparator.comparing(Person::getAge)).get()
        );
        
    }
}

终端操作—max

源码:


    Optional<T> max(Comparator<? super T> comparator);

使用参照 min

终端操作—count

源码:


    //  * This is a special case of
    //  * a <a href="package-summary.html#Reduction">reduction</a> and is
    //  * equivalent to:
    //  * <pre>{@code
    //  *     return mapToLong(e -> 1L).sum();
    //  * }</pre>
    long count();

count方法用于统计Stream流中元素的个数,这是个终结方法,使用后无法使用其他Stream流

使用


public class M1 {


    public static void main(String[] args) {

        List<Integer> l1 = Create_Data.supply_Integers();

        System.out.println(
                l1.stream()
                .count()
        );

    }
}


终端操作—anyMatch allMatch noneMatch

源码:


    boolean anyMatch(Predicate<? super T> predicate);

    boolean allMatch(Predicate<? super T> predicate);

    boolean noneMatch(Predicate<? super T> predicate);


使用

public class M1 {

    public static void main(String[] args) {

        List<Integer> l1 = Create_Data.supply_Integers();

        // 是否有大于55的数字
        System.out.println(
                l1.stream()
                .anyMatch(integer -> integer> 55)
        );

// 是否全部都是大于33的数字
        System.out.println(
                l1.stream()
                .allMatch(integer -> integer>33)
        );

// 是否全部数字都不大于200
        System.out.println(
                l1.stream()
                .noneMatch(integer -> integer>200)
        );


    }
}


终端操作—findFirst findAny

源码:


    Optional<T> findFirst();

    Optional<T> findAny();

使用
public class M1 {

    public static void main(String[] args) {

        List<Integer> l1 = Create_Data.supply_Integers();

        System.out.println(l1);

        System.out.println("-------------------------");

        System.out.println(
                l1.stream()
                .findFirst()
                .get()
        );

        System.out.println("-------------------------");


        System.out.println(
                l1.stream()
                .findAny()
                .get()
        );
    }
}


发布了229 篇原创文章 · 获赞 62 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/Coder_py/article/details/104158775
今日推荐