java8的新特性☞ lambda表达式
lambda表达式可以简化内部类代码:
比如创建一个线程任务,以前的写法是
Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println("成都in the house"); } }); t1.start();
用lambda表达式会简化代码:
Thread t1 = new Thread(()-> System.out.println("上海也in the house")); t1.start();
lambda表达式的语法:
1.完全式语法
(Type1 param1, Type2 param2, ..., TypeN paramN) -> { statment1; statment2; //............. return statmentM; }
2.单参数语法
param1 -> { statment1; statment2; //............. return statmentM; }
举例:将集合中的字母都转换成大写
List<String> list = Arrays.asList(new String[]{"aWm","ak47","Mp5"});
List<String> list2 = list.stream().map(item -> { return item.toUpperCase(); }).collect(Collectors.toList()); System.out.println(list2);
3.单语句语法
当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号
List<String> collect = list.stream().map(bb -> bb.toUpperCase()).collect(Collectors.toList()); System.out.println(collect);
4.方法引用语法
List<String> collect = list.stream().map(String::toUpperCase).collect(Collectors.toList()); System.out.println(collect);
这几种句法得出的结果都是一致的。
方法引用:
objectName::instanceMethod
ClassName::staticMethod
ClassName::instanceMethod
前两种方式类似,等同于把lambda表达式的参数直接当成instanceMethod|staticMethod的参数来调用。比如System.out::println等同于x->System.out.println(x);Math::max等同于(x, y)->Math.max(x,y)。
最后一种方式,等同于把lambda表达式的第一个参数当成instanceMethod的目标对象,其他剩余参数当成该方法的参数。比如String::toLowerCase等同于x->x.toLowerCase()。
可以这么理解,前两种是将传入对象当参数执行方法,后一种是调用传入对象的方法。
如何使用Stream?
对聚合操作的使用可以归结为3个部分:
- 创建Stream:通过stream()方法,取得集合对象的数据集。
- Intermediate:通过一系列中间(Intermediate)方法,对数据集进行过滤、检索等数据集的再次处理。如上例中,使用filter()方法来对数据集进行过滤。
- Terminal通过最终(terminal)方法完成对数据集中元素的处理。如上例中,使用forEach()完成对过滤后元素的打印。
在一次聚合操作中,可以有多个Intermediate,但是有且只有一个Terminal。也就是说,在对一个Stream可以进行多次转换操作,转换操作是lazy(惰性求值)的,只有在Terminal操作执行时,才会一次性执行。
Stream的操作分类
刚才提到的Stream的操作有Intermediate、Terminal和Short-circuiting:
-
Intermediate:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 skip、 parallel、 sequential、 unordered
-
Terminal:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、iterator
-
Short-circuiting:
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
惰性求值和及早求值方法
像filter这样只描述Stream,最终不产生新集合的方法叫作惰性求值方法;而像count这样最终会从Stream产生值的方法叫作及早求值方法。
如何判断一个操作是惰性求值还是及早求值,其实很简单,只需要看其返回值即可:如果返回值是Stream,那么就是惰性求值;如果返回值不是Stream或者是void,那么就是及早求值
在一个Stream操作中,可以有多次惰性求值,但有且仅有一次及早求值。
Stream语法
如何获取Stream?
1.Stream stream = Stream.of("a", "b", "c");
2.数组转换为一个流:
String [] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
3.集合转换为一个流
List<String> list = Arrays.asList(new String[]{"aWm","ak47","Mp5","","aWm"});
Stream<String> stream = list.stream();
distinct去重
distinct: 对于Stream中包含的元素进行去重操作(去重逻辑依赖元素的equals方法)
List<String> list = Arrays.asList(new String[]{"aWm","ak47","Mp5","","aWm"}); long count = list.stream().distinct().count(); System.out.println(count);
输出结果4
filter过滤
filter: 对于Stream中包含的元素使用给定的过滤函数进行过滤操作,新生成的Stream只包含符合条件的元素;
List<String> list = Arrays.asList(new String[]{"aWm","ak47","Mp5","","aWm"}); long count = list.stream().filter(s->!s.isEmpty()).distinct().count(); System.out.println(count);
filter中的条件是不为空串的元素,并去重
输出结果3
map操作集合
map:可以遍历集合中的每个对象,并对其进行操作,map之后,用.collect(Collectors.toList())会得到操作后的集合。
List<String> list = Arrays.asList(new String[]{"aWm","ak47","Mp5","","aWm"}); List<String> collect = list.stream().map(s -> s + "===").collect(Collectors.toList()); System.out.println(collect);
拿到list的流,使用map操作,让每个元素拼接上“===”打印输出:[aWm===, ak47===, Mp5===, ===, aWm===]
如果操作需要多条语句,需要加上{},例如在实际开发中,去数据库查询2016,2017,2018年的销售额/购入额*100%
List<String> datas = Arrays.asList(new String[]{"2016", "2017", "2018"});
datas = years.parallelStream().map(s->{ Double xse = industryDao.getSalesAmount(s.toString()); Double gre = industryDao.getBuyAmount(s.toString()); if (gre.equals(0.00)) return 0.00; else return toDouble(Math.abs(xse) / Math.abs(gre) * 100); } ).collect(toList());
匹配(Match方法):
有的时候,我们只需要判断集合中是否全部满足条件,或者判断集合中是否有满足条件的元素,这时候就可以使用match方法:
allMatch:Stream 中全部元素符合传入的 predicate,返回 true
anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
List<String> list = Arrays.asList(new String[]{"aWm","ak47","Mp5","","aWm"}); boolean awm = list.stream().anyMatch(s -> s.equalsIgnoreCase("awm")); System.out.println(awm);//true
reduce:汇聚
List<String> list = Arrays.asList(new String[]{"aWm","ak47","Mp5","","aWm"}); Optional<String> reduce = list.stream().reduce((a, b) -> a + b); System.out.println(reduce);//Optional[aWmak47Mp5aWm]