Lambda
- 함수의 명세(접근제어자, 리턴 타입 등) 없이도 함수를 실행할 수 있는 기능
- 문법이 간결하고 편리하지만, 함수를 정의하는 것이 아니기 때문에 같은 코드를 반복해서 사용해야 함 (중복 코드가 많아짐)
- function 파라미터를 받는 함수일 경우 람다 식을 사용할 수 있다는 의미
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("korea");
list.add("japan");
list.add("france");
Stream<String> stream = list.stream();
stream.map(str -> {
System.out.println(str);
return str.toUpperCase();
}).forEach(it -> System.out.println(it));
// }).forEach(System.out::println);
// 파라미터 변수가 하나인 경우 변수를 입력하지 않는 람다식으로 변형 할수 있음
}
}
- map : 앞에 입력한 값을 파라미터 내에 입력한 다른 형식 등으로 바꾸는 함수
- toUpperCase : 소문자를 대문자로 바꾸는 함수
- forEach : 값마다 각각 실행하는 함수
- 람다 : 값을 하나씩 꺼내서 변수로 지칭하고 꺽쇄(->) 표시 뒤에 실행할 함수 작성 (중괄호와 return 구문을 사용하여 여러줄 작성 가능)
Stream
- 하나의 데이터의 흐름
- 스트림을 통해서 각 데이터를 어떻게 처리할지 유연한 코드를 작성할 수 있음
- 대표적인 예 : Collection을 통한 스트림 만들기
- java 8 버전부터 도입
- Stream 코드 입력 후 어떤 메소드를 사용하든 데이터를 하나씩 불러옴
- 기존 데이터 소스를 변경하지 않음(스트림 내에서만 데이터 형식 등 변경)
- forEach : return type 이 void 이기 때문에 실행 후 stream이 닫힘, 뒤에 어떤 stream 구문도 추가할 수 없음.
- 다른 스트림을 사용하고 싶을 경우 새로운 객체명으로 호출
Stream 예제
List<String> list = new ArrayList<>();
list.add("서울");
list.add("부산");
list.add("대전");
list.add("서울");
System.out.println(list); // [서울, 부산, 대전, 서울]
List<String> result = list.stream() //list를 차례대로 호출함
.limit(2) // list에서 앞의 두개만 남기고 지움
.collect(Collectors.toList()); //새로운 리스트로 만듦
System.out.println(result); // [서울, 부산]
Set<String> set = list.stream()
.filter(it -> "서울".equals(it))
//람다식을 사용하여 list를 순서대로 "서울"과 같은 문자열인지 확인
// .filter("서울"::equals)
// 파라미터 변수가 하나이므로 람다식 변경 가능
.collect(Collectors.toSet()); //새로운 set으로 만듦
System.out.println(set); // [서울]
//set은 중복을 허용하지 않고 순서가 없으므로 이렇게 출력됨
String[] arr = {"SQL", "Java", "Python"};
Stream<String> stringStream = Arrays.stream(arr);
stringStream.forEach(System.out::println);
//forEach를 사용해 파라미터 안의 구문(출력)을 실행
class Sale {
String fruitName;
int price;
float discount;
public Sale(String fruitName, int price, float discount){
this.fruitName = fruitName;
this.price = price;
this.discount = discount;
}
}
public class Main {
public static void main(String[] args) {
List<Sale> sales = Arrays.asList(
new Sale("apple", 5000, 0.05f),
new Sale("orange", 4000, 0.02f),
new Sale("grafe", 2000, 0)
);
Stream<Sale> saleStream = saleList.stream();
saleStream.map(sale -> Pair.of(sale.fruitName,
sale.price * (1 - sale.discount)))
//파라미터 left, right 값 입력
.forEach(pair -> System.out.println(pair.getLeft()
+ " 실 구매가: " + pair.getRight() + "원 "));
}
}
//Pair 클래스는 build.gradel에 dependency 추가 또는
클래스를 직접 만들어서 사용해야 함.
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
System.out.println(list.stream().reduce(0, Integer::sum));
//asList : 고정된 List 생성
//reduce : 파라미터에 들어있는 값과 list 값을 하나씩 꺼내어
sum 메소드를 실행하고 연산한 값을 누적함 (0+1, 1+2, 3+3...)
List<String> names = Arrays.asList("김정우", "김호정", "이하늘", "이정희",
"박정우", "박지현", "정우석", "이지수");
long count = names.stream()
.filter(str -> str.startsWith("이"))
.count();
System.out.println("count : " + count);
- count() 라는 종결함수는 Stream 의 갯수를 세기 때문에 효율을 위해 중간 연산을 생략하기도 합니다. 그래서 중간 연산을 강제로 실행시키고 싶다면 filter 나 flatMap 과 같이 Stream 요소의 갯수를 변화시킬 수 있는 중간 연산을 추가하면 됩니다.
- 출처 : https://bcp0109.tistory.com/314