Java8進階_Java8_Lambda表达式进阶(比较器)

我们先来看两个题

计算一个字符串中小写字母个数

计算个数我们知道可以用count方法,然后剩下就是找到字符串中的小写字母,使用String对象的chars方法可以拿到字符列表,然后过滤小写字母

public static int countLowercaseLetters(String string) {

return (int) string.chars()

.filter(Character::isLowerCase)

.count();

}

在一个字符串列表中,找出包含最多小写字母的字符串,对于空列表,返回Optional 对象

这里我们接收的是一个字符串列表,要输出的是一个Optional,这里还要找的是最多,看到最多我们可以想到用max方法,max接收的是一个比较器,可以用来比较大小

public class Main {

public static void main(String[] args) {

List strings = Arrays.asList("Hello world","hello","welcome");

mostLowercaseString(strings).ifPresent(System.out::println);//Hello world

}

public static int countLowercaseLetters(String string) {

return (int)string.chars().filter(Character::isLowerCase).count();

}

public static Optional mostLowercaseString(List strings) {

return strings.stream().max(Comparator.comparingInt(Main::countLowercaseLetters));

}

}

这里我们主要来分析第二个问题,重点看这里

strings.stream().max(Comparator.comparingInt(Main::countLowercaseLetters));

max函数接收的是一个Compartor比较器,返回一个Optional

Optional max(Comparator super T> comparator);

Comparator我们在Java8之前就已经很熟悉了,以前我们会这样来生成一个Compartor

new Comparator() {

@Override

public int compare(String s1, String s2) {

return countLowercaseLetters(s1) - countLowercaseLetters(s2);

}

}

在Java8中,Compartor已经变成了一个函数式接口,并且封装了很多常用的默认方法

@FunctionalInterface

public interface Comparator

所以刚才的代码我们可以写成下面这种Labmda表达式的形式

(s1,s2)->countLowercaseLetters(s1)-countLowercaseLetters(s2)

这种最常用的比较两个数字大小的Compartor内部也封装了默认方法,叫做comparingInt

public static Comparator comparingInt(ToIntFunction super T> keyExtractor) {

Objects.requireNonNull(keyExtractor);

return (Comparator & Serializable)

(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));

}

可以看到其内部实现

(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));

就是我们上面(s1,s2)->countLowercaseLetters(s1)-countLowercaseLetters(s2)这种Lambda表达式,只不过它封装到comparingInt方法中,对外调用更加方便

它内部Lambda表达式右边具体的实现是这样写的

Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));

这里有个keyExtractor,这个ToIntFunction super T> 作为方法参数传递进来的,是一个Lambda表达式

@FunctionalInterface

public interface ToIntFunction {

/**

* Applies this function to the given argument.

*

* @param value the function argument

* @return the function result

*/

int applyAsInt(T value);

}

这个函数式接口接收一个值,返回一个数字,也就是说comparingInt方法将这种行为作为参数传递进来,方法内部只进行Integer.compare比较,具体比较的数字是多少,是交给传进来的Lambda表达式来描述这个行为的,所以我们用comparingInt方法来实现就可以这样写:

strings.stream().max(Comparator.comparingInt(item -> countLowercaseLetters(item)));

item -> countLowercaseLetters(item)这个Lambda表达式正好符合方法引用的规则,所以可以简写成

strings.stream().max(Comparator.comparingInt(Main::countLowercaseLetters));

总结

Lambda表达式在流的使用中是很常见的一种操作,其中比较器也是很常用的一种操作,熟练使用其内部封装好的默认方法有助于我们提高效率。

你可能感兴趣的:(Java8進階)