美文网首页程序员
Lambda之方法的引用

Lambda之方法的引用

作者: 巡山的喽罗 | 来源:发表于2016-06-07 21:51 被阅读0次

    Lambda创建一个匿名方法,这提供了一种比拥有一个方法的匿名类更简洁的用法。如果说Lambda简单到只需要调用一个现有的方法,那么方法引用可以作为一个Lambda表达式来让代码变的更加简洁直观。

    方法是可以引用的

    回顾初识Lambda当中介绍的场景,现在管理员需要用户按照生日进行排序,Lambda可以简洁直观的完成这个场景。

    
    List<Person> roster = Person.createRoster();
    Person[] rosterAsArray = roster.toArray(new Person[roster.size()]);
    Arrays.sort(rosterAsArray,
        (a, b) -> {
            return a.getBirthday().compareTo(b.getBirthday());
        }
    );
    
    

    由于Person提供了一个静态方法compareByAge,这个方法简化排序算法的代码。

    
    Arrays.sort(rosterAsArray,
        (a, b) -> {
            return Person.compareByAge(a, b);
        }
    );
    
    

    但这并不是最干净的方式,借助方法引用可以更加简单。

    
    Arrays.sort(rosterAsArray,Person::compareByAge);
    
    

    Person::compareByAge完全等同于(a, b) -> { return Person.compareByAge(a, b); }
    因为Lambda表达式仅仅使用到了一个简单的方法,所以可以借助方法引用这个特性直接将这个方法作为Lambda表达式使用。

    哪类方法可以引用

    类型 使用方式
    静态方法 ContainingClass::staticMethodName
    指定实例的方法 containingObject::instanceMethodName
    特定类实例的任意方法 ContainingType::methodName
    构造方法 ClassName::new

    静态方法

    正如之前Person::compareByAge这样的调用方式。

    指定实例的方法

    定义一个各种比较算法的封装对象。

    
    class ComparisonProvider {
        public int compareByName(Person a, Person b) {
            return a.getName().compareTo(b.getName());
        }
            
        public int compareByAge(Person a, Person b) {
            return a.getBirthday().compareTo(b.getBirthday());
        }
    }
    
    

    类实例化之后,对象就有两个可以调用的比较算法,这个对象的方法就可以用作方法引用。

    
    ComparisonProvider myComparisonProvider = new ComparisonProvider();
    Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
    
    

    特定类实例的任意方法

    这个用法与上面相比稍微特殊一些。

    
    String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
    Arrays.sort(stringArray, String::compareToIgnoreCase);
    
    

    可以看到sort操作的对象是String数组,compareToIgnoreCase既不是静态方法,同时也没有通过使用一个String对象的方法引用,而是直接将StringcompareToIgnoreCase方法作为Lambda。compareToIgnoreCase实际只有一个输入参数,Lambda的目标类型Compartor<T>compare(T o1, T o2)是有两个输入参数的,按照之前的方式,这个引用的方法似乎也是需要两个String类型的参数。
    其实并非如此,虽然Lambda有两个输入参数,这两个输入参数可以看做是ab,方法的引用则与a.compareToIgnoreCase(b)这种调用方式相同。

    构造方法

    定义了一个可以转换集合实现方式的方法,这个方法可以将一种集合对象转换成另外一种集合对象。

    
    public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>
        DEST transferElements(
            SOURCE sourceCollection,
            Supplier<DEST> collectionFactory) {
            
            DEST result = collectionFactory.get();
            for (T t : sourceCollection) {
                result.add(t);
            }
            return result;
    }
    
    

    其中的Supplier是一个JDK标准函数接口,它提供了一个get的无参方法,这里通过get构造了一个Set实例。如果把一个List集合转换成Set集合,使用Lambda实现:

    
    Set<Person> rosterSetLambda = transferElements(roster, () -> { return new HashSet<>(); });
    
    

    通过构造方法的引用变的更简洁。

    
    Set<Person> rosterSet = transferElements(roster, HashSet::new);
    
    

    编译器可以推断出HashSet的类型参数,也可以显式声明类型参数。

    
    Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);
    
    

    参考资料

    1. Java Tutorials Learning Paths - Method References

    相关文章

      网友评论

        本文标题:Lambda之方法的引用

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