함수형 프로그래밍
(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