스트림

Seung jun Cha·2022년 10월 17일
0

1. 스트림

  • 스트림은 데이터의 흐름으로 배열 또는 컬렉션에 함수 여러 개를 조합해서 원하는 결과를 필터링하고 가공된 결과를 얻을 수 있다.
  1. 저장원소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 내부 반복자
  2. 컬렉션 내부에서 요소를 반복시키고 개발자는 요소당 처리할 코드만 제공되는 코드 패턴
  3. 이미 함수가 구현되어 있어 어떻게 요소를 반복시킬 것 인가는 컬렉션에 맡겨두고 개발자는 요소처리 코드만 집중적으로 구현 가능

1-1 스트림 생성

1-1-1 배열 스트림

String[] arr = new String[]{"a", "b", "c"};
Stream<String> stream = Arrays.stream(arr);

Stream<String> stream = Stream.of("a", "b", "c"); 
IntStream stream = IntStream.of(1, 2, 3);
// 가변 인자를 넣어서 바로 생성할 수도 있음	

1-1-2 컬렉션 스트림

List이름.stream
// 스트림을 이용해서 짝수만 출력
integerList.stream()
        .mapToInt(i -> i)
        .filter(i -> i % 2 == 0)
        .forEach(i -> System.out.print(i + ", "));
        
        
// 스트림을 이용해서 문자열 합치기
List<String> stringList = List.of("a", "b", "c", "d", "e");
String concat3 = stringList.stream().collect(Collectors.joining());
System.out.println("concat3 = " + concat3);

// 스트림을 이용해서 학생 성적 평균
double average3 = studentList.stream()
        .mapToInt(s -> s.getScore())
        .average()
        .getAsDouble();
        
// group by를 이용한 그룹화
public class Person {

    private String Country; // 나라
    private String City; // 도시 
    private String name; // 이름

}
나라별로 그룹화하면 이렇게 나온다
people.stream().collect(Collectors.groupingBy(Person::getCountry));
반횐타입은 Map으로 반환된다.

1-2 파이프라인

  • 각종 메서드로 중간스트림을 생성하는데 이 때, 결과로 이전의 중간 스트림을 리턴한다. 그리고 이 스트림을 다음 중간 메서드로 이어서 처리한다. 하지만 중간 스트림들이 바로 중간처리를 하는 것이 아니라 최종처리가 될 때까지 처리가 지연된다. 그림으로 보자

1-3 중간처리 메서드

menu.stream()
	.filter(d -> d.getCalories() < 400)
    .sorted(comparing(Dish::getCalories))  // 오름차순으로 정렬
    .map(Dish::getName)
    .collect(toList));
List<String> names = Arrays.asList("이산", "진영", "이산", "이산", "별찬");
    names.stream()
        .distinct() // 중복 제거
        .filter(name -> name.equals("이산"))
        // 이산이라는 이름을 가진 이름만 리스트에 남겨 둠.
        .forEach(System.out::println);
  1. 매핑 : 스트림의 요소를 다른 요소로 대체하는 작업
    (1) flatMapXXX() : Array나 Object로 감싸져 있는 모든 원소를 그냥 문자 등이 아닌 스트림 형태로 반환
public static void main(String[] args) {
    List<String> inputList = Arrays.asList("Hello", "world");
    long res = inputList.stream()
        .flatMap(data -> Arrays.stream(data.split("")))
        .count();
    System.out.println(res);
  }

(2) mapXXX() :
(3)boxed() : int, long, double 요소를 Integer, Long, Double 요소로 박싱해서 Stream을 생성

1-4 최종처리 메서드

1-5 스트림 슬라이싱

  • 스트림의 요소를 선택하거나 스킵하는 방법을 말한다. 자바 9버전부터 지원한다
  1. takewhile , dropwhile
칼로리가 320이하인 요리를 선택해라.
List<Dish> menu = Arrays.asList(
	new Dish(100),
    new Dish(200),
    new Dish(350),
    new Dish(400),
    new Dish(420);
    
 이렇게 필터를 사용하면 리스트의 모든 요소를 탐색하게 된다. 하지만 주어진 리스트는 
 칼로리 순으로 모두 정렬되어있다.
 menu.stream()
 	 .filter(dish -> dish.getCalories() < 320)
     .collect(toList));
     
takewhile을 사용하면 320칼로리보다 큰 음식을 만나는순간 뒤의 요소들은 탐색하지않는다
리스트가 큰 경우 유의미한 속도차이를 만들 수 있다.
 menu.stream()
 	 .takewhile(dish -> dish.getCalories() < 320)
     .collect(toList));
  1. limit(n) : 정해진 숫자만큼 요소를 반환한다.
  2. skip(n) : 처음 n개 요소를 제외하고 나머지를 반환한다.

1-6 검색과 매칭

  1. anyMatch : 주어진 값에서 적어도 한 요소는 일치하는지 확인
  2. allMatch : 모든 요소가 일치하는지 검사
  3. noneMatch : 일치하는 요소가 하나도 없는지 검사
  4. findAny : 현재 스트림에서 임의의 요소를 반환한다.
  5. findFirst : 현재 스트림에서 첫번째 요소를 반환한다. 병렬실행에서는 첫번째 요소를 찾기 어려으므로 요소의 반환순서가 상관없다면 findAny를 사용한다.
1. if(menu.stream().anyMatch(Dish:getVegitarian))
2. if(menu.stream().allMatch(dish -> dish.getCalories() <1000))
4. menu.stream().filter(Dish:getVegitarian).findAny();

1-7 리듀싱

  • 모든 스트림 요소를 처리해서 값을 도출하는 연산이다. 스트림 요소의 총합, 최대값 또는 최소값을 구하는데에 사용할 수 있다.
numberList.stream().reduce(0, (a+b) -> a+b)
초기값은 0으로 두고 스트림의 모든 요소를 더한다.

numberList.stream().reduce((a+b) -> a+b))
초기값을 설정하지 않으면 Optional을 반환한다.

transactions.stream().reduce(Integer::max);
transactions.stream().max(comparing(Transactions::getValue))
최댓값을 찾는다 (두번째 방법이 더 쉽고 간단하다)

1-8 숫자형 스트림

  • 리듀스는 박싱비용이 들어간다. 숫자와 관련된 연산을 해야하는 경우 리듀스보다는 특화 스트림을 사용하는 것이 훨씬 좋다.
  • mapToInt, mapToDouble, mapToLong을 사용하면 바로 sum(), min(), average() 등 숫자와 관련된 메서드를 바로 사용할 수 있다.
menu.stream()
 	 .mapToInt(Dish::getCalories)
     .sum();
     
   mapToInt 등 특화스트림은 map과 완전 동일하지만 Stream<T> 대신 
   IntStream을 반환한다는 차이가 있다
  • OptionalInt : 특화스트림에서의 Optional이다
  • range, rangeClosed : IntStream, LongStream에서 제공하는 메서드이다. range는 시작과 종료값이 포함되지않고, rangeClosed는 포함된다
IntStream.rangeClosed(1,100)
		 .filter(n -> n % 2 == 0);

https://futurecreator.github.io/2018/08/26/java-8-streams/
https://steady-coding.tistory.com/m/313

0개의 댓글