스트림

O0·2022년 6월 22일
0

JAVA8

목록 보기
5/5
post-thumbnail

스트림


목차

1. 스트림 정의
2. 스트림 특징
3. 스트림 만들기
4. 스트림 중간연산
5. 스트림 최종연산
※ 요약 및 코드


  1. 스트림 정의
  • 정의 : 다양한 데이터 소스(컬렉션, 배열 등)를 표준화된 방법으로 다루기 위한 것. 데이터의 연속적인 흐름
  • 스트림 만드는 방법
    1) 스트림 만들기
    2) 중간연산 (n번)
    3) 최종연산(결과) (1번)
  • 스트림을 중랑천이라고 생각하면 쉽다. 데이터소스(물)이 한 방향으로 흘러간다. 그 과정에서 중간과정 최종작업을 한다.
 		String[] container = {"a","b","c","aa","d","a"}; //배열
		Stream<String> stream = Stream.of(container); //1.스트림만들기
		Stream<String> distinctStream = stream.distinct(); //2-1.중간연산(중복제거)
		Stream<String> sortStream = stream.sorted(); //2-2.중간연산(정렬)
		Stream<String> limitStream = stream.limit(5); //2-3. 중간연산(스트림 자르기)
		int total = (int) stream.count(); //3.최종연산
  1. 스트림 특징
  • 스트림은 데이터를 읽기만할 뿐 원본을 변경하지 않는다.
  • 스트림은 Iterator처럼 일회용이다.
  • 지연된연산 : 연산이 필요할 때 중간연산을 작업한다.
 -- 지연된연산 예제(로또 번호 생성)
      IntStream lotoStream = new Random().ints(1,46); // 1 ~ 45 범위의 무한 스트림
      lotoStream.distinct().limit(6).sorted()
      .forEach(j -> System.out.print(j+"  "));
  • 병렬스트림 : 멀티쓰레드로 병렬처리한다.
    • 기본이 sequenctial(), 병렬처리는 parallel()
  		Stream<String> strStream = Stream.of("gon","jae","oh","o","j","g","g");
		int sum = strStream.parallel() //병렬 스트림으로 전환
				.mapToInt(s -> s.length()).sum(); //모든 문자열 길이 합
		System.out.println(sum); //12
  • 기본형 스트림 (꼭 알필요는 없다.)
    • 오토박싱(int(기본형)->Integer(참조형)), 언박싱(Integer->int)의 비효율이 제거된다. [Stream 대신 IntStream 사용]
    • 원래는 int에서 Integer로 변환해서 사용해야 하는데 IntStream을 사용함으로 오토박싱에서 변환될 때 시간 소모가 줄어서 비효율이 제거된다.
  1. 스트림 만들기
1) 컬렉션
 - List<Integer> list = Arrays.asList(1,2,3,4,5);
 - Stream<Integer> intStream = list.stream()

2) 배열
 - Stream<String> strStream = Stream.of("a","b","c"); // 가변인자
 - Stream<String> strStream = Arrays.stream(new String[]{"a","b","c"});

3) 난수 스트림
 - IntStream intStream = new Random().ints(1,46) // 1~45를 랜덤으로 갖는 무한스트림

4) 람다식 활용 스트림
 - Stream<Integer> oneStream = Stream.generate(()->1); // 1 무한스트림
 - Stream<Integer> intStream = Stream.iterate(1, n -> n+2); //홀수 무한스트림
  1. 스트림 중간연산
    1. skip(n) : n번째 인덱스부터 시작, limit(n) : n개만 뽑기
    		IntStream intstream = IntStream.rangeClosed(1,10); //1~10 포함
    		intstream.skip(5).limit(3).forEach(System.out::println);
    			//5개 건너뛰고 6부터 시작 6,7,8
    1. filter(조건식) : 해당 조건에 맞춰 필터링, distinct() : 중복제거
    		IntStream intStream = IntStream.of(1,2,3,4,5,2,3,4,6);
    		intStream.distinct().forEach(System.out::println);
    			// 1~6까지 출력
    		IntStream intStream = IntStream.of(1,2,3,4,5,2,3,4,6);
    		intStream.filter(n -> n%2==0 && n%3==0).forEach(System.out::println); // 6출력
    1. sorted() : 정렬대상 및 기준에 맞춰 정렬

      - 정렬기준이 여러개이면 sorted() 다음으로 thenComparing()을 사용
                                          
  • 4-1. map() : 스트림 요소 변환 (요소 변경이란? 대문자 -> 소문자, 문자열 자르기 등)
  • 4-2. peek() : 스트림의 요소를 소비하지 않고 엿보기 (중간 작업결과 확인 = 디버깅용)
    • Stream< File > --(map(File::getName)) File에서 String으로 변환 --> Stream< String >
		Stream<File> fileStream = Stream.of(new File("ja.java"),new File("jaclass"),new File("ja.png"), new File("ah.txt"), new File("goods.html"));
		//파일명을 대문자로 뽑아내기
		fileStream.map(File::getName)					//파일 스트림을 String 스트림으로 변환
				  .filter(s -> s.indexOf('.') != -1)	//확장자 없는 애들 제거
				  .peek(s -> System.out.printf("filename=%s \n", s)) // 디버깅(진행이 잘 되고 있는지 확인)
				  .map(s -> s.substring(0,s.indexOf('.'))) // 확장자 앞 '.' 앞 파일 이름 으로 요소변환
				  .map(String::toUpperCase) // 메서드참조 -> 람다식으로 변경하면 (s -> s(변수참조).toUpperCase) //파일이름 대문자로 요소 변환
				  .distinct() //중복제거
				  .forEach(System.out::println); //출력
    1. flatMap() : 스트림의 스트림을 스트림으로 변환
		Stream<String[]> strArr = Stream.of(
					new String[] {"seoul","sung","su"},
					new String[] {"seoul","gang","nam"}
				);
		
//		Stream<Stream<String>> strStr = strArr.map((s) -> Arrays.stream(s));
//		strStr.distinct()
//		.forEach(System.out::println); //stream으로 출력이 된다.
		
		Stream<String> strflat = strArr.flatMap(Arrays::stream);
		strflat.map(String::toLowerCase)
				.distinct()
				.sorted(Comparator.reverseOrder())
				.forEach(System.out::println);  
  1. 스트림 최종연산
    : 스트림의 요소를 소모해서 스트림이 닫힌다.(int, boolean, Optional 등을 반환.)
  1. forEach() : 스트림의 모든 요소에 지정된 작업을 수행.

  2. 조건검사
    • allMatch : 모든 요소가 조건을 만족하면 true
    • anyMatch : 한 요소라도 조건을 만족시키면 true
    • noneMatch : 모든 요소가 조건을 만족시키지 않으면 true

  3. reduce() : 스트림의 요소를 하나씩 줄여가며 누적연산 수행 (가장 중요*** -> 최종연산이 모두 reduce로 만들었기 때문이다.)
    • identity : 초기값
    • accumulator : 작업 방식
int sum = intStream.reduce(0, (a,b) -> a+b);
// 아래와 같은 코드.
int a  = iden tity;
for(int b : stream) a = a+b


요약

  • 중간연산 요약
  • 최종연산 요약


맛집 순위 정하기 예제

package Stream;

import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;

public class StreamMake {
	public static void main(String[] args) {
		Stream<Restaurant> resStream = Stream.of(
					new Restaurant(10,5,"a"),
					new Restaurant(8,4,"b"),
					new Restaurant(5,3,"c"),
					new Restaurant(7,5,"d"),
					new Restaurant(5,5,"e"),
					new Restaurant(3,1,"f"),
					new Restaurant(10,2,"g")					
				);
		
		Stream<Restaurant> resStream1 = Stream.of(
				new Restaurant(10,5,"a"),
				new Restaurant(8,4,"b"),
				new Restaurant(5,3,"c"),
				new Restaurant(7,5,"d"),
				new Restaurant(5,5,"e"),
				new Restaurant(3,1,"f"),
				new Restaurant(15,2,"g")					
			);
		
		Stream<Restaurant> resStream2 = Stream.of(
				new Restaurant(10,5,"a"),
				new Restaurant(8,4,"b"),
				new Restaurant(5,3,"c"),
				new Restaurant(7,5,"d"),
				new Restaurant(5,5,"e"),
				new Restaurant(3,1,"f"),
				new Restaurant(15,2,"g")					
			);
		
		System.out.print("모든 맛집의 이름 : ");
		resStream.sorted(Comparator.comparing(Restaurant::getAttitude).reversed() //1.직원 태도 점수 역순으로 정렬(Comparator.naturalOrder()) 
					.thenComparing(Comparator.naturalOrder()))// 2. 클래스에서 설정한 compareTo 내림차순으로 정렬
					.forEach(n -> System.out.print(n.getName()+" , "));
		
		System.out.println();
		Stream<Integer> intStream = resStream1.map(Restaurant::getAttitude);
		int attitudeSum = intStream.reduce(0, (a,b) -> (a+b));
		System.out.println("모든 맛집의 태도 점수의 합 : " + attitudeSum);
		
		int attitudeMax = resStream2.map(Restaurant::getAttitude).reduce(Integer::max).orElse(0);
		System.out.println("모든 맛집의 태도 최고점수 : " + attitudeMax);
	}
}

class Restaurant implements Comparable<Restaurant>{
	private int attitude;
	private int star;
	private String name;

	public Restaurant(int attitude, int star, String name) {
		super();
		this.attitude = attitude;
		this.star = star;
		this.name = name;
	}

	public int getAttitude() {
		return attitude;
	}

	public void setAttitude(int attitude) {
		this.attitude = attitude;
	}

	public int getStar() {
		return star;
	}

	public void setStar(int star) {
		this.star = star;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	//별점 내림차순으로 정렬
	@Override
	public int compareTo(Restaurant o) {
		if(this.getStar() < o.getStar()) {
			return 1;
		}
		return -1;
	}
}


출처


  • 유튜버 : 남궁성의 정석코딩
profile
O0

0개의 댓글