Java中的小知识-----Stream流

Stream流完全不是I/O流,按照流水线处理方式来考虑代码中的思想;在JDK1.8之后,我们拥有了Lambda表达式,让代码的中心偏向解决实际问题,直达重点。Stream流中大量的使用了Lambda表达式

Stream流操作思想来自于生产线流水线这种方式,涉及到多步骤操作的情况下,
这里使用流水线思想进行车工需设计,然后按照设计的模型处理代码中的数据,
在数据处理的过程中,不浪费资源,没有过多的损耗,每一步操作的内容都是直切主题。
原材料从头到尾只会占用一份空间,中间过程不会占用空间,最后生成一个结果

Stream流有一些特征:

1.带有很多Stream流操作的方法,filter,limit,map,sorted,skip...这些方法大多是都会使用到函数式接口,有lambda表达式

2.整个Stream流模型操作过程中,只有执行到count,foreach这些方法,操作真正的执行中的模型,如果不存在结果导向,中级的所有操作是无效的,这里得益于Lambda表达式的延后性

3.Stream流是存在一定的管道性,pipelining流水线

操作使用Stream流

包:
    java.util.stream.Stream<T> JDK1.8新特征
    1.所有的Collection<T>集合都有对应的Stream();
    2.可以通过Stream类中的static Stream of()获取
        static Stream<T> of(T... t);
        static Stream<T> of(T t);
package com.wcc.b_streamget;

import java.util.*;
import java.util.stream.Stream;

/**
 * Stream流获取方式
 *      Collection集合
 *      Map双边队列
 *      数组
 * @Author kk
 * @Date 2020/3/12 11:16
 */
public class Demo1 {
    public static void main(String[] args) {
        //List接口获取对应的Stream类对象
        List<String> list = new ArrayList<>();
        //根据list保存元素的类型来约束对应的Stream类型操作所需类型
        Stream<String> stream = list.stream();

        //通过set集合获取对应的Stream流对象
        HashSet<String> set1 = new HashSet<>();
        Stream<String> stream1 = set1.stream();

        HashMap<String,String> map = new HashMap<>();
        //map双边队列中所有value对应的collection集合
        Set<String> KeySet = map.keySet();
        Stream<String> stream2 = KeySet.stream();

        //Map双边队列中所有value对应的Collection集合
        Collection<String> values = map.values();
        Stream<String> stream3 = values.stream();

        //map中有一个方法,可以获取所有键值对类型的set集合
        //Entry ==》键值对,是Map接口的一个成员接口
        Set<Map.Entry<String,String >> entrySet = map.entrySet();
        //获取Map键值对集合的Stream流对象
        Stream<Map.Entry<String ,String>> stream4 = entrySet.stream();

        //使用不定长参数获取对应的Stream流对象
        Stream<String> stringStream = Stream.of("江坤", "小坤坤", "小江同学");
        
        String[] arr = {"江","坤坤","江坤坤"};
        Stream<String> arrStream = Stream.of(arr);
        
    }
}

Stream流常用方法

延迟方法:

返回值类型依然是Stream接口本身,并没有影响我们操作的真正资源

允许链式操作:filter(XXX).limit(XXX).sorted(XXX)

终结方法:

返回值类型不是Stream接口本身,要么处理数据,要么返回其他类型数据,并且不再支持Stream流对象链式操作。count,foreach

foreach方法:【终结方法】

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

/*
    终结方法:
        需要一个Consumer接口进行操作处理,消耗一个数据
        Consumer接口是一个【函数式接口】那就可以使用Lambda表达式
        
        
*/

 

filter方法

Stream<T> filter(Predicate<? super T> filter);
/*
    filter是过滤方法,需要的参数是Predicate接口,Predicate是一个函数式接口,可以直接使用Lambda表达运行。
    这里返回值类型是Stream类对象,是经过过滤之后的Stream类型,可以进行链式操作
    Predicate接口中需要实现的方法
        boolean test(T t);

*/

map方法

<R> String<R> map(Function<? super T, ? super R> fun);
/*
    类型转换操作,得到的是一个类型转换之后数据类型的Stream流对象
    这里需要的参数是Function函数式接口
        R apply(T t);
        T类型的数据转换成R类型
*/

 

count方法【终结方法】

int count();
/*
    返回当前Stream流对象中有多少个元素
    类似有Collection接口下的size().String的length();
    【终结方法】
        一旦执行Stream流对象被关闭

*/

limit方法

Stream<T> limit(long maxSize);
/*
    对于当前Stream流对象操作的数据进行限制操作,限制个数到maxSize
    例如:
        Stream流中保存的有10个元素,limit 5 ==> 前五个元素

*/

skip方法

Stream<T> skip(long index);
/*
    返回值依然是一个Stream流对象,这里跳过当前Stream

*/

concat方法

static Stream<T> concat(Stream<? extends T>a , Stream<? extends T>b);
/*
    拼接两个Stream流对象,是一个静态方法,得到新的Stream流对象

*/

原始操作方式和Stream流方式对比

1.一个String类型的字符串集合,类似:“1 , 中国 , 16"
2.过滤掉没有5的数据
3.跳过前三个数据
4.限制得到前五个数据
5.两个String类型集合字符串合并
6.转换成Person类型
7.展示数据

方法引用

Lambda冗余问题

方法引用的一些小要求

1.明确对象
    对象是调用者,可以是类对象,类名,super,this,构造方法,数组构造方法
2.明确的执行方法
    该方法只有名字,不需要显式参数
3.需要处理的数据【联想推导和省略】
4. :: 方法引用格式

通过类对象来执行方法引用

1.明确对象 => 类对象
2.明确执行的方法 =>自定义
3.处理的数据 => 简单要求为String类型

代码:

package com.wcc.d_Lambda;

/**
 * @Author kk
 * @Date 2020/3/12 16:18
 */

/**
 * 自定义类
 */
class ObjectMethodReference{
    //展示字符串
    public void print(String str){
        System.out.println(str.toLowerCase());
    }
}

/**
 * 函数式接口,目标是明确约束方法;方法类型是
 *      处理String类型参数
 *      没有返回值
 */
@FunctionalInterface
interface Printable{
    void print(String str);
}
public class Demo2 {
    public static void main(String[] args) {
        /*
            test方法中需要使用一个Printable接口,执行对应的print方法
            这里需要引用ObjectMethodReference类对象对应的print方法,该方法有展示能力
         */
        ObjectMethodReference obj = new ObjectMethodReference();
        /*
            执行的对象:
                ObjectMethodReference的类对象
            明确执行的方法:
                print方法
            执行的目标:
                “ABCED” 可省略,可推导
         */
        test(obj::print);

    }

    /**
     *
     * @param printable 函数式接口,约束的是方法类型
     */
    public static void test(Printable printable){
        printable.print("ABCDED");
        printable.print("FGHJKL");
    }
}

通过类名来执行方法引用

package com.wcc.d_Lambda;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author kk
 * @Date 2020/3/12 16:39
 */

/**
 * 函数式接口
 */
@FunctionalInterface
interface PrintList{
    /**
     * 方法参数为list的集合
     * 没有返回值
     * @param list List集合
     */
    void print(List<?> list);
}

/**
 *
 */
class MethodReference{
    /**
     * 该方法符合要求
     * 没有返回值
     * @param list List集合
     */
    public static void showListInfo(List<?> list){
        for (Object o : list) {
            System.out.println(o);
        }
    }
}

/**
 * 通过类名来执行方法引用
 */
public class Demo3 {
    public static void main(String[] args) {
        /*
            明确调用对象
                当前方法是一个静态方法,需要通过类名调用
            明确调用方法
                showListInfo
            明确的数据
                ArrayList<String> list = new ArrayList<>();
                可省略可推导
         */
        testClass(MethodReference::showListInfo);
        
        testClass(list -> {
            for (Object o : list) {
                System.out.println(o);
            }
        });
    }
    /**
     * 利用了一个函数式接口做欸方法的参数
     * @param printList 函数式接口
     */
    public static void testClass(PrintList printList){
        ArrayList<String> list = new ArrayList<>();

        list.add("BMW");
        list.add("Audi");

        printList.print(list);
    }
}

通过super关键字执行方法引用

Father类

package com.wcc.d_Lambda;

/**
 * @Author kk
 * @Date 2020/3/12 19:07
 */
public class Father {
    public void sayHello(){
        System.out.println("你好 Java");
    }
}

函数式接口:

package com.wcc.d_Lambda;

/**
 * @Author kk
 * @Date 2020/3/12 19:06
 */
public interface SaySomeThing {
    void say();
}

Son类

package com.wcc.d_Lambda;

/**
 * @Author kk
 * @Date 2020/3/12 19:07
 */
public class Son extends Father{
    public static void main(String[] args) {
        //Lambda表达式
        testSay(() -> System.out.println("你好"));
        new Son().sonMethod();

    }

    /**
     * 这里的参数是一个函数式接口,这里需要提供一个符合要求的方法
     * @param sst 函数式接口参数
     */
    public static void testSay(SaySomeThing sst){
        sst.say();
    }
    public void sonMethod(){
        /*
            父类中有一个无参数无返回值的sayHello
            满足当前SaySomeThing函数式接口,方法要求:
            执行的对象
                super关键字,因为该方法在父类内
            执行的方法
                sayHello
            无需参数

         */
        testSay(super::sayHello);
    }

}

通过this关键字执行方法引用

ORM接口

package com.wcc.e_this;

/**
 * @Author kk
 * @Date 2020/3/12 19:13
 */
public interface ORM {
    /**
     * int => String
     * @param i int类型
     * @return String类型
     */
    String toStringType(int i);
}

ThisDemo类

package com.wcc.e_this;

/**
 * @Author kk
 * @Date 2020/3/12 19:15
 */
public class ThisDemo {
    public void test(){
        String s = testThis(i -> i + ":");
        System.out.println(s);
        
        /*
            调用方法的对象
                this
            执行的方法
                turn方法
            处理的数据
                10(可省略,可联想)
         */
        String s1 = testThis(this::turn);
    }
    public String turn(int i){
        return i + ":字符串";
    }
    public static String testThis(ORM orm){
        return orm.toStringType(10);
    }

    public static void main(String[] args) {
        new ThisDemo().test();
    }
}
发布了22 篇原创文章 · 获赞 34 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42597414/article/details/104812423