java32-Stream流-生成方式-中间操作方式(filter-limit-skip-concat-distinct-sorted-map-mapToInt)-终结操作-收集操作

初识Stream流

Stream流把真正的函数式编程风格引入到java中
案例:需求:
创建集合,存储多个字符串元素;把集合中“张”开头的字符串存储到另外的集合中;把“张”开头的集合中的长度大于3的元素存储到另外集合中;遍历上一步得到的集合。

package itiheima314.test5;

public class StreamDemo {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<String>();

        array.add("林俊杰");
        array.add("张信哲");
        array.add("王一博");
        array.add("许嵩");
        array.add("张杰");
        array.add("张艺兴");

        ArrayList<String> zhang = new ArrayList<String>();
        for(String s:array){
            if(s.startsWith("张")){
                zhang.add(s);
            }
        }
        System.out.println( "zhang集合:"+zhang);

        ArrayList<String> zhang3 = new ArrayList<String>();
        for(String s :zhang){
            if(s.length() == 3){
                zhang3.add(s);
            }
        }
        System.out.println("zhang3集合:" + zhang3);
        System.out.println("-----------");

        // 使用stream流实现
        array.stream().filter(s->s.startsWith("张")).filter(s-> s.length() == 3).forEach(s-> System.out.println(s));
        * 注意:
        * 意思:array.stream生成流、过滤张、过滤长度为3、forEach逐一打印
        // 使用引用类方法简化
        System.out.println("简化");
        array.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==3).forEach(System.out::println);
    }
}

注意

2022/4/22
String类中的startsWith方法
boolean startsWith(String prefix) 判断此字符串是否以指定的前缀prefix开头

Stream流的生成方式

Stream的使用:

1 生成流
	通过数据源(集合、数组等)生成流
	list.stream()
2 中间操作
	一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,
	做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用。
	filter()
3 终结操作
	一个流只能有一个终结操作,当这个操作执行后,流就被使用“光”了,无法再被操作。
	forEach()

Stream流的返回值是:Stream < T > streamName
Stream流的常见生成方式

1 Collection体系的集合可以使用默认方法stream()生成流
	default Stream< E > stream()
	// 集合.stream();
2 Map 体系的集合间接的生成流
	可以使用方法keySet方法、values方法、entrySet方法
	// 集合.keySet().stream();
3 数组可以通过Stream接口的静态方法of(T...values)生成流
	其中静态方法of(T....values)是可变参数。
	Stream.of(T...values)
	// Stream.of(数组);

代码:

package itiheima314.test5;

public class StreamDemo1 {
    public static void main(String[] args) {
        * Collection体系的集合可以使用默认方法stream()生成流
        // List 和 Set 是Collection的儿子 还有一个Queue
        List<String> list = new ArrayList<String>();
        Stream<String> listStream = list.stream();

        Set<String> set = new HashSet<String>();
        Stream<String> setStream = set.stream();

        * Map 体系的集合间接的生成流
        Map<String,Integer> map = new HashMap<String, Integer>();
        Stream<String> keyStrem = map.keySet().stream();
        // map.ksySet得到是 键的集合,集合通过stream方法可以得到stream流
        Stream<Integer> valueStream = map.values().stream();
        // map.values 得到 值的集合,集合通过stream方法可以得到stream流
        Stream<Map.Entry<String, Integer>> kvStream = map.entrySet().stream();
        // map.entrySet 得到键值对 对象的集合

        * 数组可以通过Stream接口的静态方法of(T...values)生成流
        String[] strArray = {"you","are","my","pretty","sunshine"};
        Stream<String> strArray1 = Stream.of(strArray);
        Stream<String> strStream2 = Stream.of("hello", "world");
        Stream<Integer> integerStream = Stream.of(10, 20, 30);
    }
}

Stream流的中间操作方式

中间操作方法:

方法名说明
Stream < T > filter(Predicate predicate)用于对流中的数据进行过滤
Predicate接口中的抽象方法,boolean test(T t):对给定的参数进行操作,返回一个布尔值
filter参数采用Lambda表达式,因为参数满足 是一个接口,且只有一个抽象方法test
Stream< T > limit(long maxSize)返回此流中的元素组成的流,截取前指定参数个数的数据
Stream< T > skip(long n)跳过指定参数个数的数据,返回由该流的剩余元素组成的流
static < T > Stream < T > concat(Stream a,Stream b)合并a和b两个流为一个流
Stream< T > distinct()返回由该流的不同元素(Object.equals(Object))组成的流
Stream< T > sorted()返回由此流的元素组成的流,根据自然顺序排序
Stream< T > sorted(Comparator comparator返回由该流的元素组成的流,根据提供的Comparator进行排序
Comparator接口中的方法 int compare(T o1,T o2)
< R > Stream < R > map(Function mapper)返回由给定函数应用于此流的元素的结果组成的流
Function接口中的方法 R apply(T t)
IntStream mapToInt(ToIntFunction mapper)返回一个IntStream,其中包含将给定函数应用于此流的元素的结果
IntStream 表示原始int流ToIntFunction接口中的方法 int applyAsInt(T value)
其中IntStream接口中有方法int sum() 返回此流中元素的总和
案例1:filter
package itiheima314.test5;

public class StreamDemo2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();

        list.add("林俊杰");
        list.add("张信哲");
        list.add("王一博");
        list.add("胡夏");
        list.add("张杰");
        list.add("张艺兴");

        * 需求1:把list集合中的以张开头的元素在控制台输出
        // 流生成方式1 Collection集合中静态方法Stream方法
        list.stream().filter((String s) -> s.startsWith("张")).forEach((String s)-> System.out.println(s));
        // 省略 引用类的方法 对象::实例方法
        list.stream().filter(s->s.startsWith("张")).forEach(System.out::println);
        System.out.println("-----------------");
        * 需求2:把list集合中长度为3的元素在控制台输出
        // 对象::实例方法
        list.stream().filter(s->s.length() == 3).forEach(System.out::println);

        System.out.println("------");
        * 需求3:把list集合中以张开头,长度为3的元素在控制台输出
        list.stream().filter(s->s.startsWith("张")).filter(s->s.length() == 3).forEach(System.out::println);
    }
}
案例2:limit skip
package itiheima314.test5;

public class StreamDemo3 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();

        list.add("林俊杰");
        list.add("张信哲");
        list.add("王一博");
        list.add("胡夏");
        list.add("张杰");
        list.add("张艺兴");

        * 需求1:取前三个数据在控制台输出
        list.stream().limit(3).forEach(System.out::println);
        // 输出结果是:林俊杰 张信哲 王一博
        System.out.println("-------");
        
        * 需求2:跳过3个数据,把剩下的元素在控制台输出
        list.stream().skip(3).forEach(System.out::println);
        // 输出结果是:胡夏 张杰 张艺兴
        System.out.println("-----");
        
        * 需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
        list.stream().skip(2).limit(2).forEach(System.out::println);
        // 输出结果:王一博 胡夏
    }
}
案例3:dictinct concat
package itiheima314.test5;

public class StreamDemo4 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();

        list.add("林俊杰");
        list.add("张信哲");
        list.add("王一博");
        list.add("胡夏");
        list.add("张杰");
        list.add("张艺兴");

        * 需求1:取前4个数组成一个流
        Stream<String> s1 = list.stream().limit(4);
        
        * 需求2:跳过2个数据组成一个流
        Stream<String> s2 = list.stream().skip(2);
        
        * 需求3:合并需求1和需求2得到的流,并把结果在控制台输出
        Stream.concat(s1, s2).forEach(System.out::println);
        
        * 需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
        // 输出:林俊杰 张信哲 王一博 胡夏 王一博 胡夏 张杰 张艺兴
        System.out.println("---------");
        Stream.concat(s1, s2).distinct().forEach(System.out::println);
        // 输出结果:林俊杰 张信哲 王一博 胡夏 张杰 张艺兴
      
    }
}

注意

2022/4/22
同时执行两个forEach流终端操作会报错,IllegalStateException: stream has already been operated upon or closed
流只能运行终端流操作一次
案例4:sorted
package itiheima314.test5;

public class StreamDemo5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();

        list.add("linqingxia");
        list.add("zhangmanyu");
        list.add("wangzuxian");
        list.add("liuyan");
        list.add("zhangmin");
        list.add("zhagnwuji");

        * 需求1:按照字母顺序把数据在控制台输出
        list.stream().sorted().forEach(System.out::println);
        // 输出结果 :首字母相同的时候,按照添加顺序输出
        //linqingxia
        //liuyan
        //wangzuxian
        //zhangmanyu
        //zhangmin
        //zhangwuji

        * 需求2:按照字符串长度把数据在控制台输出
        // 匿名内部类
        list.stream().sorted(new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        }).forEach(System.out::println);
        // 输出结果有问题:其中 后三个没有按照字母顺序排 而是按照添加顺序
        //liuyan
        //zhangmin
        //zhangwuji
        //linqingxia
        //zhangmanyu
        //wangzuxian
        
        // Lambda表达式
//        list.stream().sorted((s1,s2)->s1.length()-s2.length()).forEach(System.out::println);

        * 按长度排序,长度相同 按照自然顺序排
        list.stream().sorted((s1,s2)->{
            int sum = s1.length()-s2.length();
            int sum2 = sum == 0?s1.compareTo(s2):sum;
            return sum2;
        }).forEach(System.out::println);
        // 输出结果:
		//liuyan
        //zhangmin
        //zhangwuji
        //linqingxia
        //wangzuxian
        //zhangmanyu
    }
}
案例5:map mapToInt
package itiheima314.test5;
public class StreamDemo6 {
    public static void main(String[] args) {
         ArrayList<String> array = new ArrayList<String>();

         array.add("10");
         array.add("20");
         array.add("30");
         array.add("40");
         array.add("50");
         
         * 需求:将集合中的字符串数据转化为整数之后在控制台输出
//        array.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
//        array.stream().map(Integer::parseInt).forEach(System.out::println);
        // 方法引用 分别是 类的方法(类名::静态方法)、对象的实例方法(对象的成员方法)

//        array.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
        // mapToInt方法的返回值类型是 IntStream 其中有个int sum()方法 返回此流中元素的总和。
        int result = array.stream().mapToInt(Integer::parseInt).sum();
        System.out.println(result);
        // 输出结果150
    }
}

Stream流的常见终结操作方法forEach/count

方法名说明
viod forEach(Consumer action)对此流的每个元素执行操作
Consumer接口中的抽象方法 void accept(T t)对给定的参数执行此操作
long count()返回此流中的元素个数
案例:
package itiheima314.test5;
public class StreamDemo7 {
    public static void main(String[] args) {
        ArrayList<String> list= new ArrayList<String>();

        list.add("林俊杰");
        list.add("张信哲");
        list.add("王一博");
        list.add("刘维");
        list.add("张杰");
        list.add("张艺兴");

        * 需求1:把集合中的元素在控制台输出
//        list.stream().forEach(System.out::println);

        * 需求2:统计集合中有几个以张开头的元素,并把统计结果在控制台输出
        long result = list.stream().filter(s -> s.startsWith("张")).count();
        System.out.println(result);
        // 输出结果是3
    }
}

Stream流练习

需求:
有两个ArrayList集合,分别存储6名男演员和6名女演员名称,完成如下操作:

1 男演员只要名字为三个字的前三个人
	Stream<String> manList = list.stream().filter(s -> s.length() == 3).limit(3);
2 女演员只要姓林的,并且不要第一个人
	Stream<String> womanList = list.stream().filter(s ->s.startsWith("林")).skip(1);
3 把过滤后的男演员名字和女演员名字合并在一起
	Stream<String> streamList = concat(manList,womanList);
4 把上一个步操作后的元素作为构造方法的参数创建演员对象,遍历数据
	streamList.map(Actor::new).forEach(s -> System.out.println(s.getName()));
演员类Actor,有一个成员变量,一个带参构造方法,以为其对应的get/set方法
package itiheima314.test6;
public class StreamDemo {
    public static void main(String[] args) {
        // 创建集合
        ArrayList<String> manList = new ArrayList<String>();
        manList.add("周润发");
        manList.add("成龙");
        manList.add("刘德华");
        manList.add("吴京");
        manList.add("周星驰");
        manList.add("李连杰");

        ArrayList<String> womanList = new ArrayList<String>();
        womanList.add("林心如");
        womanList.add("张嘉倪");
        womanList.add("林黛玉");
        womanList.add("柳岩");
        womanList.add("林志玲");
        womanList.add("王祖贤");

        // 1 男演员只要名字为三个字的前三个人
        Stream<String> manStream = manList.stream().filter(s->s.length() ==3).limit(3);
        // 2 女演员只要姓林的,并且不要第一个人
        Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
        // 3 把过滤后的男演员名字和女演员名字合并在一起
        Stream<String> conStream = Stream.concat(manStream, womanStream);
        // 4 把上一个步操作后的元素作为构造方法的参数创建演员对象,遍历数据
//        conStream.map(Actor::new).forEach(System.out::println);
        // 引用方法是 引用构造器 = 类::构造方法
        conStream.map(Actor::new).forEach(p-> System.out.println(p.getName()));
    }
}

Stream流的收集操作

  • 对数据使用Stream流的方式后,把流中的数据收集到集合中,收集方法是:R collect(Collector collector)
  • 参数Collector 是一个接口interface,interface Collector< T,A,R >
  • 工具类Collectors类实现了各种有用的还原操作的Collector
  • Collector类提供了具体的收集方法:
方法名说明
public static < T > Collector toList()把元素收集到List集合中
public static < T > Collector toSet()把元素收集到Set集合中
public static < T > Collector toMap(Function keyMapper,Function valueMapper)把元素收集到Map集合中
toMap的参数必须是key

案例:

package itiheima314;
public class test7 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("林俊杰");
        list.add("张信哲");
        list.add("王一博");
        list.add("刘维");

          * 需求1:得到名字为三个字的流
//        Stream<String> stringList = list.stream().filter(s -> s.length() == 3);

          * 需求2:把使用Stream流操作完毕的数据收集到List集合中
//        List<String> names = stringList.collect(Collectors.toList());
//        for(String name:names ){
//            System.out.println(name);
//        }

        Set<Integer> set = new HashSet<Integer>();
        set.add(10);
        set.add(20);
        set.add(30);
        set.add(33);
        set.add(35); 
		  * 需求3:年龄大于25的流
//        Stream<Integer> integerStream = set.stream().filter(a -> a > 25);

		 * 需求4:把使用Stream流操作完毕的数据收集到Set集合中
//        Set<Integer> ages = integerStream.collect(Collectors.toSet());
//        for(Integer age : ages){
//            System.out.println(age);
//        }

        String[] strArray = {"林俊杰,30","张信哲,35","王一博,33","刘维,25"};
        * 需求5:字符串中年龄大于28的流
        Stream<String> ageStream = Stream.of(strArray).filter(s ->
            Integer.parseInt(s.split(",")[1]) >28 );
            
        * 需求6:把使用Stream流操作完毕的数据收集到Map集合中,并遍历
        Map<String,Integer> map = ageStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));

        Set<String> keySet = map.keySet();
        for(String key:keySet){
            Integer value = map.get(key);
            System.out.println("姓名:" + value + ", " + "年龄:" + key);
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值