자바의 람다식은 함수형 프로그래밍에서 사용되는 함수를 간결하게 표현하기 위한 방법 중 하나이다.
람다식은 자바8부터 도입되었으며, 람다식은 익명함수(anonymous function)의 한 형태로서, 메서드 구현을 간결하게 표현하는 방법이다.
람다식은 다음과 같은 구조로 이루어진다.
(parameters) -> {expression} // 함수의 이름이 없다.(익명 함수)위 구조에서 parameters는 메서드에서 사용할 매개변수, expression은 메서드의 구현체를 나타낸다.
예를 들어 2개의 정수를 더하는 메서드를 람다식으로 구현하면 다음과 같이 작성할 수 있다.
(int x, int y) -> {return x + y;}
람다식은 함수형 인터페이스와 함께 사용된다. 특히 java.util.function패키지에 많은 함수형 인터페이스가 정의되어 있어 이 인터페이스들을 람다식으로 구현해 사용할 수 있다.
다음은 함수형 인터페이스를 람다식으로 구현한 예시이다.
@FunctionalInterface // 함수형 인터페이스
public interface MathOperation {
public int operation(int x, int y);
}
public class LambdaTest {
public static void main(String[] args) {
// MathOperation add = (int x, int y) -> { return x + y; };
MathOperation add = (x, y) -> x + y; // 타입 및 return 생략 가능
int result = add.operation(10, 20);
System.out.println("result = " + result);
}
}
람다식을 사용하면 코드가 줄고 간편하게 인터페이스를 구현할 수 있어서 확장성도 커진다.
public class LambdaTest {
public static void main(String[] args) {
MathOperation add = (x, y) -> x + y; // 코드가 줄어 간편하게 구현할 수 있고, 확장이 쉬워진다.
MathOperation multi = (x, y) -> x * y;
MathOperation minus = (x, y) -> x - y;
MathOperation divid = (x, y) -> x / y;
int result1 = add.operation(60, 30);
int result2 = multi.operation(60, 30);
int result3 = minus.operation(60, 30);
int result4 = divid.operation(60, 30);
System.out.println("result1 = " + result1);
System.out.println("result2 = " + result2);
System.out.println("result3 = " + result3);
System.out.println("result4 = " + result4);
}
}
람다식을 메서드 내에서 사용하거나 메서드의 인자로 전달할 수도 있다.
public class LambdaApplyTest {
public static void main(String[] args) {
// 람다식으로 모든 문자를 대문자로 변환하는 StringOperation 구현
StringOperation operationUpperCase = s -> s.toUpperCase();
StringOperation operationLowerCase = s -> s.toLowerCase();
String input = "Lambda Expresstions";
System.out.println(processString(input, operationUpperCase)); // operationUpperCase람다식 전달
System.out.println(processString(input, operationLowerCase)); // operationLowerCase람다식 전달
}
public static String processString(String input, StringOperation operation) { // 람다식을 메서드의 인자로 전달
return operation.apply(input); // 해당 메서드 내에서 람다식이 사용되게 된다.
}
}
각각 구현한 람다식을 따로 사용하지 않고, 메서드의 인자로 람다식을 전달해 코드 수정을 용이하게 만들고 확장성을 높였다.
스트림은 자바8에서 도입된 기능으로, 데이터의 흐름을 다루기 위한 선언형 API이다,
스트림을 사용해 필터링, 매핑, 정렬 등 다양한 데이터 처리 작업을 적용할 수 있으며, 최종 결과를 배열이나 컬렉션으로 변환할 수 있다. 또한, 스트림은 데이터 처리 작업을 연속적인 파이프라인으로 나타낼 수 있어 가독성이 높고, 병력처리를 쉽게 구현할 수 있다.
배열을 스트림으로 변환한다는 것은 배열의 원소들을 스트림 형태로 변환하여 처리할 수 있게 하는 것이다. 스트림은 원본 데이터를 변경하지 않고, 필요한 데이터 처리 작업을 적용한 결과를 생설하기 때문에 인덱스를 통한 접근은 제공하지 않는다.
1. Arrays.stream() 메서드 사용
int[] numbers = {1,2,3,4,5};
intStream stream = Arrays.stream(numbers);
위 코드에서 numbers 배열을 스트림으로 변환한 뒤 StreamAPI에서 제공하는 메서드를 활용해 다양한 방식의 처리를 할 수 있다.
int sumOfEvens = Arrays.stream(numbers) // 배열을 스트림으로 변환 후 1. 짝수 원소만 골라 2. 합계를 계산
.filter(n -> n % 2 == 0)
.sum();
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
int[] evenNumbers = Arrays.stream(numbers) // 배열을 스트림으로 변환 후 1. 짝수 원소만 골라 2. 배열로 변환
.filter(n -> n % 2 == 0)
.toArray();
스트림API와 함수형 인터페이스를 사용해 List에 저장된 정수들의 짝수 여부를 판별하고, 짝수들만 필터링하여 정렬하고, 각 숫자를 제곱한 후 모든 숫자의 합을 계산해보자
public class StreamExampleTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(3,5,6,9,7,4,1,10,8,2);
//Predicate<Integer> isEven = n -> n % 2 == 0;
int sumOfSquares = list.stream()
.filter(StreamExampleTest::isEven)
.sorted()
.map(n -> n * n)
.reduce(0, Integer::sum);
System.out.println("짝수의 제곱의 합 = " + sumOfSquares);
}
public static boolean isEven(int number) {
return number % 2 == 0;
}
}
정수 리스트에서 각 원소를 제곱한 값을 출력
public class MapStreamTest {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1,3,5,4,2);
List<Integer> squaredNumbers = numbers.stream()
.sorted()
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println("squaredNumbers = " + squaredNumbers);
}
}
스트림의 문자열 원소를 대문자로 변환
public class MapStreamTest2 {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry", "orange");
List<String> uppercase = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println("uppercase : " + uppercase);
for(String str : uppercase) {
System.out.println("str : " + str);
}
}
}