美文网首页技术Code
Java8_Lambda表达式进阶(比较器)

Java8_Lambda表达式进阶(比较器)

作者: 大鹏_xzlp | 来源:发表于2017-10-28 16:25 被阅读0次

    我们先来看两个题

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

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

      public static int countLowercaseLetters(String string) {
      return (int) string.chars()
                       .filter(Character::isLowerCase)
                         .count();
      }
      
    1. 在一个字符串列表中,找出包含最多小写字母的字符串,对于空列表,返回Optional<String> 对象

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

      public class Main {
      
          public static void main(String[] args) {
              List<String> 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<String> mostLowercaseString(List<String> strings) {
              return strings.stream().max(Comparator.comparingInt(Main::countLowercaseLetters));
          }
      }
      
      

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

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

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

    Optional<T> max(Comparator<? super T> comparator);
    

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

    new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return countLowercaseLetters(s1) - countLowercaseLetters(s2);
                }
            }
    

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

    @FunctionalInterface
    public interface Comparator<T> 
    

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

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

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

    public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & 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<T> {
    
        /**
         * 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_Lambda表达式进阶(比较器)

        本文链接:https://www.haomeiwen.com/subject/mdsspxtx.html