Language/JAVA

[JAVA] 자바 스트림 API

gangintheremark 2023. 9. 8. 12:06
728x90

자바 스트림 API

  • 표준 API 함수적 인터페이스 사용
  • 자바 스트림 API를 이용하면 컬렉션 List Set Map에 저장된 데이터 연산이 가능

 

자바 스트림 API 이용

1. 컬렉션 또는 배열에서 스트림 생성

Stream.of(names);
Arrays.stream(names);

2. 중간처리

  • 정렬, 중복제거, 필터링, skip, limit, 가공처리 map flatMap

3. 최종처리

  • 반복처리 forEach , 합계, 평균, 최대, 최소, 갯수, 그룹핑, 타입변환 collect

 

컬렉션 또는 배열에서 스트림 생성

컬렉션에서 생성

List<String> list = Arrays.asList("옥지", "빵빵이", "제니");

// 람다식
list.stream().forEach(t->System.out.println(t));
// Method reference
list.stream().forEach(System.out::println);

배열에서 생성

String names = { "옥지", "빵빵이", "제니" };
Stream<String> x = Stream.of(names);

또는

Stream<String> x2 = Arrays.stream(names);

 

중간처리

distinct

  • 중복제거
list.stream().distinct().forEach(System.out::println);

 

filter

  • filter(Predicate)
  • predicate 인터페이스 이용 ➜ 파라미터/리턴값 있고, 리턴값은 무조건 boolean
// "김"으로 시작하는 요소만 출력
list.stream().filter(t->t.startWith("김")).forEach(System.out::println);

 

map

  • map(Funtion) , mapToInt(ToIntFunction), mapToDouble(ToDoubleFunction)
  • function 인터페이스 이용 ➜ 파라미터/리턴값 있고
  • 요소를 가공하는 역할
// username(이름)과 score(성적)을 멤버변수로 갖는 Student 클래스가 있다고 가정

// 💡 이름에서 성만 출력
list.stream().map(t->t.username.substring(0,1)).forEach(System.out::println);

// 💡 성적만 출력
list.stream().map(t->t.getScore()).forEach(System.out::println);
list.stream().map(Student::getScore()).forEach(System.out::println);

// 💡 성적만 출력 (정수로 반환)
list.stream().mapToInt(Student::getScore()).forEach(System.out::println);

 

flatMap

  • flatMap(Function<T, Stream>)
  • 요소를 가공하여 복수 개의 요소들로 구성된 새로운 스트림을 반환
// 💡 공백문자 기준으로 분리
List<String> list = Arrays.asList("hello world", "happy life");
list.stream().flatMap(t->Arrays.stream(t.split(" "))).forEach(System.out::println);

// 💡 쉼표 기준으로 분리 + 정수값으로 출력
List<String> list = Arrays.asList("10,20,30", "50,60,70");
list.stream().flatMapToInt(t->Arrays.stream(t.split(",")).mapToInt(Integer::parseInt).toArray())).forEach(System.out::println);

 

sorted, skip, limit

  • 정렬
// username(이름)과 height(키)를 멤버변수로 갖는 Person 클래스가 있다고 가정

List<Person> list = Arrays.asList(new Person("옥지", 180), 
                                   new Person("빵빵이", 160), 
                                  new Person("제니", 140));

// 💡 오름차순 정렬 - Comparator 클래스의 comparing
list.stream().sorted(Comparator.comparing(Person::getHeight)).forEach(System.out::println);

// 💡 내림차순 정렬 - Comparator 클래스의 reverseOrder
list.stream().sorted(Comparator.comparing(Person::getHeight, Comparator.reverseOrder())).forEach(System.out::println);

// 💡 skip(n) : n개 skip
list.stream().sorted(Comparator.comparing(Person::getHeight)).skip(2).forEach(System.out::println);

// 💡 limit(n) : n개만 얻기
list.stream().sorted(Comparator.comparing(Person::getHeight)).limit(3).forEach(System.out::println);

 

boxed

  • 기본형을 참조형으로 변환
int[] arr = { 10, 20, 30, 40, 50 };

// 💡 boxed : int ➜ Integer
IntStream s = Arrays.stream(arr);
s.boxed().forEach(System.out::println); 

// 💡 asDoubleStream : int ➜ double
Arrays.stream(arr).asDoubleStream().forEach(System.out::println);

 

최종처리

allMatch, anyMatch, noneMatch

  • allMatch(Predicate) : 모든 요소들이 Predicate 조건에 일치하는지 체크
  • anyMatch(Predicate) : 일부 요소들이 Predicate 조건에 일치하는지 체크
  • noneMatch(Predicate) : 모든 요소들이 Predicate 조건에 일치하지 않는지 체크
int[] arr = { 1, 2, 3, 4, 5 };

// 💡 모든 요소가 10보다 작은가? - allMatch
boolean result = Arrays.stream(arr).allMatch(t -> t < 10);

// 💡 요소 중에 3의 배수가 있나? - anyMatch
boolean result = Arrays.stream(arr).anyMatch(t -> t % 3 == 0);

// 💡 모든 요소가 3의 배수가 없나? - noneMatch
boolean result = Arrays.stream(arr).noneMatch(t -> t % 3 == 0);

 

통계처리 - sum, average, max, min, count

  • InputStream DoubleStream LongStream 의 집계메서드
int[] arr = { 1, 2, 3, 4, 5 };

// 💡 합계
int sum = Arrays.stream(arr).sum();

// 짝수의 합 
int sum = Arrays.stream(arr).filter(n -> n % 2 == 0).sum();

// 💡 평균
double avg = Arrays.stream(arr).average().orElse(0.0);

// 💡 최대
int max = Arrays.stream(arr).max().orElse(0);

// 💡 최소
int min = Arrays.stream(arr).min().orElse(0);

// 💡 갯수
long count = Arrays.stream(arr).count();

 

collect

  • Collectors 클래스 사용
// username(이름), grade(등급), isMale(남자인지), age(나이)를 멤버변수로 갖는 Stu 클래스가 있다고 가정
// 5명의 정보를 Stu[] stuArr 에 저장했다고 가정

// 💡 이름만 출력
Arrays.stream().map(Stu::getUsername).forEach(System.out::println);

// 💡 List에 이름저장 - toList
List<String> names = Stream.of(stuArr).map(Stu::getUsername).collect(Collectors.toList());

// 💡 Map 에 이름저장 - toMap
Map<String, Stu> m = Stream.of(stuArr).collect(Collectors.toMap(t -> t.getUsername(), t -> t));

// 💡 개수 - counting
long count = Stream.of(stuArr).collect(Collectors.counting());

// 💡 age 합 - summingInt
int sum = Stream.of(stuArr).collect(Collectors.summingInt(Stu::getAge));

// 💡 age 최대 값 - maxBy
Optional<Stu> max = Stream.of(stuArr).collect(Collectors.maxBy(Comparator.comparing(Stu::getAge)));

// 💡 age 최대 값 - minBy
Stu min = Stream.of(stuArr).collect(Collectors.minBy(Comparator.comparing(Stu::getAge))).orElse(null);

// 💡 성별 분류 - partitioningBy(Predicate) : true/false로 나눠 반환
Map<Boolean, List<Stu>> xxx = Stream.of(stuArr).collect(Collectors.partitioningBy(Stu::isMale));
List<Stu> male = xxx.get(true);
List<Stu> female = xxx.get(false);

// 💡 등급 분류 - groupingBy(Function) : 리턴값으로 나눠 반환
Map<Integer, List<Stu>> yyy = Stream.of(stuArr).collect(Collectors.groupingBy(Stu::getGrade));

// 💡 그룹핑 갯수 구하기
Map<Integer, Long> yyy2 = Stream.of(stuArr).collect(Collectors.groupingBy(Stu::getGrade, Collectors.counting()));
💡 OptionalInt, OptionalDouble, OptionalLong
- 컬렉션에 값이 없을 경우 집계 메서드를 사용하면 OptionalXXX.empty 예외가 발생한다
- orElse() 를 통해 예외 발생 시 기본값으로 처리 가능
728x90