람다 식에는 코드 줄 저장 이외의 용도가 있습니까?
람다 식에는 코드 줄 저장 이외의 용도가 있습니까?
해결하기 쉽지 않은 문제를 해결 한 람다가 제공하는 특별한 기능이 있습니까? 내가 본 전형적인 사용법은 이것을 쓰는 대신 :
Comparator<Developer> byName = new Comparator<Developer>() {
@Override
public int compare(Developer o1, Developer o2) {
return o1.getName().compareTo(o2.getName());
}
};
람다 식을 사용하여 코드를 줄일 수 있습니다.
Comparator<Developer> byName =
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());
Lambda 표현식은 일반적으로 Java로 해결할 수있는 일련의 문제를 변경하지 않지만 더 이상 어셈블리 언어로 프로그래밍하지 않는 것과 같은 이유로 특정 문제를보다 쉽게 해결합니다. 프로그래머의 작업에서 여분의 작업을 제거하면 삶을 더 쉽게 만들고 다른 방법으로는 손대지 않은 작업을 수행 할 수 있습니다 (수동으로).
그러나 람다 식은 코드를 저장하는 것만이 아닙니다. 람다 식을 사용하면 함수 를 정의 할 수 있습니다. 이전에는 해결 방법으로 익명 내부 클래스를 사용할 수 있었기 때문에 이러한 경우 익명 내부 클래스를 대체 할 수 있지만 일반적으로는 그렇지 않습니다.
특히, 람다 식은 변환 될 기능 인터페이스에 독립적으로 정의되므로 액세스 할 수있는 상속 된 멤버가 없으며 기능 인터페이스를 구현하는 유형의 인스턴스에 액세스 할 수 없습니다. 람다 식 내 this
및 super
주변의 상황에서와 같은 의미를 가지고, 또한 볼 이 대답 . 또한 주변 컨텍스트의 로컬 변수를 음영 처리하는 새 로컬 변수를 만들 수 없습니다. 함수를 정의하려는 의도 된 작업의 경우 많은 오류 소스가 제거되지만 다른 사용 사례의 경우 기능적 인터페이스를 구현하더라도 람다 식으로 변환 할 수없는 익명 내부 클래스가있을 수 있음을 의미합니다.
또한이 구문 new Type() { … }
은 new
항상 그렇듯이 새로운 고유 인스턴스를 생성하도록 보장합니다 . 익명의 내부 클래스 인스턴스는 static
컨텍스트 가 아닌 상태 에서 생성 된 경우 항상 외부 인스턴스에 대한 참조를 유지합니다 . 반대로 람다 식은 this
필요할 때, 즉 액세스 this
하거나 static
멤버 가 아닌 경우에 대한 참조 만 캡처합니다 . 또한 의도적으로 지정되지 않은 아이디의 인스턴스를 생성하여 구현시 런타임에 기존 인스턴스의 재사용 여부를 결정할 수 있습니다 (“ 람다식이 실행될 때마다 힙에 객체를 생성합니까? ”참조).
이러한 차이점은 귀하의 예에 적용됩니다. 익명의 내부 클래스 구조는 항상 새로운 인스턴스를 생성하고 외부 인스턴스에 대한 참조를 캡처 할 수 있지만 (Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName())
일반적인 구현에서는 단일 톤으로 평가되는 캡처되지 않는 람다 식입니다. 또한 .class
하드 드라이브에 파일을 생성하지 않습니다 .
시맨틱과 성능에 대한 차이점을 감안할 때 람다 식은 프로그래머가 미래에 특정 문제를 해결하는 방식을 바꿀 수 있습니다. 물론 새로운 API는 새로운 언어 기능을 활용하는 기능적 프로그래밍 아이디어를 수용하기 때문입니다. Java 8 람다 식 및 일류 값 도 참조하십시오 .
프로그래밍 언어는 기계가 실행할 수 없습니다.
프로그래머가 생각할 수 있습니다.
언어는 우리의 생각을 기계가 실행할 수있는 것으로 바꾸는 컴파일러와의 대화입니다. 다른 언어에서 온 (또는 사람에서 자바에 대한 주요 불만 중 하나 남겨 을 위해 이 있음으로 사용되는 다른 언어) 강제 프로그래머의 특정 정신적 모델을 (즉, 모든 클래스)입니다.
나는 그것이 좋은지 나쁜지에 무게를 두지 않을 것입니다. 모든 것이 절충입니다. 그러나 Java 8 람다는 프로그래머가 이전에는 Java로는 할 수 없었던 기능 측면 에서 생각할 수있게합니다 .
자바에 와서 클래스 에 대해 생각 하는 것은 절차 적 프로그래머 학습과 같은 것입니다. 그들은 점차 영광스러운 구조체 인 클래스에서 점차 움직이고 정적 메소드가 많은 '도우미'클래스가있는 것을 보았습니다. 합리적 OO 디자인 (mea culpa)과 더 유사합니다.
익명의 내부 클래스를 표현하는 더 짧은 방법으로 생각하면 위의 절차 프로그래머가 클래스가 크게 향상되었다고 생각하지 않는 방식으로 인상적이지 않을 것입니다.
더 짧고 명확한 방식으로 상당한 논리 덩어리를 작성할 수 있으면 다른 사람들이 읽고 이해하는 데 시간이 덜 걸리면 코드 줄을 저장하는 것이 새로운 기능으로 볼 수 있습니다.
람다 식 (및 / 또는 메서드 참조)이 없으면 Stream
파이프 라인을 훨씬 쉽게 읽을 수 없었을 것입니다.
예를 들어, Stream
각 람다 식을 익명 클래스 인스턴스로 바꾸면 다음 파이프 라인이 어떻게 생겼는지 생각해보십시오 .
List<String> names =
people.stream()
.filter(p -> p.getAge() > 21)
.map(p -> p.getName())
.sorted((n1,n2) -> n1.compareToIgnoreCase(n2))
.collect(Collectors.toList());
다음과 같습니다.
List<String> names =
people.stream()
.filter(new Predicate<Person>() {
@Override
public boolean test(Person p) {
return p.getAge() > 21;
}
})
.map(new Function<Person,String>() {
@Override
public String apply(Person p) {
return p.getName();
}
})
.sorted(new Comparator<String>() {
@Override
public int compare(String n1, String n2) {
return n1.compareToIgnoreCase(n2);
}
})
.collect(Collectors.toList());
이것은 람다식이있는 버전보다 쓰기가 훨씬 어렵고 오류가 발생하기 쉽습니다. 이해하기도 어렵습니다.
그리고 이것은 비교적 짧은 파이프 라인입니다.
람다 식과 메서드 참조없이 이것을 읽을 수있게하려면 여기에서 사용되는 다양한 기능 인터페이스 인스턴스를 보유하는 변수를 정의해야하는데, 이로 인해 파이프 라인의 논리가 분할되어 이해하기가 더 어려워졌습니다.
내부 반복
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<Integer>() {
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);
Behaviors as arguments
Guess the following case:
public int sumAllEven(List<Integer> 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<Integer> numbers, Predicate<Integer> 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: DZone - Why We Need Lambda Expressions in Java
There are many benefits of using lambdas instead of inner class following as below:
Make the code more compactly and expressive without introducing more language syntax semantics. you already gave an example in your question.
By using lambdas you are happy to programming with functional-style operations on streams of elements, such as map-reduce transformations on collections. see java.util.function & java.util.stream packages documentation.
There is no physical classes file generated for lambdas by compiler. Thus, it makes your delivered applications smaller. How Memory assigns to lambda?
The compiler will optimize lambda creation if the lambda doesn't access variables out of its scope, which means the lambda instance only create once by the JVM. for more details you can see @Holger's answer of the question Is method reference caching a good idea in Java 8? .
Lambdas can implements multi marker interfaces besides the functional interface, but the anonymous inner classes can't implements more interfaces, for example:
// v--- create the lambda locally. Consumer<Integer> action = (Consumer<Integer> & Serializable) it -> {/*TODO*/};
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.
One thing I don't see mentioned yet is that a lambda lets you define functionality where it's used.
So if you have some simple selection function you don't need to put it in a separate place with a bunch of boilerplate, you just write a lambda that's concise and locally relevant.
Yes many advantages are there.
- No need to define whole class we can pass implementation of function it self as reference.
- Internally creation of class will create .class file while if you use lambda then class creation is avoided by compiler because in lambda you are passing function implementation instead of class.
- Code re-usability is higher then before
- And as you said code is shorter then normal implementation.
Lambdas are just syntactic sugar for anonymous classes.
Before lambdas, anonymous classes can be used to achieve the same thing. Every lambda expression can be converted to an anonymous class.
If you are using IntelliJ IDEA, it can do the conversion for you:
- Put the cursor in the lambda
- Press alt/option + enter
'Programming' 카테고리의 다른 글
Node.js 템플릿을위한 Jade와 EJS의 장단점은 무엇입니까? (0) | 2020.07.18 |
---|---|
SQL Server 2008 및 SQL Server 2005 및 날짜 시간 사용 (0) | 2020.07.18 |
플레이시 휴식! (0) | 2020.07.18 |
vb.net에서 중첩 / 종료 (0) | 2020.07.18 |
ApiController로 원시 문자열을 반환하는 방법은 무엇입니까? (0) | 2020.07.18 |