본문 바로가기
언어 공부/Java_Spring

[ 자바/Java] Java_Stream

by 무으리 2024. 6. 17.

혼공

stream의 대상 : Collection 과 배열을 대상으로 스트림 생성

함수형 프로그래밍 방식 : 데이터와 객체 중심이 아닌, 입력에 따른 출력만 존재
데이터의 안정성 향상
java에서 함수형프로그래밍을 지원하기 위한 라이브러리가 streamAPI
=> stream<String>, intstream

 

stream 생성

        String[] stArr = {"HTML", "CSS", "JAVA", "PYTHON"};
//        stream<클래스명> : 제네릭타입으로 stream객체가 생성
        Stream<String> stream1 = Arrays.stream(stArr);
        List<String> stList = new ArrayList<>(Arrays.asList(stArr));
        Stream<String> stream2 = stList.stream();

        int[] intArr = {10,20,30,40,50};
//        기본 자료형은 별도의 stream 제공
        IntStream stream3 = Arrays.stream(intArr);

        List<Integer> myList = new ArrayList<>();
        myList.add(10);
        myList.add(20);
        myList.add(30);

        Stream<Integer> stream4 = myList.stream();
//        오류가 발생한다. why?
//        int가 아니라 Integer이기 때문에 Intstream은 사용 불가
        IntStream stream5 = myList.stream();

 

 

stream 변환 연산 : filter, map, sorted, distinct, limit

String[] stArr = {"HTML", "CSS", "JAVA", "PYTHON"};

filter : 특정기준으로 대상을 filtering하는

//        stream<String>을 반환
//        참조변수의 스트림변환의 경우 제네릭의 타입소거 문제 발생
//        제네릭의 타입소거란 제네릭타입을 런타입시점에는 제거하는 것을 의미한다.
//        그래서, 타입이 소거된 Stream객체에서 배열로 변환하려면 타입이 뭔지 명시해 주어야 한다.(타입캐스팅)
        String[] newStArr = Arrays.stream(stArr).filter(a->a.length() <= 4).toArray(a -> new String[a]);
//        메소드 참조 방식(매개변수가 추론가능할때 생략하는 형식) : 클래스::메서드
        String[] newStArr2 = Arrays.stream(stArr).filter(a->a.length() <= 4).toArray(String[]::new);
//        두개가 같다
        Arrays.stream(stArr).forEach(System.out::println);
        Arrays.stream(stArr).forEach(a-> System.out.println(a));

 

int[] intArr = {10,10,30,40,50};
// 30 이하인 값만 출력
	int[] newIntArr = Arrays.stream(intArr).filter(a->a <= 30).toArray();
        System.out.println(Arrays.toString(newIntArr));

 

distinct : 중복 제거

sum : 배열의 합

// 중복제거
	int[] newIntArr2= Arrays.stream(intArr).distinct().toArray();
        System.out.println(Arrays.toString(newIntArr2));
// 총합
        int total = Arrays.stream(intArr).sum();
        System.out.println(total);

 

map : 기존의 스트림을 조작하여 새로운 스트림 반환

// 각 요소에 10을 곱한 값 출력
	int[] newMapArr =Arrays.stream(intArr).map(a->a*10).toArray();
        System.out.println(newMapArr);

 

mapToInt : int stream의 형태로 변환해 주는 map

String[] stArr = {"HTML","CSS","JAVASCRIPT","JAVA"};
//        각 문자열의 길이를 담은 새로운 int배열 생성
//	String의 길이를 저장한 배열 출력
        int[] intArr = Arrays.stream(stArr).mapToInt(String::length).toArray();
//	String의 길이를 저장한 배열 3번 인덱스 까지 -> JAVA는 limit 에 제한됨
        int[] intArr2 = Arrays.stream(stArr).mapToInt(String::length).limit(3).toArray();
        System.out.println(Arrays.toString(intArr));
        System.out.println(Arrays.toString(intArr2));

 

스트림의 소모 : sum-합계, reduce-누적합계, foreach(출력) 등

foreach - 각각의 요소를 출력

int[] intArr3 = {10,20,30,40};
Arrays.stream(intArr3).forEach(System.out::println);

 

sum - 합계

        int[] intArr3 = {10,20,30,40};
        int intArrSum = Arrays.stream(intArr3).sum();
        System.out.println(intArrSum);

 

Optional객체 : 값이 있을수도 있고, 없을수도 있음을 명시한 객체

ex) max, min, count, average

int intArrMax = Arrays.stream(intArr3).max().getAsInt();
int intArrMin = Arrays.stream(intArr3).min().getAsInt();
int intArrCount = (int)Arrays.stream(intArr3).count();
int allMultiply = Arrays.stream(intArr3).reduce(1,(a,b) -> a*b);
int allAdd = Arrays.stream(intArr3).reduce(0, (a,b) -> a+b);
System.out.println("최대값 " + intArrMax);
System.out.println("최소값 " + intArrMin);
System.out.println("개수 " + intArrCount);
System.out.println("누적곱 " + allMultiply);
System.out.println("누적합 " + allAdd);

다른 객체의 값 또한 가져올수 있다.

ex) student 객체의 이름이나 나이를 가져옴

List<Student> students = new ArrayList<>();
students.add(new Student("kim", 20));
students.add(new Student("choi", 32));
students.add(new Student("lee", 35));
students.add(new Student("park", 22));

findFirst : 첫번째 요소 반환

//        1) 나이가 30이 넘는 학생중에 첫번째 index값을 가지는 학생 객체 생성
//           get이 없으면 오류
//        student객체 실습
//        2) 모든 객체의 평균나이
//        3) 가장 나이 어린 사람 찾기
//        4-1) 30대가 몇명인지 출력 
//	  4-2) 30대의 이름을 String배열에 담기
// 1)
Student s1 = students.stream().filter(a->a.getAge() >= 30).findFirst().get();
System.out.println("30이상인 첫번째 index : " + s1.getName() + " " + s1.getAge());
// 2)
int averageAge = (int) students.stream().mapToInt(a->a.getAge()).average().getAsDouble();
System.out.println(averageAge);
// 3)
Student s2 = students.stream().sorted((a,b) -> a.getAge()-b.getAge()).findFirst().get();
System.out.println("s2의 이름과 나이 : " + s2.getName() + " " + s2.getAge());
// 4-1)
int countthr = (int) students.stream().filter(a->a.getAge() >= 30).count();
System.out.println("30대가 몇명인가? : " + countthr);
// 4-2)
String[] countth = students.stream().filter(a->a.getAge()>=30).map(a->a.getName()).toArray(String[]::new);
System.out.println("30대인 사람의 이름을 담은 배열 : " + Arrays.toString(countth));