美文网首页
Java-8-Stream接口

Java-8-Stream接口

作者: Cool_Pomelo | 来源:发表于2020-02-03 16:52 被阅读0次

    Java-8-Stream接口

    interface Stream<T>

    思维导图:

    Stream T .png

    生成 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()
            );
        }
    }
    
    
    

    相关文章

      网友评论

          本文标题:Java-8-Stream接口

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