함수형 프로그래밍
(java 는 기본적으로 객체지향 언어라 함수형 프로그래밍이 불가능한데, JDK8부터 Stream API 와 람다식 등을 통하여 Java 를 이용해 함수형으로 프로그래밍 할 수 있는 API 를 제공해준다.)
스트림을 생성하는
최초연산, 중간 로직을 구성하는중간 연산, 결과물을 처리하는최종 연산으로 구성된다.
데이터 소스를 추상화하여 코드의 재사용성이 높아졌다
(데이터 소스의 추상화란? 데이터를 다루는데 자주 사용하는 메서드들을 정의
데이터 소스가 무엇이든 같은 방식으로 처리 가능 : 배열이나 List 를 둘다 Stream 으로 처리 가능하다)
작업을 내부 반복으로 처리함으로써 작업이 간결해질 수 있다.
( java8 이전엔 for 문으로 처리했지만, 지금은 .forEach 를 쓰면 되는 것 처럼.)
컬렉션 요소를 람다식으로 처리하여, 복잡한 구조의 데이터 처리를 간단하게 해주어 코드의 복잡도를 낮출 수 있다.
데이터를 다룰 때 병렬 처리가 쉽다. 멀티 스레드를 활용해서 병렬로 연산을 계산 할 수 있고,부 반복으로 연산을 수행하기 때문에 코드가 매우 간단해진다는 것을 알 수 있음.~
stream1.sorted().forEach(System.out::println);
int count = stream1.count(); // ERROR 스트림 닫힘
stream.forEach(System.out::println);
List<String> result = stream1.sorted().collect(Collectors.toList());
- Collection 에 스트림을 생성하는 메서드 정의
.stream()- Stream 에 스트림을 생성하는 static 메서드로 정의
.of()- IntStream 에 범위의 정수를 반환하여 스트림을 생성하는 메서드
.ranged()- 람다식을 매개변수로, 무한 스트림을 생성하는 메서드
.iterate(),.generate()
( iterate 와의 차이점은 매개변수가 없어야하고, 이전 결과를 이용하여 다음 결과를 계산하지 않는다)- Files 에 파일 목록을 소스로 하는 스트림 생성 메서드
.list()
List<Integer> list = ArrayList.asList(1,2,3,4);
Stream<Integer> stream = list.stream();
Stream<String> stream = Stream.of("a","b","c");
IntStream stream = IntStream.rangeClosed(1,5);
Stream<Integer> stream = Stream.iterate(0, n->n+2); //0,2,4,6...
Stream<Integer> stream = Stream.generate(()->1);
- 데이터 변환
map, 필터링filter, 정렬sort, 중복제거distinct등.. 을 제공한다- 매개변수로 함수형 인터페이스(Predicate)를 받는다.
(Type T인자를 받고boolean을 리턴하는 함수형 인터페이스)- 중간연산의 리턴 값은 스트림으로 계속해서 메서드 체이닝을 이어나갈 수 있다.
- 최종연산의 리턴값이 수행되지 않는다면 중간 연산 역시 수행되지 않는다.
(최종 연산이 수행되어야 중간연산을 거쳐 최종 연산이 이뤄진다)
.filter()
intStream.filter(i->i%2==0 && i%3!=0)
.forEach(System.out::print);
.map() , .mapToInt() , .mapToObj() ..
: 매개변수로 T 타입을 R 타입으로 변환해서 반환하는 함수를 지정
Student[] student = { new Student("홍길동",20,160) };
Stream<Student> studentStream = Stream.of(student);
//모두 대문자로 변환
studentStream.map(Student::getName)
.map(s->s.toUpperCase());
//기본형 스트림의 계산 메서드 제공
int avg = studentStream.mapToInt(Student::getTotalScore)
.average();
//정수를 문자열로 변환 (원시 Stream으로 변환)
Stream<String> lottoStream = new Random().ints(1,46)
.distinct().limit(6).sorted()
.mapToObj(i->i+",");
//문자열을 정수로 사용
int sum = "12345".chars()
.map(ch->ch-'0').sum(); //sum=15
sorted()
List<String> list = Arrays.asList{"c","b","a"};
list.stream().sorted().forEach(System.out::print); // [a,b,c]
//Comparator의 static 메서드) Comparator<T> 반환
studentStream.sorted(Comparator.comparing(Student::getAge)) // 우선 나이 순 정렬
.thenComparing(Student::getScore)) // 이후 성적 순 정렬
.forEach(System.out::print);
.findAny(), .findFirst(), .max(), min(), .reduce()
NullPointerException 을 방지 할 수 있다..get() 을 사용한다.
- 데이터 수집
collect, 조건 검사match, 통계count등.. 을 제공한다.- 스트림의 요소를 소모하여 결과를 만들어낸다.
.forEach()
: stream의 요소들을 대상으로 특정한 연산을 수행 할 때
: 반환 타입은 void
.collect()
: stream 의 요소들을 컬렉션이나 배열등으로 수집하는 최종 연산
: 매개변수로 Collector(인터페이스) 필요
: Collectors(클래스)에 static 메서드로 미리 작성된 Collector를 제공한다.
List<Student> students = Arrays.asList(new Student(1, "홍길동", 100),
new Student(2, "고길동", 80));
// List 반환
List<String> name = students.stream()
.map(Student::getName)
.collect(Collectors.toList());
// Map 반환 | <키,값> 지정
Map<Integer, Student> store = students.stream()
.collect(Collectors.toMap(s->s.getId(), s->s));
//Array 반환 | 해당 타입의 생성자 참조를 매개변수로 지정
Student[] student = students.stream().toArray(Student[]::new);
.match() : anyMatch, allMatch, noneMatch
: Stream 요소들이 특정한 조건을 충족하는 검사
// 1개의 요소라도 해당 조건을 만족하는가
boolean anyMatch = names.stream().anyMatch(name -> name.contains("a"));
// 모든 요소가 해당 조건을 만족하는가
boolean allMatch = names.stream().allMatch(name -> name.length() > 10);
// 모든 요소가 해당 조건을 만족하지 않는가
boolean noneMatch = names.stream().noneMatch(name -> name.length() < 5);
: 중간연산 & 최종연산
: 매개변수로 함수형 인터페이스를 받는다.
distinct() : 중복 제거
count() : 개수 반환
max,min()
limit() : 스트림의 일부만
findAny,findFirst() : 스트림 요소 하나만 반환
allMatch, anyMatch, noneMatch() : 주어진 조건을 모든 요소가 만족시키는지
filter() : 스트림의 조건
sorted() : 스트림의 요소를 정렬
map() : 스트림의 요소를 변환
forEach() : 각 요소에 지정된 작업 수행
toArray() : 배열로 반환collect() : 스트림의 요소 수집. 컬렉션으로 담아 반환
[개념 참조]
자바의 정석
https://mangkyu.tistory.com/112
https://ryan-han.com/post/dev/java-stream/
[기타 참조]
https://velog.io/@hygoogi/%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91-%EC%A4%80%EB%B9%84%ED%95%98%EA%B8%B0
https://dev-kani.tistory.com/32