知识点:
1.离不开Lamda表达式;
2.方法引用、四个函数式接口;
3.如何使用stream数据流进行集合的辅助操作,MapReduce的使用过程。
具体内容:
在JDK1.8开始整个类集里面出现了大量的default或则是static方法,以Collection的父接口Iterable接口里面定义的一个方法来分析。default void forEach(Consumer<? super T>action)
范例:利用forEach()方法输出
package conll;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>();
all.add("hello");
all.add("world");
all.add("good");
all.forEach(System.out :: println);
}
}
一般不回采用以上的方式完成,因为forEach()只能够实现输出,但是很多时候我们在进行集合数据输出的同时还需要对数据进行处理,也就是说Iterator输出是主要使用的方式。
除了使用Iterator迭代取出数据并且处理之外,在JDK1.8里面又专门提供了一个专门进行数据处理的类:Stream ,这个类的对象可以利用Collection接口提供的方法操作:default Stream<E>stream
范例:取得Stream对象
package conll;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>();
all.add("hello");
all.add("world");
all.add("good");
Steram<String> stream = all.stream(); //取得stream类的对象
System.out.println(stream.count); //取得数据个数
}
}
既然取得了Stream类的对象那么下面进行数据的加工处理操作。
范例:取消掉重复数据
Stream类里面有一个消除重复的方法:public Stream<T>distinct();
收集器(最后使用收集):public <R,A>R collect(Collector<? super T,A,R>collector);
-Collections类:public static<T>Collector<T,?,List<>>toList;
package conll;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>();
all.add("hello");
all.add("world");
all.add("good");
Steram<String> stream = all.stream(); //取得stream类的对象
System.out.println(stream.distinct().count); //取得不重复数据个数
//去除掉所有的重复数据后形成新的集合数据,里面是不包含重复内容的集合
List<String> newAll = stream.diatinct().collect(collectors.toList());
newAll.forEach(System.out :: println);
}
}
既然Stream类是进行数据处理的,那么数据处理过程中就不能不去思考数据的筛选问题(过滤),Stream类里面支持有数据的过滤操作:public Stream<T>filter(Predicate<? super T>predicate)
范例:数据过滤
package conll;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>();
all.add("Android");
all.add("java");
all.add("Ios");
all.add("ORACLE");
Steram<String> stream = all.stream(); //取得stream类的对象
//增加了数据的过滤操作,使用断言型函数接口,使用String类中的contains()方法
List<String> newAll = stream.diatinct().filter((x)->x.contains("a"))collect(collectors.toList());
newAll.forEach(System.out :: println);
}
}
整个现在的数据操作已经成功的实现了过滤应用,但是缺点是这个过滤的时候区分了大小写,证明在对数据过滤前需要对数据进行一些额外的处理,例如:转大写或者统一转小写。在Stream接口里面提供有专门的数据处理方法:public<R>Stream<R>map(Function<? super T,?extends R> mapper) Function式的函数接口:接收数据,处理并返回。针对数据逐行进行处理。
范例:数据处理后过滤
package conll;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>();
all.add("Android");
all.add("java");
all.add("Ios");
all.add("ORACLE");
Steram<String> stream = all.stream(); //取得stream类的对象
//增加了数据的过滤操作,使用断言型函数接口,使用String类中的contains()方法
List<String> newAll = stream.diatinct().map((x)->x.toLowerCase()).filter((x)->x.contains("a"))collect(collectors.toList());
newAll.forEach(System.out :: println);
}
}
在Stream接口里面提供有进行集合数据分页的操作:
1.设置跳过的数据行数:public Stream<T>skip(long n);
2.设置取出的数据个数:public Stream<T>limit(long maxSize)
package conll;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>();
all.add("Android");
all.add("java");
all.add("Ios");
all.add("ORACLE");
Steram<String> stream = all.stream(); //取得stream类的对象
//增加了数据的过滤操作,使用断言型函数接口,使用String类中的contains()方法
List<String> newAll = stream.diatinct().map((x)->x.toLowerCase()).skip(2).limit(2).collect(collectors.toList());
newAll.forEach(System.out :: println);
}
}
在Stream接口里面还可以进行数据的全匹配或部分匹配;
1.全匹配:public boolean allMatch(Predicate<? super T>predicate) Predicate断言型接口
2.匹配任意一个:public boolean anyMatch(Predicate<? super T>predicate)
范例:实现一个数据的匹配查询
package conll;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>();
all.add("Android");
all.add("java");
all.add("Ios");
all.add("ORACLE");
Steram<String> stream = all.stream(); //取得stream类的对象
if(Stream.anyMatch((x)->.contains("jsp"))){
System.out.println("数据存在!");
}
}
}
在实际中有可能会出现多个匹配条件,在断言型的函数是接口里面提供有如下的方法:
1.或操作:default Predicate<T> or(Predicate<? super T> other)
2.与操作:default Predicate<T> and(Predicate<? super T> other)
范例:设置多个条件
package conll;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.sql.rowset.Predicate;
public class TestDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>();
all.add("Android");
all.add("java");
all.add("Ios");
all.add("ORACLE");
Predicate<String> p1 = (x)->x.contains("jsp");
Predicate<String> p2 = (x)->x.contains("Ios");
Steram<String> stream = all.stream(); //取得stream类的对象
if(Stream.anyMatch(p1.or(p2)){ //同时使用两个条件
System.out.println("数据存在!");
}
}
}
利用这样的匹配条件,可以针对数据进行方便的查询操作。
如果要想更好的返回Stream的操作优势,必须结合MapReduce一起观察。
数据分析方法:public Optional<T> reduce(BinaryOperator<T> accumulator)
-就是做数据统计使用的。
范例:实现一个MapRedce
class ShopCar{
private String pname;
private double price;
private int amount;
public ShopCar(String pname,double price,int amount){
this.pname = pname;
this.price = price;
this.amount = amount;
}
public String getPname(){
return pname;
}
public int getAmount(){
return amount;
}
public double getPrice(){
return price;
}
}
本类设计的时候专门设计初了商品的价格与数量,这样想取得某一个购物车的一个商品的总价格就必须数量乘以价格。
范例:进行数据的保存与初步的处理
public class TestDemo {
public static void main(String[] args) throws Exception {
List<ShopCar> all = new ArrayList<ShopCar>();
all.add(new ShopCar("电影票",800.0,20));
all.add(new ShopCar("鸭子",80.0,2));
all.add(new ShopCar("剃须刀",100.0,1));
all.stream().map((x)->x.getAmount()*x.getPrice()).forEach(System.out :: println);
}
}
此时已经针对于每一个数据进行了处理。但是这个时候没有总价,于是要对处理后的数据进行统计操作,就使用reduce()完成。
范例:统计处理数据
public class TestDemo {
public static void main(String[] args) throws Exception {
List<ShopCar> all = new ArrayList<ShopCar>();
all.add(new ShopCar("电影票",800.0,20));
all.add(new ShopCar("鸭子",80.0,2));
all.add(new ShopCar("剃须刀",100.0,1));
double s = all.stream().map((x)->x.getAmount()*x.getPrice()).reduce((sum,m)->sum+m).get();
System.out.println("花费总金额:"+s);
}
}
以上只是实现了一个最简单的MapReduce,但是所完成的统计功能实在有限,为了完成统计功能,需要使用Stream接口里面定义的以下统计方法:
按照double处理:public DoubleStream mapToDouble(ToDoubleFunction<? super T>mapper)
按照int处理:public IntStream mapToInt(ToIntFunction<? super T>mapper)
按照long处理:public LongStream mapToLong(ToLongFounction<?superT>mapper)
Stream是BaseStream的子接口,而DoubleStream也是BaseStream的子接口)
范例:实现一个数据的统计操作
public class TestDemo {
public static void main(String[] args) throws Exception {
List<ShopCar> all = new ArrayList<ShopCar>();
all.add(new ShopCar("电影票",800.0,20));
all.add(new ShopCar("鸭子",80.0,2));
all.add(new ShopCar("剃须刀",100.0,1));
DoubleSummaryStatics dss = all.stream().mapToDouble((cs)->sc.getAmount()*getPrice()).summaryStatistics();
System.out.println("商品个数:"+dss.getCount());
System.out.println("总花费:"+dss.getSum());
System.out.println("平均花费:"+dss.getAverage());
System.out.println("最高花费:"+dss.getMax());
System.out.println("最低花费:"+dss.getMin());
}
这种操作虽然麻烦,但是的确简化了代码的编写。
总结:以上的操作忘了把,就像它从未出现过一样。就清楚MapReduce:Map处理数据,Reduce统计数据