Stream : 데이터 가공
*모든 예문에는 lombok이 사용되었습니다
Stream
- 스트림은 컬렉션의 저장요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자
- 중간처리 메서드 : Stream을 리턴
- 최종처리 메서드 : int형, String형 ......
- 중간처리 메서드가 Stream을 리턴하기 때문에 메서드 체이닝을 통해 데이터 가공이 가능하다.
- 메서드 체이닝한 모습을 스트림의 파이프라인이라고 표현한다.
- 합계,평균값,카운팅,최대값,최소값 등의 최종처리를 파이프라인으로 해결
Stream 생성하기
- 컬렉션으로 부터 스트림 얻기
import java.util.stream.*;
import java.util.*;
import lombok.*;
class Main{
public static void main(String args[]){
List<Person> list1=Arrays.asList(
new Person("홍길동",25),
new Person("김길동",28),
new Person("박길동",23)
);
List<Person> list2=new ArrayList<>();
list2.add(new Person("송길동",21));
list2.add(new Person("이길동",29));
Stream<Person> s1=list1.stream(); //리스트를 Person형인 Stream으로 변경
Stream<Person> s2=list2.stream(); //리스트를 Person형인 Stream으로 변경
s1.forEach( System.out::println ); //Stream의 최종 처리 메서드인 forEach를
s2.forEach( System.out::println ); //사용해서 list의 데이터들을 출력
}
}
@Data
@AllArgsConstructor
class Person{
String name;
int age;
}
- 컬렉션.Stream() 으로 Stream을 생성한다.
- 배열로부터 스트림 얻기
import java.util.stream.*;
import java.util.*;
import lombok.*;
class Main{
public static void main(String args[]){
int[] a1={1,2,3};
String[] a2={"aa","bb","cc"};
Person[] a3={
new Person("홍길동",25),
new Person("김길동",28),
new Person("박길동",23)
};
IntStream s1=Arrays.stream(a1); // 자료형이 Int인 배열의 Stream객체를 생성
Stream<String> s2=Arrays.stream(a2); // 자료형이 String인 배열의 Stream객체를 생성
Stream<Person> s3=Arrays.stream(a3); // 자료형이 Person인 배열의 Stream객체를 생성
s1.forEach( System.out::println ); //Stream의 최종 처리 메서드인 forEach를
s2.forEach( System.out::println ); //사용해서 배열의 데이터들을 출력
s3.forEach( System.out::println );
}
}
@Data
@AllArgsConstructor
class Person{
String name;
int age;
}
- Arrays.stream(배열) 으로 Stream을 생성한다.
- Int[]형인 배열은 IntStream으로 생성한다.
- 숫자 범위로부터 스트림 얻기
import java.util.stream.*;
class Main{
public static void main(String args[]){
System.out.println(
IntStream.rangeClosed(1,10).sum() //55
);
}
}
- IntStream을 생성
- 메서드 체이닝을 통해 중간처리 메서드인 rangeClosed(start int, end int)과
- 최종 처리메서드인 sum()을 통해서 1부터 10까지의 합을 출력한다.
필터링 : 조건을 통해서 원하는 자료로 정제
Stream filter(Predicate<? super T> predicate)
: 조건필터링
Stream distinct()
: 중복제거
import java.util.*;
import lombok.*;
class Main{
public static void main(String args[]){
List<Person> list=Arrays.asList(
new Person("홍길동",20,"F"),
new Person("홍길동",20,"F"),
new Person("홍길동",20,"M"),
new Person("김길동",35,"M"),
new Person("이길동",40,"F"),
new Person("김길동",40,"F"),
new Person("박길동",50,"M")
);
list.stream()
.distinct()
.filter( p->p.getGender()=="F" )
.forEach( System.out::println );
}
}
@AllArgsConstructor
@Data
class Person{
private String name;
private int age;
private String gender;
- distinct() : 중간처리 메서드, 중복되는 자료(new Person("홍길동",20,"F"))를 제거
- filter()
- 중간처리 메서드
- 조건을 필터링 해주는 메서드
- 매개변수 Predicate : true 또는 false를 리턴하는 boolean 형이 들어가야 한다.
매핑 : 스트림의 요소를 다른 요소로 대체하는 작업
Stream map(Function<? super T,? extends R> mapper)
: T에서 R로 변경
- map() 메서드
import java.util.stream.*;
class Main{
public static void main(String args[]){
Stream<String> names=Stream.of("fsaf","fdsafsa","dsa");
names.map( str-> str.length() )
.forEach( size->System.out.println("문자열의길이:"+size) );
}
}
import java.util.stream.*;
class Main{ //람다식을 메서드 참조형으로 바꾼형태
public static void main(String args[]){
Stream<String> names=Stream.of("fsaf","fdsafsa","dsa");
names.map( String::length )
.forEach( size->System.out.println("문자열의길이:"+size) );
}
}
- Stream.of(생성하려는 객체) : of에 매개변수로 객채를 입력하면 스트림객체로 생성해줌
- String형인 Stream요소를 map을 이용해서 Stream의 요소를 str.length()로 바꿈
- .map( str-> str.length() )
- .map( String::length )
IntStream mapToInt(ToIntFunction<? super T> mapper)
: T를 int형으로 변경
- mapToInt() 메서드
import java.util.function.*;
import java.util.*;
import lombok.*;
class Main{
public static void main(String args[]){
List<Student> list=Arrays.asList(
new Student("홍길동",50),
new Student("김길동",90),
new Student("박길동",100),
new Student("송길동",70)
);
System.out.println(
list.stream()
.mapToInt( Student::getScore )
.sum()
);
}
}
@AllArgsConstructor
@Getter
class Student{
String name;
int score;
}
- mapToInt형을 이용해서 list의 요소인 Student들을 int 형인 Student.getscore로 변경
- mapToInt( stu -> stu.getScore )
- mapToInt( Student::getScore )
Stream flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
: Stream의 요소가 복수의 배열일 경우 배열의 요소를 다 가지는 새로운 Stream객체를 생성한다.
flatMap() 메서드
import java.util.*;
import java.util.stream.*;
class A{
public static void main(String args[]){
String[] a={"aa","bb","cc"};
String[] b={"dd","ee"};
Stream<String[]> s1=Stream.of(a,b);
s1.forEach(System.out::println);
Stream<String> s2=Stream.of(a,b).flatMap(Arrays::stream);
s2.forEach(System.out::println);
}
}
- String[] a와 String[] b가 Stream의 요소
- flatMap 매서드를 이용해서 a와 b의 요소를 가지는 새로운 Stream을 생성해서 forEach메서드로 요소를 출력
정렬 : Stream의 요소들을 정렬
Stream sorted()
sorted() 메서드
import java.util.stream.*;
class Main{
public static void main(String args[]){
Stream<String> names=Stream.of("홍길동","김길동","박길동","송길동","이길동");
names.sorted()
.forEach( System.out::println );
}
}
sorted()
메서드를 이용해서 “x길동” 의 이름을 글자순으로 정렬 할 수있다.
Stream sorted(Comparator<? super T> comparator)
: sorted메서드에 매개변수로 Comparator를 넘길수 있다.
- sorted메서드에 매개변수로 Comparator를 넘길수 있다.
import java.util.Comparator;
import java.util.stream.*;
class Main {
public static void main(String args[]) {
Stream<String> names = Stream.of("홍길동", "김길동", "박길동", "송길동", "이길동");
names.sorted(new Descending()) //Sorted(Comparator)
.forEach(System.out::println);
}
}
class Descending implements Comparator<String> {
public int compare(String o1, String o2) {
return o2.codePointAt(0) - o1.codePointAt(0);
}
}
- 비교하는 연산자인 Comparator의 compare메서드를 오버라이딩
- compare메서드는 원래 o1 - o2 = 음수 또는 양수 를 이용해서 정렬 → 오름차순 정렬
- o2 - o1 으로 변경 및 codePointAt 메서드로 한글의 내림차순으로 compare메서드를 오버라이딩
반응형