람다와 스트림을 사용하면 코드의 양 감소 및 읽기 쉬운 코드를 만드는데 유리하다.
람다는 익명 함수(Anonymous functions)을 의미한다.
먼저 아래의 인터페이스를 보자
interface Calculator{
int sum(int a, int b);
}
위 인터페이스를 사용하려면 다음처럼 Calculator 인터페이스를 구현해야 한다.
class MyCalculator implements Calculator{
public int sum(int a, int b){
return a+b;
}
}
public class Sample{
public static void main(String[] args){
MyCalculator mc = new MyCalculator();
int result = mc.sum(3,4);
System.out.println(result); // 7출력
}
}
위 코드를 다음처럼 람다를 적용한 코드로 변경
interface Calculator{
int sum(int a, int b);
}
public class Sample{
public static void main(String[] args){
Calculator mc = (int a, intb) -> a+b; // 람다 적용
}
}
인터페이스의 메서드가 1개 이상이면 람다함수 생성 불가.
interface Calculator{
int sum(int a, int b);
int mul(int a, int b); // mul 메서드 추가시 컴파일 에러 발생
}
따라서 람다 함수로 사용할 인터페이스는 @FunctionalInterface
어노테이션을 사용하는 것이 좋다.
@FunctionalInterface
interface Calculator{
int sum(int a, int b);
// int mul(int a, int b); // FunctionalInterface는 두번째 메서드를 허용하지 않는다.
}
Integer.sum(int a,int b)
와 동일해 위와 같이 작성 가능::
메서드 방식으로 구분해 표기BiFunction
인터페이스 사용해 Calculator 인터페이스 대신 아래처럼 작성 가능
import java.util.fuction.BiFuncion;
public class Sample{
public sataic void main(String[] args){
BiFunction<Integer, Integer, Integer> mc = (a,b) ->(a+b);
int result = mc.apply(3,4); // sum이 아닌 apply 메서드 적용
System.out.println(result);
}
}
입출력 모두 동일할 경우 BinaryOperator
사용
import java.util.function.BinaryOperator;
public class Sample{
public static void main(String[] args){
BinaryOperator<Integer> mc= (a,b)->a+b;
int result = mc.apply(3,4);
System.out.println(result); // 7출력
}
}
스트림은 "흐름"이라는 의미이며, 데이터가 흐르며 필터링 과저을 통해 여러번 변경/반환되기 때문에 스트림이라는 이름을 갖게 되었다.
int[] data = {5,6,4,2,3,4,1,1,2,2,,4,8}
----------------------------------------
(출력결과)
int[] result = {8,6,4,2};
스트림 사용전
import java.lang.reflect.Array;
import java.util.*;
public class test {
public static void main(String[] args) {
int[] data = {5,6,4,2,3,4,1,1,2,2,4,8};
//짝수만 포함하는 ArrayList 생성ㄴ
ArrayList<Integer> dataList = new ArrayList<>();
for(int i=0; i<data.length; i++){
if(data[i]%2==0){
dataList.add(data[i]);
}
}
// Set 사용해 중복 제거
HashSet<Integer> dataSet=new HashSet<>(dataList);
// Set을 다시 List로 변경
ArrayList<Integer> distinctList = new ArrayList<>(dataSet);
//역순으로 정렬
distinctList.sort(Comparator.reverseOrder());
// Integer 리스트를 정수 배열로 변환
int[] result = new int[distinctList.size()];
for (int i = 0; i < distinctList.size(); i++) {
result[i] = distinctList.get(i);
}
System.out.println(result);
}
}
스트림 사용후
import java.util.*;
public class test {
public static void main(String[] args) {
int[] data = {5,6,4,2,3,4,1,1,2,2,4,8};
//짝수만 포함하는 ArrayList 생성
int[] result = Arrays.stream(data) // Instream 생성
.boxed() //Intsteam을 Stream<Integer>로 변경
.filter((a)->a%2==0) // 짝수만 선별
.distinct() // 중복 제거
.sorted(Comparator.reverseOrder()) // 역순 정렬
.mapToInt(Integer::intValue) // Stream<Integer>를 InStream으로 변경.
.toArray() // int[] 배열로 반환
;
}
}
위 코드는 다음과 같은 순서로 동작한다.
1. Arrays.stream(data)
으로 정수 배열을 IntStream으로 생성
2. .boxed()
로 IntStream을 Integer의 Stream으로 변경한다. (Comparator.reverseOrder
와 같은 메서드는 원시 타입인 Integer를 사용하기 때문)
3. .filter((a)->a%2==0)
로 짝수만 필터링
4. .distinct()
로 스트림에서 중복 제거
5. .sorted(Comparator.reverseOrder())
로 역순 정렬
6. .mapToInt(Integer::intValue)
로 Integer의 Stream을 IntStream으로 변경한다.
(최종적으로 int[]
타입 배열을 리턴해야 하기 때문)
7. .toArray()
를 호출해 IntStream 배열인 int[]
배열 리턴