一、简单了解下Lambda表达式:
之前遍历一个Iterable集合,我可能会这样写:
Set<String> set = new HashSet<>();
set.add("AAA");
set.add("BBB");
set.add("CCC");
set.add("DDD");
for(String str: set){System.out.println("e:"+str);
}
for(Iterator<String> it=set.iterator();it.hasNext();){
System.out.println("e:"+it.next());
}
而java8之后,Iterable接口里新增了一个默认方法forEach,我更喜欢这种操作:
set.forEach((e)->{
System.out.println("e:"+e);
});
其中forEach方法的参数是个消费型的函数式接口Consumer,它里面只有一个抽象方法void accept(T t),我们传进去的参数在这里其实就是集合的元素值了。上面的e就是集合中遍历的没一个元素值,->符号后面的语句块就是具体的操作。
Lambda表达式里的参数是两个的情形:
List<String> list = new ArrayList<>();
list.add("AAAA");
list.add("BBB");
list.add("CC");
list.add("D");
//对集合元素按自定义方式排序
return ((String)e1).length()-((String)e2).length(); //根据元素的长度从小到大排序
});
其实吧,我觉得方法的参数符合函数式接口的标准,都可以用Lambda表达式来写,简洁,清晰,明了。那啥才算是函数式接口呢?其实就是只有一个抽象方法的接口,比如常用的Runnable接口,FileFilter等,但是,接口里的默认方法不算抽象方法哈。
二、简单了解下Stream API:
java8中Collection接口里面,增加了一个stream()方法,这个方法返回一个Stream(流);我觉得在集合上打开的这个流就像是给这组集合数据生成了一条流水线式的处理过程。
有个List集合:
List<String> list = new ArrayList<>();
list.stream();list.add("AAAA");
list.add("BBB");
list.add("CC");
list.add("D");
list.add("CC");
list.stream().forEach(e->{System.out.println(e);});
stream()方法会打开这个集合的一个流并返回。在调用流里面的forEach方法,可以轻松遍历得到集合的数据。整了半天,一直再整集合的遍历,没劲儿。下面用流来截取集合中的数据:
list.stream().limit(2).forEach(e->{System.out.println(e);});可以看到,获得了流之后,调用了流的limit方法,限制只取出2条数据,所以输出AAAA "\r\n" BBBB,但是这个截取操作并没有改变原List集合中的数据哦,原List里面还是4个值。只不过这个流只操作前两个而已。
再来一个API:distinct()
list.stream().distinct().forEach(e->{System.out.println(e);});去重,输出AAAA "\r\n" BBBB "\r\n" CC "\r\n" "D",我想应该是按照类型的equals方法来判断是否重复吧。哦,java8里面还提供了一个方法引用,如下操作:
list.forEach(System.out::println);就是这个样子,写法又更简单了一点。这个意思是:System.out中的这个out是一个PrintWriter类型的实例,这个实例有一个println(String)或println(Object)的成员方法,所以,可以直接应用,当然,类的静态方法也可以引用啦,道理是一样的。其实Stream类还有很多实用的方法,就不一一测试啦,不会的方法,用的时候再去查API文档就是啦。