目录
一、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);
}
}