Lambda
一、准备
public interface CatChecker {
public boolean check(Cat c);
}
public class Cat {
public int length,weight;
public Cat(int l,int w) {
length=l;
weight=w;
}
public String toString() {
return "length:"+length+" weight:"+weight;
}
}
public class Cats {
public List<Cat> lc;
public Cats() {
lc=new ArrayList<>();
for(int i=1;i<11;i++) {
lc.add(new Cat(i*5,i*2));
}
}
}
二、LambdaDemo
- 筛选出身长>30,体重>15的cat
- 原理是将 ->后的语句作为接口CatChecker类中check函数的返回值
public class LambdaDemo {
private static void filter(List<Cat> lc, CatChecker checker) {
for(Cat c:lc) {
if(checker.check(c))System.out.println(c.toString());
}
}
public static void main(String[] args) {
Cats cats=new Cats();
filter(cats.lc,c->c.length>30 && c.weight>15);
}
}
三、Lambda引用方法
- 筛选出身长>30,体重>15的cat
- lambda表达式引入方法注意方法的返回值和参数列表与接口一致
- 引入静态方法用 类名::方法名,注意不加括号
- 引入成员方法用 实例::方法名,注意不加括号
- 引用容器中的方法,假设Cat类中有成员方法check,而Cat类是列表容器cats.lc中储存的对象,那么可以使用以下两种lambda表达
- filter(cats.lc,c->c.check());
- filter(cats.lc,Cat::check);
public class LambdaWithMethods {
private void filter(List<Cat> lc, CatChecker checker) {
for(Cat c:lc) {
if(checker.check(c))System.out.println(c.toString());
}
System.out.println("--------------------------");
}
public void withStaticMethods() {
Cats cats=new Cats();
System.out.println("使用静态方法:");
filter(cats.lc,c->checkCat(c));
System.out.println("直接引用静态方法");
filter(cats.lc,LambdaWithMethods::checkCat);
System.out.println("引用对象方法");
LambdaWithMethods lwm=new LambdaWithMethods();
filter(cats.lc,lwm::check);
}
public static boolean checkCat(Cat c) {
if(c.length>30 && c.weight>15)return true;
else return false;
}
public boolean check(Cat c) {
if(c.length>30 && c.weight>15)return true;
else return false;
}
public static void main(String[] args) {
LambdaWithMethods lwm = new LambdaWithMethods();
lwm.withStaticMethods();
}
}
四、Lambda引用构造器
interface Supplier<T> {
T get();
}
public class ReferenceConstructor {
public static List getList(Supplier<List> s) {
return s.get();
}
public void test() {
List<Cat> lc1=getList(ArrayList<Cat>::new);
List<Cat> lc2=getList(()->new ArrayList<Cat>());
}
}
五、Stream
- demo:使用循环和使用stream遍历cats.lc
public class StreamDemo {
Cats cats=new Cats();
public void readCats() {
System.out.println("传统方式:");
for(Cat c:cats.lc) {
if(c.length>30&&c.weight>15)System.out.println(c.toString());
}
System.out.println("聚合方式:");
cats.lc
.stream()
.filter(c -> c.length>30&&c.weight>15)
.forEach(c -> System.out.println(c.toString()));
}
public static void main(String args[]) {
StreamDemo sd=new StreamDemo();
sd.readCats();
}
}
- Stream 和Collection结构化的数据不一样,Stream是一系列的元素,就像是生产线上的罐头一样,一串串的出来。
- 管道指的是一系列的聚合操作。
- 管道又分3个部分
- 管道源:在这个例子里,源是一个List
- 中间操作: 每个中间操作,又会返回一个Stream,比如.filter()又返回一个Stream, 中间操作是“懒”操作,并不会真正进行遍历。
- 结束操作:当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。 结束操作不会返回Stream,但是会返回int、float、String、 Collection或者像forEach,什么都不返回, 结束操作才进行真正的遍历行为,在遍历的时候,才会去进行中间操作的相关判断
public class Stream {
Cats cats=new Cats();
public void streamMiddleOperator(){
cats.lc.stream().filter(c->c.length>40)
.forEach(c->System.out.println(c.toString()));
cats.lc.stream().distinct()
.forEach(c->System.out.println(c.toString()));
cats.lc.stream().sorted((c1,c2)->c1.length>c2.length?1:-1)
.forEach(c->System.out.println(c.toString()));
cats.lc.stream().limit(3)
.forEach(c->System.out.println(c.toString()));
cats.lc.stream().skip(3)
.forEach(c->System.out.println(c.toString()));
}
public void streamFinalOperator() {
cats.lc.stream().limit(3)
.forEach(c->System.out.println(c.toString()));
Object[] cs=cats.lc.stream().limit(3).toArray();
Cat cat1=cats.lc.stream().limit(3)
.min((c1,c2)->c1.length>c2.length?1:-1).get();
Cat cat2=cats.lc.stream().limit(3)
.max((c1,c2)->c1.length>c2.length?1:-1).get();
long cou=cats.lc.stream().limit(3).count();
Cat cat3=cats.lc.stream().limit(3).findFirst().get();
}
}