Java 스트림 Stream

별의개발자커비·2023년 3월 11일
0

Java

목록 보기
60/66
post-thumbnail

스트림 Stream이란?

  • 컬렉션이 for, foreach 등을 이용한 외부 반복을 해야한다면
  • 스트림은 내부 반복 할 수 있음

구현

  • 컬렉션객체. stream
  • 배열 -> Stream의 경우
String [] strs = {"aa", "bb", "cc", "dd", "bb" };
Stream<String> ss = Arrays.stream(strs);
  • 배열 -> Intstream의 경우 ( 2가지 방법 )
IntStream is = Arrays.stream(array_int);

IntStream is2 = IntStream.of(array_int);

스트림 파이프라인

: 메소드 체이닝 같은 거
: 이렇게 점으로 계속 기능 추가하는 것

lists.stream().filter(x -> x>=10).sorted().forEach(x -> System.out.print(x+" "));

종류

  • Stream
  • IntStream
  • ...

Stream 기능들

  • filter()
  • sorted()
  • distinct(): 중복제거
  • count() : 갯수세주기
  • iterate(0, x -> x+1): 0부터 뒤에 기능을 반복적으로 수행함 (그래서 .limit(숫자)가 뒤에 붙어야 무한 안 됨)
  • forEachOrdered: foreach의 정렬 버전

IntStream 기능들

  • map()
  • average()
  • getAsDouble()
  • rangeClosed(): 범위 한정해주기

느긋한 연산 vs 조급한 연산


import java.util.Random;
import java.util.stream.IntStream;

public class Laziness1Demo_4 {

	public static void main(String[] args) {
		
		// 1~5 범위의 intstream is 만들
		IntStream is = IntStream.rangeClosed(1, 5) ;
		
		// is에 아닌애들은 그냥 filter: 수, 프린트하고
		// 2의 배수인 애들은 다음단계도: 프린트 + map: 
		// 마지막으로 foreaxh: 수x수 한 거 프린트하기
		is.filter(x -> {
			System.out.println("filter:"+ x);
			return x % 2==0;
		}).map ( x -> {
			System.out.println("map:"+x);
			return x*x;
		}).forEach(x -> System.out.println("foreach="+ x)); ;
		
	}

}

기본형

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;

public class StreamDemo {

	public static void main(String[] args) {
		// 정수형 리스트 객체를 생성
		Random r = new Random();
		
		// 해당 리스트에 랜덤한 정수형 값을 저장 10개: r.nextInt(30)
		List<Integer> lists = new ArrayList<Integer>();
		for (int i = 0; i < 10; i++) {
			lists.add(r.nextInt(30));
		}
				
		// 1. Collection 방식
		// 정수형 리스트 객체를 생성
		List<Integer> lists2 = new ArrayList<Integer>();
		// 위에서 저장한 리스트 중에서 값이 10 이상인 데이터만 새로운 리스트에 저장
		for (Integer data : lists) {
			if ( data > 10)
				lists2.add(data);
		}
		// 정렬
		Collections.sort(lists2);
		// 출력
		System.out.println(lists2);

		
		// 2. Streaming 방식: 위를 한 줄로 줄인 
		lists.stream().filter(x -> x>=10).sorted().forEach(x -> System.out.print(x+" "));
		
	}

}

// 정렬할 때 lists2.sort 가 아니라 collections.sort를 썼네?

예제

예제 1

package day7;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.OptionalDouble;
import java.util.Random;
import java.util.function.IntUnaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Array2StreamDemo_3 {

	public static void main(String[] args) {
		int [] array_int = {1,5,4,8,4,1,4,};
		// 2가지 방법으로 array -> Intstream
		IntStream is = Arrays.stream(array_int);
		IntStream is2 = IntStream.of(array_int);
		
		System.out.println(is.average());
		System.out.println(is2.average().getAsDouble());
		
		String [] strs = {"aa", "bb", "cc", "dd", "bb" };
		// array -> stream 하고
		Stream<String> ss = Arrays.stream(strs);
		// 중복 제거, 갯수 세기
//		ss.distinct();
//		ss = Arrays.stream(strs);
//		System.out.println(ss.count());
		
		// 1부터 2씩 커지는, 요소 4개짜리 intstream 만들
		IntStream is1 = IntStream.iterate(1, x -> x+2).limit(4);
		is1.forEach(x -> System.out.print(x+" "));
		System.out.println();
		
		// 0~10 숫자 랜덤으로 5개 담는 intstream만들고 정렬하기
		IntStream is3 = new Random().ints(0, 10).limit(5);
		is3.forEachOrdered(x -> System.out.print(x +" "));
		
		
		
	}

}
// IntStream 만드
// is/ is2 2가지 방법이 있다.

// intstream의 기능 사용해보기
// average
// getAsDouble
// forEachOrdered: foreach의 정렬 버

// stream의 기능 사용해보기
// distinct: 중복제거
// count : 갯수세주기


// string으로 된 strs 배열은  intstream 같은 애가 없으니
// 그냥 객체stream 으로 바꿔서 써야한다.
// stream은 한 번 쓰면 닫히니까 위에 막아줘야함

// is1, 3 : 무한히 반복하는 애가 되버렸음
// .limit(5): 해결!

예제 2: stream, Intstream

- Integer::compare

- reduce();

- mapToInt

- intValue

import java.util.Comparator;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.function.ToIntFunction;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Demo2_6 {

	public static void main(String[] args) {
		Stream<String> ss ; 
		List<String> names = List.of("홍길동", "배장화", "임꺽정", "연흥부", "김선달", "황진이");
		List<Integer> ages = List.of(25, 20, 29, 28, 32, 18);
		List<Gender> genders 
		= List.of(Gender.MALE, Gender.FEMALE, Gender.MALE, Gender.MALE, Gender.MALE, Gender.FEMALE);
		
		Stream<Integer> as = ages.stream();
		System.out.println(as.reduce(0, (a,b) -> a+b ));
		
		as = ages.stream();
//		System.out.println( as.max( (a,b) -> a-b ) );
		System.out.println( as.max( Integer::compare ).get() );
		
		as = ages.stream();
		System.out.println( as.min(Integer::compare).get());
		
		IntStream is = ages.stream().mapToInt(x -> x.intValue()) ;
		System.out.println(is.average().getAsDouble()); 
		
	}

}

enum Gender {
	MALE, FEMALE
}

// 매번 여는게 귀찮으면 ages.stream() 이렇게 앞에 붙이기
// intstream으로 바꿀 땐 mapToInt
// 근데 mapToInt로 intstream으로 바꾸면 안에 들어있는 건 interger
// 그래서 x.intvalue로 int로 바꿔주는 

//이상하게 출력되면 stream의 경우 .get로 출력해보

예제 3

import java.util.Comparator;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Demo3_7 {
	static int i = 0;
	public static void main(String[] args) {
		Stream<String> ss;
		
		List<String> names = List.of("홍길동", "배장화", "임꺽정", "연흥부", "김선달", "황진이");
		List<Integer> ages = List.of(25, 20, 29, 28, 32, 18);
		List<Gender> genders 
		= List.of(Gender.MALE, Gender.FEMALE, Gender.MALE, Gender.MALE, Gender.MALE, Gender.FEMALE);
		
		// 스트림 안에  멤버들을 차례대로 출력
		Stream<Member> sm = names.stream().map(x -> new Member(x, genders.get(i) , ages.get(i++) )  );
		sm.forEach(x -> System.out.println(x));
		System.out.println("-".repeat(40));

		// 남자인 멤버만 출력
		i= 0;
		sm = names.stream().map(x -> new Member(x, genders.get(i) , ages.get(i++) )  );
		sm.filter( x -> x.gender == Gender.MALE ).forEach(x -> System.out.println(x));
		System.out.println("-".repeat(40));

		
		// 나이가 평균보다 높은 사람들
		i= 0;
		sm = names.stream().map(x -> new Member(x, genders.get(i) , ages.get(i++) )  );
		double avg = ages.stream().mapToInt(x -> x.intValue()).average().getAsDouble();
		sm.filter(x ->   x.ages > avg ).forEach(x -> System.out.println(x) );
		

		
	}

}

 class Member{
	 // 생성자 통해 초기화/ getter /to string override
	 String names;
	 Gender gender;
	 int ages ; 
	public Member(String names, Gender gender , int ages) {
		super();
		this.names = names;
		this.ages = ages;
		this.gender = gender;
	}
	public String getNames() {
		return names;
	}
	public int getAges() {
		return ages;
	}
	public Gender getGender() {
		return gender;
	}
	@Override
	public String toString() {
		return "Member [names=" + names + ", gender=" + gender + ", ages=" + ages + "]";
	}
 }

예제 4

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/* 
 * 스트림... 컬렉션과 비슷한 기능을 제공...
 * 람다를 이용해서 커스텀화... 버퍼링처럼 자료를 저장하지 않고
 * 
 * 랜덤하게 1~100 의 숫자 중에서 20개를 선택하고
 * 짝수만
 * 홀수만
 * 3의 배수만
 */

public class Demo4_8 {

	public static void main(String[] args) {
		// 중복 제거 x 버전
		Random r = new Random();
		List<Integer> lists = new ArrayList<Integer>();
		for (int i = 0; i < 20; i++) {
			lists.add(r.nextInt(100)+1);			
		}
		System.out.println(lists);

		
		Stream<Integer> sm = lists.stream();
		sm.filter(x -> x%2 == 0).sorted().forEach(x -> System.out.print(x + " "));
		System.out.println();
		
		sm = lists.stream();
		sm.filter(x -> x%2 != 0).sorted().forEach(x -> System.out.print(x + " "));
		System.out.println();
		
		sm = lists.stream();
		sm.filter(x -> x%3 == 0).sorted().forEach(x -> System.out.print(x + " "));
		System.out.println();
		System.out.print("-".repeat(50));
		System.out.println();


		
		// 중복 제거 o 버전
		List<Integer> lists2 = new ArrayList<Integer>();
		for (int i = 0; i < 100; i++) {
			lists2.add(i +1);			
		};
		Collections.shuffle(lists2);
		System.out.println(lists2);
		
		Stream<Integer> sm2 = lists2.stream().limit(20).sorted();
		sm2.forEach(x -> System.out.print(x + " "));
		System.out.println();

		sm2 = lists2.stream().limit(20).sorted();
		sm2.filter(x -> x%2 == 0).sorted().forEach(x -> System.out.print(x + " "));
	}
}

예제 5

  • Filter
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import day7.Nation;
import day7.Nation;
import day7.Util;

public class FilterDemo_1 {

	public static void main(String[] args) {
		Stream<String> s1 = Stream.of("a1", "b1", "b2", "c1", "c2", "c3");
		String str = "avds";
		System.out.println(str.startsWith("a"));
		
		// Q1 c로 시작하는 문자열들만 추출
		s1.filter(x -> x.startsWith("c")==true ).forEach(x -> System.out.print(x + " "));
		System.out.println();
		
		// Q2 짝수만 골라서 출력
		IntStream is = IntStream.of(1,4,5,1,4,5,8,4,7,4,1,5);
		is.filter(x -> x%2 ==0 ).forEach(Util::print);
		System.out.println();
		
		// Q3 population 100보다 큰 나라만 출력
		List<Nation> nations = Nation.nations;
		Stream<Nation> ns = nations.stream();
		ns.filter(x -> x.getPopulation() > 100).forEach(x -> System.out.print(x.getName()+" "));
	}

}

// c로 시작하는 문자열들만 추출
// x.startsWith("c")

// 길게 sysout 쓰지말고 
// 이전에 만들어둔 (Util::print) 쓰면 편함

예제 6

  • map 활용 연습

  • 그냥 쓰지 말고 :: 방식으로도 써보기

x -> x.toUpperCase() 
=> String::toUpperCase

x -> Integer.valueOf(x)
=> Integer::valueOf
  • 원래는 charat을 쓸 텐데 그렇게 하면 아래줄에서 valueof, parseint 를 못쓰니 (string이여야해서)

  • 그래서 비슷한 역할인 string ver . substring으로 씀

  • 오류1) 아스키 숫자 표출:

    		Stream sm2 = sm.map( x -> Integer.valueOf(x.indexOf(0)) );
      
import java.util.stream.IntStream;
import java.util.stream.Stream;

import day7.Util;

public class MapDemo1_2 {

	public static void main(String[] args) {

		Stream<String> sm = Stream.of("a1", "b1", "b2", "c1", "c2", "c3");
		// 대문자로 변경
		sm.map(String::toUpperCase).forEach(Util::print);
		System.out.println();
		
		// 숫자만 뽑아서 출력 ( charat(1) 쓰지 말고)
		sm = Stream.of("a1", "b1", "b2", "c1", "c2", "c3");
		Stream<String> sm2 = sm.map( x -> x.substring(1) );
		
		IntStream ism = sm2.mapToInt(x -> Integer.valueOf(x));
		ism.forEach(Util::print);
	}

}
// x -> x.toUpperCase() 
// => String::toUpperCase


// x -> Integer.valueOf(x)
// => Integer::valueOf

// 원래는 charat을 쓸 텐데 그렇게 하면 아래줄에서 valueof, parseint 를 못쓰니 (string이여야해서)
// 그래서 비슷한 역할인 string ver . substring으로 씀
// 오류1) 아스키 숫자 표출: Stream sm2 = sm.map( x -> Integer.valueOf(x.indexOf(0)) );

0개의 댓글