Java---Stream流详解

目录​​​​​​​

一、Stream流详解

二、Stream流的获取

(1)单列集合

(2)双列集合

(3)数组

(4)一些零散数据

三、Stream流中常用的API方法

(1)中间方法

(2)终结方法

(3)收集方法


一、Stream流详解

Stream流其实就相当于是工厂上的流水线,后面会对数据更好的进行操作,如打印,过滤等等。说到底把它比作是工厂上的流水线还是很形象的。

二、Stream流的获取

    获取方式       方法名                                          说明

  单列集合         default<E>stream()                            collection中的默认方法
  双列集合         无                                            无法直接使用stream流 
  数组             public static<T>Stream<T>stream(T[] array)    Array工具类的静态方法
  一堆零散数据     public static<T>Stream<T>of(T...values)       Stream接口中的静态方法

(1)单列集合

package article;
import java.util.*;
import java.util.Collection;
import java.util.*;
import java.util.function.Consumer;
import java.util.*;
import java.util.*;
public class first {
   public static void main(String[] args) {
     ArrayList<String>s=new ArrayList<>();
     Collections.addAll(s, "opop","------","4er45","<>><><");
     s.stream().forEach(new Consumer<String>() {

		@Override
		public void accept(String t) {
			// TODO 自动生成的方法存根
			System.out.println(t);
		}
    	 
     });
     //接下来使用lambda表达式进行简化
     System.out.println("--------------------------------");
     s.stream().forEach(i->System.out.println(i));
   }
}

(2)双列集合

双列结合获取stream流有两种办法,一种是获取通过键获取,一种是通过键值来获取。

package article;
import java.util.*;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.*;
import java.util.function.Consumer;
import java.util.*;
import java.util.*;
public class first {
   public static void main(String[] args) {
     HashMap<String,Integer> s=new HashMap<>();
     s.put("abs", 192);
     s.put("<<<<",200);
     s.put("[][][]", 10);
     
     //第一种通过键获取stream流
     s.keySet().stream().forEach(new Consumer<String>(){

		@Override
		public void accept(String t) {
			// TODO 自动生成的方法存根
			//t是键
			System.out.println("键="+t+" 值="+s.get(t));
			
		}
    	 
     });
     System.out.println("----------------------------------------------------");
     //第二种通过键值对获取
     s.entrySet().stream().forEach(new Consumer<Map.Entry<String, Integer>>() {

		@Override
		public void accept(Entry<String, Integer> t) {
			// TODO 自动生成的方法存根
			System.out.println("键="+t.getKey()+" 值="+t.getValue());
		}
    	 
     });
   }
}

(3)数组

package article;
import java.util.*;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.*;
import java.util.*;
public class first {
   public static void main(String[] args) {
     int[] a= {1,32,98,12,90};
     
     Arrays.stream(a).forEach(s->System.out.println(s));
   }
}

(4)一些零散数据

静态方法of可以=传递零散数据,也可以是一个数组,如果是基本数据类型数组,传递进去的是地址,引用数据类型则是值。

package article;
import java.util.*;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.stream.Stream;
import java.util.*;
import java.util.*;
public class first {
   public static void main(String[] args) {
     Stream.of("1",";").forEach(s->System.out.println(s));
     int[] a= {1,2,8};
     String[] b= {"klj",";;;"};
     Stream.of(a).forEach(s->System.out.println(s));
     Stream.of(b).forEach(s->System.out.println(s));
   }
}

三、Stream流中常用的API方法

(1)中间方法

修改stream流中的数据,但不会影响原来集合或者数组中的数据。这里建议使用链式编程。


Stream<T>filter(Predicate<?super T>predicate)   过滤
Stream<T>limit(long maxsize)                    获取前几个元素
Stream<T>skip(long n)                           跳过前几个元素
Stream<T>distinct()                             元素去重,以来hashcode和equals方法,自定义类时记得重写hashcode和equals
static<T>Stream<T>concat(Stream a,Stream b)     合并a和b两个流为一个;流
Stream<R>map(Function<T,R>mapper)               转换流中的数据类型
package article;
import java.util.*;

import java.util.Collection;
import java.util.Map.Entry;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.*;
import java.util.*;
public class first {
   public static void main(String[] args) {
     ArrayList<String> s=new ArrayList<>();
     Collections.addAll(s,"张三丰","周芷若","赵敏","张强","张无忌","张翠山","张亮","王二麻子","谢广坤");
     
     //第一个使用filter过滤,假如得到所有姓张的
     s.stream().filter(new Predicate<String>() {

		@Override
		public boolean test(String t) {
			// 如果返回值是true,表示该数据留下
			if(t.startsWith("张")) {
				return true;
			}
			return false;
		}
    	 
     }).forEach(i->System.out.print(i+" "));
     System.out.println();
     
     //filter使用lambda表达式简写,我也推荐大家这样写,简单一点
     System.out.println("lambda写法:姓张并且长度=3----------------------");
     s.stream()
     .filter(i->i.startsWith("张"))
     .filter(i->i.length()==3)
     .forEach(i->System.out.print(i+" "));
     System.out.println();
   
     System.out.println("limit的使用");
     //第二个limit获取前几个元素
     System.out.println("获取stream中的前面两个元素:");
     s.stream().limit(2).forEach(i->System.out.print(i+" "));
     System.out.println();
    
     System.out.println("skip的使用");
     //第三个skip跳过前面几个元素
     System.out.println("跳过前面7个元素,也就是获得后面两个元素:");
     s.stream().skip(7).forEach(i->System.out.print(i+" "));
     System.out.println();
     
     System.out.println("distinct的使用:");
     //第四个distinct元素去重,依赖hashcode和equals(自定义对象记得重写)
     ArrayList<String> list=new ArrayList<>();
     Collections.addAll(list, "张三丰","张三丰","周芷若","赵敏","张强","张无忌","张翠山","张亮","王二麻子","谢广坤");
     list.stream().distinct().forEach(i->System.out.print(i+" "));
     System.out.println();
     
     System.out.println("concat的使用");
     //第五个使用concat将a,b两个流合并成为一个流,注意这里两个流中的数据类型建议是一样的,不一样合并之后则是它们共同父类的数据类型
     ArrayList<String> list1=new ArrayList<>();
     Collections.addAll(list1, "-=-=","[][][");
     Stream.concat(list1.stream(),s.stream()).forEach(i->System.out.print(i+" "));
     System.out.println();
     
     System.out.println("map的使用:");
     //第六个使用map转换流中的数据类型
     //比如来个需求现在想要下面集合中的年龄
     //这里注意一下map方法执行了以后,流上的数据就变成了整数,不在是之前的字符串了,所以后面的forEach打印出来的是数字
     ArrayList<String> list2=new ArrayList<>();
     Collections.addAll(list2,"张无忌-15","周芷若-18","王柳-100","段誉-98");
     list2.stream().map(i->Integer.parseInt(i.split("-")[1]))
     .forEach(i->System.out.print(i+" "));
     System.out.println();
  }
}

 

 

(2)终结方法

终结方法是什么呢,与中间方法有什么区别吗?没什么大的区别,都是方法,只不过终结方法使用过后就不能再对流进行操作了,它是对流做的最后一次操作了。


void forEach()            遍历
long count()              统计
toArray()                 收集流中的数据,放到数组中
package article;
import java.util.*;

import java.util.Collection;
import java.util.Map.Entry;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.*;
import java.util.*;
public class first {
   public static void main(String[] args) {
     ArrayList<String> s=new ArrayList<>();
     Collections.addAll(s,"张三丰","周芷若","赵敏","张强","张无忌","张翠山","张亮","王二麻子","谢广坤");
     
     String[] a=s.stream().toArray(new IntFunction<String[]>() {
        //这里的IntFunction中的类型就是要转换成的数组类型
    	//apply中的value是流中的数据个数,要和数组长度保持一致
    	 //apply的返回值是具体类型的数组
		@Override
		public String[] apply(int value) {
			// TODO 自动生成的方法存根
			return new String[value];
		}
    	 
     });
     System.out.println(Arrays.toString(a));
     
     //lambad表达式
     String[] b=s.stream().toArray((i)->{
    	 return new String[i];
   });
     System.out.println(Arrays.toString(b));
     
  }
}

 

(3)收集方法

collect()                 收集流中的数据,放到集合(list,set,map)中

注意啊,collect()也是终结方法使用了它之后后面就不能在使用其它什么了。

package article;
import java.util.*;

import java.util.Collection;
import java.util.Map.Entry;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.*;
import java.util.*;
public class first {
   public static void main(String[] args) {
     ArrayList<String> s=new ArrayList<>();
     Collections.addAll(s,"张无忌-男-15","张无忌-男-15","周芷若-女-14","赵敏-女-13","张强-男-29","张三丰-男-100","张翠山-男-40","王五-男-66","谢逊-女-87");
     
     //第一个:收集到list集合中,这里的tolist底层是用ArrayList实现的
     //需求收集性别是男的,姓张的
     List<String> list1=s.stream().filter(i->i.startsWith("张"))
    		 .filter(i->"男".equals(i.split("-")[1]))
    		 .collect(Collectors.toList());
     System.out.println(list1);
     
     //第二个:收集到Set集合中,与List集合不同的是Set集合不允许重复
     //这里的toSet方法底层是通过HashSet实现的
     Set<String> list2=s.stream().filter(i->"男".equals(i.split("-")[1]))
    		 .filter(i->i.startsWith("张"))
    		 .collect(Collectors.toSet());
     System.out.println(list2);
     
     //第三个:收集到Map集合中,这里有一个注意点,键值一定不能重复,否则报错
     //我们要确定哪个是键哪个是值
     //这里我们将名字确定为键,年龄确定是值
     //
     ArrayList<String> li=new ArrayList<>();
     Collections.addAll(li,"张无忌-男-15","周芷若-女-14","赵敏-女-13","张强-男-29","张三丰-男-100","张翠山-男-40","王五-男-66","谢逊-女-87");
     
     Map<String,Integer> ma=li.stream().filter(i->i.startsWith("张"))
    		 .filter(i->"男".equals(i.split("-")[1]))
    		 .collect(Collectors.toMap(new Function<String,String>(){
//这里的toMap中的第一个参数是键的规则,第二个参数是值的规则
    			 //第一个参数的第一个参数是流的类型,第二个是转换的键的类型,第二个同样如此
    			 //返回值就是转换后的
				@Override
				public String apply(String t) {
					// TODO 自动生成的方法存根
					return t.split("-")[0];
				}
    			 
    		 }, new Function<String,Integer>(){

				@Override
				public Integer apply(String t) {
					// TODO 自动生成的方法存根
					return Integer.parseInt(t.split("-")[2]);
				}
    			 
    		 }));
     System.out.println(ma);
  }
}

​​​​​​​

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜到极致就是渣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值