
Java 1.8 两个重大的改变,第一个就是Lambda表达式 ,另一个就是Stream API.
Stream 简介而这个添加了一个新的抽象称为Stream(java.util.stream)。其把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充。
为什么这样说?因为可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
为什么要有stream?实际开发中,项目中多数数据来源都来自Mysql,Oracle等。打死你hi现在数据源更多了,比如MongDb,Redis等,而这些Nosql的数据就需要Java层面去处理了。
-
补充1:Stream与Collection集合的区别:
- Collection 是一种静态的内存数据结构,主要面向内存,存储在内存中。
- Stream是由关计算的。主要是面向CPU,通过CPU实现计算。
-
补充2:
- Stream自己不会存储数据
- Stream不会改变源的对象。相反,它们会返回一个持有结果的新Stream。
- Stream *** 作是延迟执行的。这意味它们会等到结果的时候才会执行。
stream的 *** 作有三个步骤
- 1.创建Stream:一个数据源(如 集合,数组)从而获取一个Stream
,泛型最好带着,因为有时候不带使用lambda的时候会有类型错误,默认其泛型为obeject的流。 - 2.中间 *** 作 : 一个中间 *** 作链,对数据源的数据进行处理。(代码中演示)
- 3.终止 *** 作:一旦执行终止 *** 作 ,就执行了中间 *** 作链,并产生结果,之后就不会再被使用。这也是为什么说Stream是延迟执行的原因。
这种方式是最简单的一种创建stream的方式,直接通过集合调用方法即可得到
public class test {
public static void main(String[] args) {
List list=new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
// 创建一个Stream
// 返回一个顺序 *** 作的stream 从上倒下的 *** 作
Stream stream1= list.stream();
// 返回一个并行 *** 作的stream 有几个线程会同时运行,所以数据有可能不按照得到
Stream stream2= list.parallelStream();
}
}
创建方式2–通过数组
这一种是调用Arrays类的中的方法,进行创建的。
public class test {
public static void main(String[] args) {
String[] arr= {"a","b"};
Stream stream=Arrays.stream(arr); // 这种也可以创建自定义的类类型 是顺序
}
}
创建方式3–of方法
Stream本身就有一个方法of()。
public class test {
public static void main(String[] args) {
Stream steam=Stream.of("a","b"); // 这种也可以创建自定义的类类型 是顺序
}
}
创建方式4-无限流
这种方式,暂时先了解先看代码。
public class test {
public static void main(String[] args) {
// 无限流第一种 迭代
// 其中这个方法用到了Function 接口的子接口 public interface UnaryOperator extends Function
// 这个地方其实也用了中间 *** 作 limit 以及终止 *** 作 forEach 不然无法体现出效果
Stream.iterate(0, t-> t=t+1).limit(5).forEach(System.out::println);
}
}
public class test {
public static void main(String[] args) {
// 无限流第二种 生成
// 其中这个方法用到了Supplier public static Stream generate(Supplier s) {
// 这个地方其实也用了中间 *** 作 limit 以及终止 *** 作 forEach 不然无法体现出效果
// 普通写法
Stream.generate(new Supplier() {
@Override
public Double get() {
// TODO Auto-generated method stub
return Math.random();
}
}).limit(10).forEach(System.out::println);
// 方法引用
// Supplier 实现的方法中一行代码 通过 Math用random方法,所以可以用方法引用
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
}
步骤2 中间 *** 作
中间 *** 作说白了就是对数据进行处理
代码演示前,首先创建一个对象类:
class ObJ{
private String name;
private int age;
public ObJ(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
// 为了更方便看输出的数据所以重写一下String
public String toString() {
// TODO Auto-generated method stub
return "名字是:"+this.name+" 年纪:"+this.age;
}
}
再创建一个带有对象的list:
Listlist=new ArrayList (); list.add(new ObJ("张三",15)); list.add(new ObJ("李四",9)); list.add(new ObJ("王五",14)); list.add(new ObJ("赵六",5)); list.add(new ObJ("王七",25)); list.add(new ObJ("张八",15)); ObJ obj=new ObJ("石九", 13); list.add(obj); list.add(obj);
所以后面代码演示的时候直接就用list了,不然每次重复,会让文章变得又长又没有多少干货。
筛选与切片常用方法如下:
//通过 filter方法 筛选大于15岁的人 Streamstream = list.stream(); stream.filter(obj-> obj.getAge()>15).limit(100).forEach(System.out::println);
// 通过list 得到前3个人
Stream stream = list.stream();
stream.filter(obj-> obj.getAge()>15).limit(3).forEach(System.out::println);
stream.limit(3).forEach(System.out::println);
通过这个可以看出创建的stream只能用一次。这的用一次的是不是说一个stream无法多次使用中间 *** 作,而是使用了终止 *** 作(forEach),就无法在进行 *** 作了。
// 顺序
Stream stream = list.stream();
stream.limit(3).forEach(System.out::println);
System.out.println("-----------分割线-------");
// 并行
Stream stream1 = list.parallelStream();
stream1.limit(3).forEach(System.out::println);
可以看出并行,没有按照list添加的数据取出数据。
Streamstream = list.stream(); stream.skip(3).forEach(System.out::println);
Stream映射stream = list.stream(); stream.distinct().forEach(System.out::println);
常用的方法如下:
如果懂点python的话感觉有点像是线程中调用map的方法。
// 判断输出名字里面含有王的名字。
Stream stream = list.stream();
stream.filter(t-> t.getName().contains("王")).limit(3).forEach(System.out::println);
System.out.println("-----------分割线-------");
stream = list.stream();
Stream stream1= stream.map(t -> t.getName());
stream1.filter(t -> t.contains("王")).forEach(System.out::println);
public class test {
public static void main(String[] args) {
List list=Arrays.asList("ab","cd","ef");
// 想要打印出 a b c d e f
// 如果使用map
Stream stream=list.stream();
Stream> streamCs= stream.map(test::chai);
streamCs.forEach(streamC->
streamC.forEach(System.out::println)
);
System.out.println("-----------分割线-------");
// flatMap
stream=list.stream();
//Stream 这个直接将里面的集合进行展开
Stream streamC=stream.flatMap(test::chai);
streamC.forEach(System.out::println);
}
// 将字符串拆成一个字符
public static Stream chai(String str){
List list=new ArrayList<>();
for(Character c:str.toCharArray()) {
list.add(c);
}
// 直接返回一stream 为了好 *** 作
return list.stream();
}
}
排序
public class test {
public static void main(String[] args) {
List list=Arrays.asList(1,3,2);
Stream stream=list.stream();
Stream stream1=stream.sorted();
stream1.forEach(System.out::println);
System.out.println("-----------分割线-------");
stream=list.stream();
stream1=stream.sorted( (o1,o2) -> Integer.compare(o2, o1) );
stream1.forEach(System.out::println);
}
}
步骤3 终止 *** 作
前面一种用的forEach就是常用的一个终止 *** 作,当然还有一些其他的终止 *** 作,具体如下。
匹配与查找Listlist=Arrays.asList(1,3,2); Stream stream=list.stream(); boolean b=stream.allMatch(t -> t>0); System.out.println(b); System.out.println("-----------分割线-------"); stream=list.stream(); b=stream.allMatch(t -> t>2); System.out.println(b);
Listlist=Arrays.asList(1,3,2); Stream stream=list.stream(); boolean b=stream.anyMatch(t -> t>0); System.out.println(b); System.out.println("-----------分割线-------"); stream=list.stream(); b=stream.anyMatch(t -> t>2); System.out.println(b);
Listlist=Arrays.asList(1,3,2); Stream stream=list.stream(); boolean b=stream.noneMatch(t -> t>2); System.out.println(b); System.out.println("-----------分割线-------"); stream=list.stream(); b=stream.noneMatch(t -> t>5); System.out.println(b);
List归约list=Arrays.asList(1,3,2); Stream stream=list.stream(); Optional OP=stream.findFirst();// System.out.println(OP.get()); System.out.println("-----------分割线-------"); stream=list.stream(); OP=stream.findAny(); System.out.println(OP.get());
Listlist=Arrays.asList(1,3,2); // 把list中的值累加起来 Stream stream=list.stream(); //为了方便理解 把这个初始值先写出来 Integer start=0; Integer sum=stream.reduce(start, Integer::sum); System.out.println(sum); System.out.println("-----------分割线-------"); stream=list.stream(); start=1; sum=stream.reduce(start, Integer::sum); System.out.println(sum);
// 将 List收集list 中的年龄值相加 stream = list.stream(); Integer sumAge= stream.map(t -> t.getAge()).reduce(Integer::sum);
Collector 接口中方法的实现决定了如何对流执行收集的 *** 作,(如收集到List,Set,Map)另外还有很多静态方法,方便创建常见的收集器实例。
如下:
Listlist=Arrays.asList(1,3,2); // 把list中的值累加起来 Stream stream=list.stream(); Stream stream1 =stream.filter(t-> t>1);// System.out.println(stream1); System.out.println(stream1.collect(Collectors.toList())); //将 stream转换为一个list
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)