java
이 기사에서는 Java 람다 식과 기능 인터페이스, 일반 기능 인터페이스 및 스트림 API와 함께 람다 식을 사용하는 방법에 대해 예제를 통해 배웁니다.
람다 표현식은 Java 8에서 처음 도입되었습니다. 언어의 표현력을 높이는 것이 주요 목표입니다.
그러나 람다에 들어가기 전에 먼저 기능적 인터페이스를 이해해야 합니다.
<시간>Java 인터페이스에 하나의 추상 메소드만 포함되어 있으면 이를 기능 인터페이스라고 합니다. 이 단 하나의 메소드는 인터페이스의 의도된 목적을 지정합니다.
예를 들어, Runnable
패키지 java.lang
의 인터페이스; 하나의 메소드(예:run()
)만 구성하기 때문에 기능적 인터페이스입니다. .
import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
// the single abstract method
double getValue();
}
위의 예에서 인터페이스 MyInterface에는 하나의 추상 메소드 getValue()만 있습니다. 따라서 기능적 인터페이스입니다.
여기에서는 @FunctionalInterface
주석을 사용했습니다. . 주석은 Java 컴파일러가 인터페이스가 기능적 인터페이스임을 나타내도록 합니다. 따라서 둘 이상의 추상 메서드를 사용할 수 없습니다. 그러나 의무 사항은 아닙니다.
Java 7에서 기능 인터페이스는 단일 추상 메소드 또는 SAM으로 간주되었습니다. 유형. SAM은 일반적으로 Java 7에서 Anonymous Classes로 구현되었습니다.
public class FunctionInterfaceTest {
public static void main(String[] args) {
// anonymous class
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("I just implemented the Runnable Functional Interface.");
}
}).start();
}
}
출력 :
I just implemented the Runnable Functional Interface.
여기에서 익명 클래스를 메서드에 전달할 수 있습니다. 이것은 Java 7에서 더 적은 수의 코드로 프로그램을 작성하는 데 도움이 됩니다. 그러나 구문은 여전히 어렵고 많은 추가 코드 라인이 필요했습니다.
Java 8은 한 단계 더 나아가 SAM의 기능을 확장했습니다. 함수형 인터페이스에는 하나의 메서드만 있다는 것을 알고 있기 때문에 인수로 전달할 때 해당 메서드의 이름을 정의할 필요가 없습니다. 람다 표현식을 사용하면 정확히 그렇게 할 수 있습니다.
<시간>람다 표현식은 기본적으로 익명 또는 이름 없는 메서드입니다. 람다 식은 자체적으로 실행되지 않습니다. 대신, 기능적 인터페이스에 의해 정의된 메소드를 구현하는 데 사용됩니다.
다음은 Java에서 람다 표현식을 정의하는 방법입니다.
(parameter list) -> lambda body
새 연산자(->
) 사용되는 화살표 연산자 또는 람다 연산자로 알려져 있습니다. 현재 구문이 명확하지 않을 수 있습니다. 몇 가지 예를 살펴보겠습니다.
다음과 같은 방법이 있다고 가정해 보겠습니다.
double getPiValue() {
return 3.1415;
}
다음과 같이 람다 식을 사용하여 이 메서드를 작성할 수 있습니다.
() -> 3.1415
여기에서 메서드에는 매개변수가 없습니다. 따라서 연산자의 왼쪽에는 빈 매개변수가 포함됩니다. 오른쪽은 람다 식의 동작을 지정하는 람다 본문입니다. 이 경우 값 3.1415를 반환합니다.
<시간>Java에서 람다 본문은 두 가지 유형입니다.
1. 하나의 표정을 가진 몸
() -> System.out.println("Lambdas are great");
이러한 유형의 람다 본문을 표현식 본문이라고 합니다.
2. 코드 블록으로 구성된 본문입니다.
() -> {
double pi = 3.1415;
return pi;
};
이러한 유형의 람다 바디를 블록 바디라고 합니다. 블록 본문을 사용하면 람다 본문에 여러 문을 포함할 수 있습니다. 이 명령문은 중괄호 안에 포함되며 중괄호 뒤에 세미콜론을 추가해야 합니다.
참고 :블록 본문의 경우 본문이 값을 반환하면 return 문을 가질 수 있습니다. 그러나 표현식 본문에는 return 문이 필요하지 않습니다.
<시간>
람다 식을 사용하여 Pi 값을 반환하는 Java 프로그램을 작성해 보겠습니다.
앞에서 언급했듯이 람다 식은 자체적으로 실행되지 않습니다. 오히려 기능 인터페이스에 의해 정의된 추상 메소드의 구현을 형성합니다.
따라서 먼저 기능적 인터페이스를 정의해야 합니다.
import java.lang.FunctionalInterface;
// this is functional interface
@FunctionalInterface
interface MyInterface{
// abstract method
double getPiValue();
}
public class Main {
public static void main( String[] args ) {
// declare a reference to MyInterface
MyInterface ref;
// lambda expression
ref = () -> 3.1415;
System.out.println("Value of Pi = " + ref.getPiValue());
}
}
출력 :
Value of Pi = 3.1415
위의 예에서
getPiValue()
라는 단일 추상 메서드가 포함됩니다.
// it will throw an error
MyInterface ref = new myInterface();
// it is valid
MyInterface ref;
ref = () -> 3.1415;
getPiValue()
메서드를 호출합니다. 참조 인터페이스를 사용합니다. 언제
System.out.println("Value of Pi = " + ref.getPiValue());
지금까지 매개변수 없이 람다 표현식을 만들었습니다. 그러나 메서드와 마찬가지로 람다 식에도 매개 변수가 있을 수 있습니다. 예를 들어,
(n) -> (n%2)==0
여기서 괄호 안의 변수 n은 람다 식에 전달되는 매개변수입니다. 람다 본문은 매개변수를 받아 짝수인지 홀수인지 확인합니다.
@FunctionalInterface
interface MyInterface {
// abstract method
String reverse(String n);
}
public class Main {
public static void main( String[] args ) {
// declare a reference to MyInterface
// assign a lambda expression to the reference
MyInterface ref = (str) -> {
String result = "";
for (int i = str.length()-1; i >= 0 ; i--)
result += str.charAt(i);
return result;
};
// call the method of the interface
System.out.println("Lambda reversed = " + ref.reverse("Lambda"));
}
}
출력 :
Lambda reversed = adbmaL<시간>
지금까지 한 가지 유형의 값만 허용하는 기능적 인터페이스를 사용했습니다. 예를 들어,
@FunctionalInterface
interface MyInterface {
String reverseString(String n);
}
위의 기능 인터페이스는 String
만 허용합니다. String
를 반환합니다. . 그러나 기능 인터페이스를 일반화하여 모든 데이터 유형이 허용되도록 할 수 있습니다. 제네릭에 대해 잘 모르는 경우 Java Generics를 방문하십시오.
// GenericInterface.java
@FunctionalInterface
interface GenericInterface<T> {
// generic method
T func(T t);
}
// GenericLambda.java
public class Main {
public static void main( String[] args ) {
// declare a reference to GenericInterface
// the GenericInterface operates on String data
// assign a lambda expression to it
GenericInterface<String> reverse = (str) -> {
String result = "";
for (int i = str.length()-1; i >= 0 ; i--)
result += str.charAt(i);
return result;
};
System.out.println("Lambda reversed = " + reverse.func("Lambda"));
// declare another reference to GenericInterface
// the GenericInterface operates on Integer data
// assign a lambda expression to it
GenericInterface<Integer> factorial = (n) -> {
int result = 1;
for (int i = 1; i <= n; i++)
result = i * result;
return result;
};
System.out.println("factorial of 5 = " + factorial.func(5));
}
}
출력 :
Lambda reversed = adbmaL factorial of 5 = 120
위의 예에서는 GenericInterface라는 일반 기능 인터페이스를 만들었습니다. . 여기에는 func()
라는 일반 메서드가 포함되어 있습니다. .
여기 Main 클래스 내부
GenericInterface<String> reverse
- 인터페이스에 대한 참조를 생성합니다. 인터페이스는 이제 String
에서 작동합니다. 데이터 유형.GenericInterface<Integer> factorial
- 인터페이스에 대한 참조를 생성합니다. 이 경우 인터페이스는 Integer
에서 작동합니다. 데이터 유형.
새로운 java.util.stream 패키지가 JDK8에 추가되어 Java 개발자가 Lists
과 같은 컬렉션 검색, 필터링, 매핑, 축소 또는 조작과 같은 작업을 수행할 수 있습니다. .
예를 들어 데이터 스트림(이 경우 List
String
) 여기서 각 문자열은 국가 이름과 국가의 장소를 조합한 것입니다. 이제 이 데이터 스트림을 처리하고 네팔에서 장소만 검색할 수 있습니다.
이를 위해 Stream API와 Lambda 표현식을 조합하여 스트림에서 대량 작업을 수행할 수 있습니다.
import java.util.ArrayList;
import java.util.List;
public class StreamMain {
// create an object of list using ArrayList
static List<String> places = new ArrayList<>();
// preparing our data
public static List getPlaces(){
// add places and country to the list
places.add("Nepal, Kathmandu");
places.add("Nepal, Pokhara");
places.add("India, Delhi");
places.add("USA, New York");
places.add("Africa, Nigeria");
return places;
}
public static void main( String[] args ) {
List<String> myPlaces = getPlaces();
System.out.println("Places from Nepal:");
// Filter places from Nepal
myPlaces.stream()
.filter((p) -> p.startsWith("Nepal"))
.map((p) -> p.toUpperCase())
.sorted()
.forEach((p) -> System.out.println(p));
}
}
출력 :
Places from Nepal: NEPAL, KATHMANDU NEPAL, POKHARA
위의 예에서 다음 문장에 주목하십시오.
myPlaces.stream()
.filter((p) -> p.startsWith("Nepal"))
.map((p) -> p.toUpperCase())
.sorted()
.forEach((p) -> System.out.println(p));
여기에서는 filter()
과 같은 방법을 사용하고 있습니다. , map()
및 forEach()
스트림 API의 이러한 메서드는 람다 식을 입력으로 사용할 수 있습니다.
위에서 배운 구문을 기반으로 고유한 표현식을 정의할 수도 있습니다. 이를 통해 위의 예에서 본 것처럼 코드 줄을 크게 줄일 수 있습니다.
java
자바 반복자 인터페이스 이 튜토리얼에서는 예제를 통해 Java Iterator 인터페이스에 대해 알아볼 것입니다. Iterator Java 컬렉션 프레임워크의 인터페이스를 사용하면 컬렉션의 요소에 액세스할 수 있습니다. ListIterator 하위 인터페이스가 있습니다. . 모든 Java 컬렉션에는 iterator()이 포함됩니다. 방법. 이 메서드는 컬렉션 요소를 반복하는 데 사용되는 iterator의 인스턴스를 반환합니다. 반복자 메소드 Iterator 인터페이스는 컬렉션 요소에 대해 다양한 작업을 수행하는 데 사용
자바 ListIterator 인터페이스 이 튜토리얼에서는 예제를 통해 Java ListIterator 인터페이스에 대해 알아볼 것입니다. ListIterator Java 컬렉션 프레임워크의 인터페이스는 목록의 요소에 액세스하는 기능을 제공합니다. 양방향입니다. 즉, 목록의 요소를 양방향으로 반복할 수 있습니다. Iterator 확장 인터페이스. List 인터페이스는 listIterator()를 제공합니다. ListIterator 인스턴스를 반환하는 메서드 인터페이스. ListIterator의 메소드 ListItera