即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

lambda表达式除了保存代码行之外还有什么特殊用途吗?

本文目录
[隐藏]

1.原始问题:Are lambda expressions any special use other than saving lines of code?

Are lambda expressions any special use other than saving lines of code?

Is there any special features provided by lambdas, solved some kind of problems which were not easy to solve? The typical usage is instead of writing this

Comparator byName = new Comparator() {
  @Override
  public int compare(Developer o1, Developer o2) {
    return o1.getName().compareTo(o2.getName());
  }
};

we can write this..

Comparator byName =
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());

2.被采纳答案

暂无被采纳答案,请参照下面其他答案。

3.其他高票答案

3.1.第1个答案

Lambda expressions do not change the set of problems you can solve with Java in general, but definitely make solving certain problems easier, just for the same reason we’re not programming in assembly language anymore. Removing redundant tasks from the programmer’s work makes life easier and allows to do things you wouldn’t even touch otherwise, just for the amount of code you would have to produce (manually).

But lambda expressions are not just saving lines of code. Lambda expressions allow you to define functions, something for which you could use anonymous inner classes as a work-around before, that’s why you can replace anonymous inner classes in these cases, but not in general.

Most notably, lambda expressions are defined independently to the functional interface they will be converted to, so there are no inherited members they could access, further, they can not access the instance of the type implementing the functional interface. Within a lambda expression, this and super have the same meaning as in the surrounding context, see also this answer. Also, you can not create new local variables shadowing local variables of the surrounding context. For the intended task of defining a function, this removes a lot of error sources, but it also implies that for other use cases, there might be anonymous inner classes which can not be converted to a lambda expression, even if implementing a functional interface.

Further, the construct new Type() { … } guarantees to produce a new distinct instance (as new always does). And anonymous inner class instances always keep a reference to their outer instance if created in a non-static context. In contrast, lambda expression only capture a reference to this when needed, i.e. if they access this or a non-static member. And they produce instances of an intentionally unspecified identity, which allows the implementation to decide at runtime whether to reuse existing instances (see also “Does a lambda expression create an object on the heap every time it’s executed?”).

These differences apply to your example. Your anonymous inner class construct will always produce a new instance, also it may capture a reference to the outer instance, whereas your (Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName()) is a noncapturing lambda expression that will evaluate to a singleton in typical implementations. Further, it doesn’t produce a .class file on your hard drive.

Given the differences regarding both, semantic and performance, lambda expressions may change the way programmers will solve certain problems in the future, of course, also due to the new APIs embracing ideas of functional programming utilizing the new language features. See also Java 8 lambda expression and first-class values.

3.2.第2个答案

4.Internal iteration

When iterating Java Collections, most developers tend to get an element and then process it. This is, take that item out and then use it, or reinsert it, etc. With pre-8 versions of Java, you can implement an inner class and do something like:

numbers.forEach(new Consumer() {

    public void accept(Integer value) {

        System.out.println(value);

    }

});

Now with Java 8 you can do better and less verbose with:

numbers.forEach((Integer value) -> System.out.println(value));

or better

numbers.forEach(System.out::println);

5.Behaviors as arguments

Guess the following case:

public int sumAllEven(List numbers) {

    int total = 0;

    for (int number : numbers) {
        if (number % 2 == 0) {
            total += number;
        }
    } 
    return total;
}

With Java 8 Predicate interface you can do better like so:

public int sumAll(List numbers, Predicate p) {

    int total = 0;

    for (int number : numbers) {

        if (p.test(number)) {
            total += number;
        }
    }
    return total;
}

Calling it like:

sumAll(numbers, n -> n % 2 == 0);

Source

5.1.第3个答案

Saving lines of code can be viewed as a new feature, if it enables you to write a substantial chunk of logic in a shorter and clearer manner, which takes less time for others to read and understand.

Without lambda expressions (and/or method references) Stream pipelines would have been much less readable.

Think, for example, how the following Stream pipeline would have looked like if you replaced each lambda expression with an anonymous class instance.

List names =
    people.stream()
          .filter(p -> p.getAge () > 21)
          .map(p -> p.getName())
          .sorted((n1,n2)->n1.compareTo(n2))
          .collect(Collectors.toList());

And this is a relatively short pipeline.

To make this readable without lambda expressions and method references, you would have had to define variables that hold the various functional interface instances being used here, which would have split the logic of the pipeline, making it harder to understand.

5.2.第4个答案

To answer your question, the matter of fact is lambdas don’t let you do anything that you couldn’t do prior to java-8, rather it enables you to write more concise code. The benefits of this, is that your code will be clearer and more flexible.

转载请注明:CodingBlog » lambda表达式除了保存代码行之外还有什么特殊用途吗?

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情