## 📌 스트림
자바8 부터 추가된, 컬렉션의 저장요소를 하나씩 참조해서
람다식으로 처리할 수 있도록 해주는 '반복자'이다.
✨ 반복자 스트림
자바7이전까지는 Iterator 반복자 사용하여 컬렉션 요소를 순차 처리함
이제는 Stream 이용도 가능.
🌳 스트림의 특징 🌳
Stream은 Iterator와 비슷한 역할을 하는 반복자이지만,
람다식으로 요소 처리 코드를 제공하는 점과,
내부 반복자를 사용하므로 병렬처리가 쉽다는 점,
중간처리와 최종 처리 작업을 수행하는 점에서 많은 차이를 가지고 있다.
✨ 외부반복자(external iterator)란
개발자가 코드로 직접 컬렉션의 요소를 반복해서 가져오는 코드 패턴을 말함.
반면에 내부반복자(internal iterator)는 컬렉션 내부에서 요소들을 반복시키고,
개발자는 요소당 처리해야할 코드만 제공하는 코드 패턴을 말함.
스트림은 중간처리와 최종처리를 할 수 있다.
중간처리에서는 매핑, 필터링, 정렬을 수행하고
최종처리에서는 반복, 카운팅, 평균, 총합등 집계 처리를 수행한다.
java.util.stream 패키지에 Stream API 들이 들어있다.
BaseStream
- Stream
- DoubleStream
- IntStream
- LongStream
1) 컬렉션으로 부터 스트림 얻기
컬렉션변수.stream()
2) 배열로 부터 스트림 얻기
Arrays.stream(배열)
3) 숫자 범위로부터 스트림 얻기
IntStream.range(int start, int endExclusive)
IntStream.rangeClosed(int start, int endInclusive)
다량의 데이터를 가공해서 축소하는 것을 일반적으로 리덕션이라고 하는데,
데이터의 합계, 평균값, 카운팅, 최대값, 최소값 등
대표적인 리덕션의 결과물이라고 볼 수 있다.
컬렉션의 요소를 리덕션의 결과물로 바로 집계할 수 없을 경우
필터링, 매핑, 정렬, 그룹핑등 중간 처리가 필요하다.
💡중간처리와 최종처리를 파이프라인으로 해결한다. 파이프라인은 여러개의 스트림이 연결되어있는 구조를 말한다.
✨중간처리 기능으로 요소를 걸러내는 역할
distinct() : 중복제거
filter(Predicate/IntPredicate/Long../Double..) : 조건 필터링 변수 -> {true/false로 리턴}
✨ 중간처리 기능으로 스트림의 요소를 다른 요소로 대체하는 작업을 함.
1) flapMapXXX()
요소를 대체해주는 여러개의 요소들로 구성된 새로운 스트림을 리턴함
2) mapXXX()
요소를 대체해주는 요소로 구성된 새로운 스트림을 리턴함.
3) asXXXStream(), boxed()
asDoubleStream() : IntStream의 int, LongStream의 long요소를 double로 변환해
DoubleStream으로 생성해줌
asLongStream() : IntStream의 int를 long으로 변환해 LongStream으로 생성
boxed() : int,long,double 을 wrapper클래스 요소로 박싱해서 Stream으로 생성
✨최종 처리전에 중간단계에서 요소를 정렬해 최종처리 해주어야 할 경우
요소가 객체일 경우에는 Comparable 을 구현하지 않은 객체일때 예외발생
sorted()는 Comparble을 구현한 요소에서 사용 가능.
✨루핑은 요소 전체를 반복하는 것.
peek() : 중간처리 메서드
forEach() : 최종처리 메서드
✨최종 처리 단계에서 요소들이 특정 조건에 만족하는지 조사 할수 있도록 세가지 매칭메서드 제공
✨집계는 최종처리 기능, 처리한후 하나의 값으로 산출해줌
1) Optional 클래스
단순히 집계값만 저장하는 것이 아니라,
집계값이 존재하지 않는 경우 디폴트 값을 설정할 수도 있고,
집계값을 처리하는 Consumer도 등록할 수 있다.
//스트림 활용을 위한 클래스 생성
public class Student implements Comparable<Student> {
private String name;
private int score;
public Student(String name ,int score) {
this.name = name ; this.score = score;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
@Override
public int compareTo(Student o) {
// TODO Auto-generated method stub
return Integer.compare(score,o.score);
//score < o.score 음수
// score == o.score 0
// score> o.score 양수
}
}
//스트림 사용하는 메인메서드
public class Stream02 {
public static void main(String[] args) {
List<Student> list = Arrays.asList(
new Student("jace",90),
new Student("peter",93),
new Student("linda",95)
);
//문법 늘여서 분석
Stream<Student> stream = list.stream(); // 스트림 리스트 생성
stream.forEach(s ->{ // 스트림 람다식과 foreach문으로 출력
String name = s.getName();
int score = s.getScore();
System.out.println(name+ " "+score);
});
double avg = list.stream() //스트림 가져옴
.mapToInt(Student :: getScore) // 중간처리 : 학생 객체를 점수로 매핑
.average() // 최종 처리 : 평균 구하기
.getAsDouble(); //최종결과 리턴 받기
System.out.println("평균점수 : "+avg);
//위에 코드를 3줄로 줄인 코드
double average = list.stream().mapToInt(Student :: getScore).average().getAsDouble();
System.out.println("평균점수 : "+ average);
}
}
jace 90
peter 93
linda 95
평균점수 : 92.66666666666667
평균점수 : 92.66666666666667
public class Stream10 {
public static void main(String[] args) {
int[] arr = {2,4,6};
boolean result = Arrays.stream(arr).allMatch(a -> a%2 ==0);
System.out.println(result);
Arrays.stream(arr).anyMatch(a -> a%3 ==0); //3의 배수있는지 없는지?
System.out.println("3의 배수가 하나라도 있니?" + result);
result = Arrays.stream(arr).noneMatch(a -> a%3 ==0);/ /3의 배수가 없니?
System.out.println("3의 배수가 없니?"+result);
}
}
true
3의 배수가 하나라도 있니?true
3의 배우가 없니?false