3.Stream流的中间方法

一.Stream流的中间方法:

1.distinct方法底层依赖hashCode方法和equals方法去重,使用时对于自定义数据类型根据需求重写hashCode方法和equals方法(注:基本数据类型和字符串类型不需要重写hashCode方法和equals方法就可以实现去重)。distinct方法底层利用HashSet集合进行去重,所以除了字符串类型外的自定义类型要根据需求重写hashCode方法和equals方法;

2.concat方法用于合并两个流,这两个流的数据类型尽可能的保持一致,如果数据类型不一致,那么最终的数据类型就是这两个流共同的父类类型,相当于进行了类型提升,导致无法使用子类里特有的功能;

3.map方法里的参数mapper是接口类型Function<T, R>,而且该接口是函数式接口,因此可用lambda表达式:

解析接口类型Function<T, R>:T表示流里原本的类型,R表示之后要转成的类型,方法apply的形参s依次表示流里面的每一个数据,方法apply的返回值表示转换之后的数据(注:T和R是泛型,不能是基本数据类型,如果写基本数据类型的话要用包装类,如int要用Integer)

4.concat方法是静态方法,因此可以类名.方法名进行调用:

5.filter方法里的形参predicate的数据类型是函数式接口,因此可以先写匿名内部类,再用lambda表达式进行优化:

6.stream流中间方法的特点是调用完stream流的中间方法后还可以继续使用stream流里的其他方法。


二.代码演示:

1.filter方法(过滤):

package com.itheima.a01mystream;
​
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
​
public class StreamDemo6 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        //注:修改Stream流中的数据,不会影响原来集合或者数组中的数据
​
        //1.filter:过滤->把"张"开头的留下,其余数据过滤不要
        list.stream().filter(new Predicate<String>() {  //list.stream()意思是获取Stream流,并把数据放到Stream流当中
            @Override
            public boolean test(String s) {  //形参s代表流中的每一个数据
                boolean flag=s.startsWith("张"); //startsWith返回布尔类型,是"张"开头返回true,不是返回false
                return flag; //返回false,表示当前数据舍弃;返回true,表示当前数据保留
            }
        }).forEach(s-> System.out.println(s)); //打印结果
        /*注:打印结果里的s是forEach里的s,不是test方法里的s*/
    }
}
上述例子中filter方法的方法体只是用来指定过滤掉哪些数据,对于集合中的数据类型不会改变,打印集合依旧是打印集合中剩余的数据。
注:Predicate是函数式接口,上例中由于是在流里new的Predicate接口,所以Predicate接口的泛型和流里的数据的类型要保持一致,此时list集合获取的stream流,所以流里的数据的类型就是list集合的类型即String型,所以Predicate接口的泛型是String型

new Predicate<String>()用到了匿名内部类,可用lambda表达式优化:

package com.itheima.a01mystream;
​
import java.util.ArrayList;
import java.util.Collections;
​
public class StreamDemo6 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        //注:修改Stream流中的数据,不会影响原来集合或者数组中的数据
​
        //1.filter:过滤->把"张"开头的留下,其余数据过滤不要
        list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
        /*s依次表示流水线上的数据,s.startsWith("张")表示开始过滤不需要的数据,以"张"开头的留下 */
    }
}
​

代码折行(折行处回车即可折行),可提高链式编程代码的可读性:

package com.itheima.a01mystream;
​
import java.util.ArrayList;
import java.util.Collections;
​
public class StreamDemo6 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        //注:修改Stream流中的数据,不会影响原来集合或者数组中的数据
​
        //1.filter:过滤->把"张"开头的留下,其余数据过滤不要
        list.stream().
                filter(s -> s.startsWith("张")).
                forEach(s -> System.out.println(s));
        /*s依次表示流水线上的数据,s.startsWith("张")表示开始过滤不需要的数据,以"张"开头的留下 */
    }
}

注:String类里的startsWith方法和endsWith方法

2.中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程:

例如:

package com.itheima.a01mystream;
​
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
​
public class StreamDemo6 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        //注:修改Stream流中的数据,不会影响原来集合或者数组中的数据
        
        Stream<String> stream1 = list.stream().filter(s -> s.startsWith("张"));/*留下以"张"开头*/
        Stream<String> stream2 = stream1.filter(s -> s.length() == 3);/*留下长度为3,stream1调用了方法即使用了stream1。stream流只能用一次,因此stream1之后不能再用了*/
        stream2.forEach(s -> System.out.println(s));/*遍历,stream2调用了方法即使用了stream2。stream流只能用一次,因此stream2之后不能再用了*/
        /*注:之后stream1和stream2这两个流就不能再用了,这样使得代码占用内存较大,因此可使用链式编程节省内存 */
    }
}
​

3.修改Stream流中的数据,不会影响原来集合或者数组中的数据:

例如:

package com.itheima.a01mystream;
​
import java.util.ArrayList;
import java.util.Collections;
​
public class StreamDemo6 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        //注:修改Stream流中的数据,不会影响原来集合或者数组中的数据
​
        //1.filter:过滤->把"张"开头的留下,其余数据过滤不要
        list.stream().
                filter(s -> s.startsWith("张")).
                forEach(s -> System.out.println(s));
        /*s依次表示流水线上的数据,s.startsWith("张")表示开始过滤不需要的数据,以"张"开头的留下 */
​
        System.out.println("========================================");
        System.out.println(list);
        /*运行结果为[张无忌, 周芷若, 赵敏, 张强, 张三丰, 张翠山, 张良, 王二麻子, 谢广坤]
          集合中的数据没发生改变*/
    }
}

4.limit方法(获取前几个元素):

package com.itheima.a01mystream;
​
import java.util.ArrayList;
import java.util.Collections;
​
public class StreamDemo6 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        //注:修改Stream流中的数据,不会影响原来集合或者数组中的数据
        
       //2.limit:获取前几个元素
       list.stream().
               limit(3). //3代表获取前3个元素,不是索引
               forEach(s -> System.out.println(s)); //遍历
    }
}

5.skip方法(跳过前几个元素):

package com.itheima.a01mystream;
​
import java.util.ArrayList;
import java.util.Collections;
​
public class StreamDemo6 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        //注:修改Stream流中的数据,不会影响原来集合或者数组中的数据
​
       //3.skip:跳过前几个元素
       list.stream().
               skip(4). //4代表跳过前4个元素
               forEach(s -> System.out.println(s)); //遍历
    }
}

6.练习:

package com.itheima.a01mystream;
​
import java.util.ArrayList;
import java.util.Collections;
​
public class StreamDemo6 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        //注:修改Stream流中的数据,不会影响原来集合或者数组中的数据
        
       //练习:获取 "张强","张三丰","张翠山" 这3个元素
       /*方法一:先获取前6个元素,再跳过前3个元素*/
       list.stream().limit(6).skip(3).forEach(s -> System.out.println(s));
       /*方法二:先跳过前3个元素,再获取前3个元素*/
       list.stream().skip(3).limit(3).forEach(s -> System.out.println(s));
    }
}

7.distinct方法(元素去重,依赖hashCode和equals方法):

package com.itheima.a01mystream;

import java.util.ArrayList;
import java.util.Collections;

public class StreamDemo7 {
    public static void main(String[] args) {
        ArrayList<String> list1=new ArrayList<>();
        Collections.addAll(list1,"张无忌","张无忌","张无忌","张强","张三丰","张翠山","张良","王二麻子","谢广坤");

        list1.stream().distinct().forEach(s -> System.out.println(s));
        /*运行结果为 张无忌
                    张强
                    张三丰
                    张翠山
                    张良
                    王二麻子
                    谢广坤 */
    }
}

8.concat方法(合并a和b两个流为一个流):

package com.itheima.a01mystream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;

public class StreamDemo7 {
    public static void main(String[] args) {
        ArrayList<String> list1=new ArrayList<>();
        Collections.addAll(list1,"张无忌","张无忌","张无忌","张强","张三丰","张翠山","张良","王二麻子","谢广坤");

        ArrayList<String> list2=new ArrayList<>();
        Collections.addAll(list2,"周芷若","赵敏");

        Stream.concat(list1.stream(),list2.stream()). //合并list1流和list2流
                forEach(s -> System.out.println(s));//遍历
        /*list1.stream()调用了stream()才成为了流 */

    }
}

9.map方法(转换流中的数据类型):

普通:
package com.itheima.a01mystream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class StreamDemo8 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌-15","周芷若-14","赵敏-13","张强-20",
                "张三丰-100","张翠山-40","张良-35","王二麻子-37","谢广坤-41");

        //要求:只获取里面的年龄并进行打印
        //获取stream流
        Stream<String> stream = list.stream();
        //遍历
        stream.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) { //s代表集合的每一个元素
                String[] result = s.split("-");
                System.out.println(result[1]);
            }
        });
    }
}

注:Consumer接口是一个函数式接口

用lambda表达式优化:

package com.itheima.a01mystream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;

public class StreamDemo8 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌-15","周芷若-14","赵敏-13","张强-20",
                "张三丰-100","张翠山-40","张良-35","王二麻子-37","谢广坤-41");

        //需求:只获取里面的年龄并进行打印
        //获取stream流
        Stream<String> stream = list.stream();
        //遍历
        stream.forEach(s -> { //s代表集合的每一个元素
                String[] result = s.split("-");
                System.out.println(result[1]);
            }
        );
    }
}

注:String类里的split方法,用于切割字符串

split方法举例:

public class Main {
    public static void main(String[] args) {
        String s="1-2-3";
        String[] arr = s.split("-"); //代表要用-切割字符串s,结果为数组,但结果不包括-
        for (String result : arr) {
            System.out.printf("%s,",result);
        }
        //运行结果为1,2,3,

    }
}
高级:
package com.itheima.a01mystream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;

public class StreamDemo8 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌-15","周芷若-14","赵敏-13","张强-20",
                "张三丰-100","张翠山-40","张良-35","王二麻子-37","谢广坤-41");

        //需求:只获取里面的年龄并进行打印
         /*相当于字符串里提取数字:String -> int*/
        /*第一个类型:流中原本的类型
          第二个类型:之后要转成的类型*/
        //apply的形参s:依次表示流里面的每一个数据
        //返回值:表示转换之后的数据
        list.stream().map(new Function<String, Integer>() { //要用泛型
            @Override
            public Integer apply(String s) { //这个s表示集合里的每一个数据如张无忌-15
                //1.切割:比如张无忌-15切割为张无忌和15,此时结果为数组,0索引上为张无忌,1索引上为15
                String[] arr = s.split("-");
                //2.获取年龄:但是为字符串
                String ageString = arr[1];
                //3.转换为int型,可利用int型的包装类Integer里的parseInt方法
                int age = Integer.parseInt(ageString);
                return age; //返回整型,所以apply方法的返回类型用整型Integer
            }
        }).forEach(s -> System.out.println(s));
        /*当map方法执行完毕之后,流上的数据就变成了整数,
        所以在调用forEach方法中,s依次表示流里面的每一个数据,这个数据现在就是整数了*/
    }
}

用lambda表达式优化:

package com.itheima.a01mystream;

import java.util.ArrayList;
import java.util.Collections;

public class StreamDemo8 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌-15","周芷若-14","赵敏-13","张强-20",
                "张三丰-100","张翠山-40","张良-35","王二麻子-37","谢广坤-41");

        //需求:只获取里面的年龄并进行打印
         /*相当于字符串里提取数字:String -> int*/
        /*第一个类型:流中原本的类型
          第二个类型:之后要转成的类型*/
        list.stream().
                map(s -> Integer.parseInt( s.split("-")[1] )). //这个s表示集合里的每一个数据如张无忌-15
                forEach(s -> System.out.println(s)); //这个s就是最终要的年龄
        //s.split("-")结果为字符串数组,s.split("-")[1]表示获取字符串数组1索引上的元素
        //s.split("-")[1]是字符串型,Integer.parseInt( s.split("-")[1]为整型
    }
}

注:Integer类里的parseInt方法可以把字符串转化为整数,parseInt方法是静态方法,可以类名.方法名进行调用,也可以使用类名::静态方法名(方法引用)进行调用


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值