티스토리 뷰

Goal 

 - 스트림의 개념 및 사용이유에 대해 알아본다

 - 스트림 연산에 대해 알아본다

 - 스트림의 예제 코드를 학습한다

 - reduce() 연산에 대해 알아본다

 

1. 스트림의 개념 및 사용이유

 - 자료의 연산을 위해 사용하는 스트림으로 함수형 프로그램을 지원하기 위한 클래스(IO에서 사용하는 스트림은 입출력을 위한 스트림, 같은 용어이나 다른 의미)

 - 자료의 대상과 관계없이 동일한 연산을 수행할 수 있는 기능(자료의 추상화)이 있기 때문에 배열, 컬렉션등에 동일한 연산이 수행되어 일관성 있는 처리가 가능함.

 - 한번 생성하고 사용한 스트림은 재사용할 수 없음 (다른 새로운 메모리에서 연산이 진행되기 때문에) 추가적인 접근을 위해서는 스트림을 새로 생성해 접근해야 함

 - 스트림 연산은 기존 자료를 변경하지 않고 결과를 새로운 스트림에 저장함

 - 중간 연산과 최종 연산으로 구분 되며, 중간 연산이 계속 이어질 수 있고 최종 연산이 수행되어야 모든 연산이 적용되어 결과값을 확인할 수 있다(지연 연산)

 

2. 스트림 연산

 - 스트림에서 연산에 대한 구현부는 람다식을 사용한다.

 

2-1 중간 연산

 - 조건에 맞는 요소를 추출 (filter()) 하거나 요소를 변환 함(꺼내옴) (map())

 

 1) 문자열의 길이가 5 이상인 요소만 출력 하기

sList.stream().filter(s -> s.length() >= 5).forEach(s -> System.out.println(s));
// 스트림 생성   // 중간 연산                     //최종연산

 

 2) 고객 클래스에서 고객 이름만 가져오기

customerList.stream().map(c -> c.getName()).forEach(s -> System.out.println(s));
// 스트림 생성           // 중간 연산         // 최종 연산

 

2-2 최종 연산

 - 스트림의 자료를 소모 하면서 연산을 수행

 - 최종 연산 후에 스트림은 더 이상 다른 연산을 적용할 수 없음

 - forEach() : 요소를 하나씩 꺼내 옴, count() : 요소의 개수, sum() : 요소의 합

 - 이외에도 여러가지 최종연산이 있음

 

3. 스트림 예제

 

3-1 배열에서 연산

package stream;

import java.util.Arrays;

public class IntArrayTest {

    public static void main(String[] args) {
        
        
        int[] arr = {1, 2, 3, 4, 5};
        
       int sum =  Arrays.stream(arr).sum(); //Arrays를 활용하여 stream객체를 만드는 함수가 static으로 선언되어 있어서 바로 사용가능
       int count = (int)Arrays.stream(arr).count();
       
       System.out.println(sum);
       System.out.println(count);

    }

}

 

3-2 collection에서 연산

package stream;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class ArrayListStreamTest {

    public static void main(String[] args) {
        
        
        List<String> sList = new ArrayList<String>();
        sList.add("Tomas");
        sList.add("Edward");
        sList.add("Jack");
        
        //collection에서 stream을 사용할 때는 객체에 담는다
        Stream<String> stream = sList.stream();
        //리스트의 이름 출력
        stream.forEach(s -> System.out.print(s + " "));
        System.out.println();
        
        //출력을 하는데 소팅하고 싶을 때      
        sList.stream().sorted().forEach(s -> System.out.print(s + " "));
        System.out.println();
        
        //각 이름의 길이를 map으로 가져와서 forEach로 하나씩 출력함.
        sList.stream().map(s -> s.length()).forEach(n -> System.out.println(n));

    }

}

4. reduce() 연산

 - forEach(), count(), sum()과 같이 자주사용하는 메서드들은 이미 정의되어 있는 연산임.

 - reduce() 연산은 정의된 연산이 아닌 프로그래머가 직접 지정하는 연산을 적용함.

 - 최종 연산으로 스트림의 요소를 소모하며 연산을 수행

 

 

사진 1) 배열의 모든 요소의 합을 구하는 reduce() 연산

 

 

 - 두 번째 요소로 전달되는 람다식에 따라 다양한 기능을 수행함.

 

4-1 reduce() 메서드 구현하기

 

1) 가장 긴 문자열을 반환하는 reduce 메서드 구현

package stream;

import java.util.Arrays;

}

public class ReduceTest {

    public static void main(String[] args) {
       
        
        String[] greetings = {"안녕하세요~~~", "hello", "Good morning", "반갑습니다"};
        
        //가장 긴 문자열을 반환하는 reduce 메서드 구현
       System.out.println(Arrays.stream(greetings).reduce("", (s1, s2) -> 
        { if (s1.getBytes().length >= s2.getBytes().length)
            return s1;
        else return s2;
        }));

    }

}

 

 2)  BinaryOperator를 이용한 reduce() 연산 구현 코드.

 - 메서드 구현부가 길어질 경우 BinaryOperator를 구현한다.

 - 가장 긴 문자열을 반환하는 reduce 메서드를 BinaryOperator를 이용하여 구현.

package stream;

import java.util.Arrays;
import java.util.function.BinaryOperator;

//메서드 구현부가 길어질 경우 BinaryOperator를 구현한다.
class CompareString implements BinaryOperator<String>{

    @Override
    public String apply(String s1, String s2) {
        if (s1.getBytes().length >= s2.getBytes().length)
            return s1;
        else return s2;
    }
    
}

public class ReduceTest {

    public static void main(String[] args) {
       
        
        String[] greetings = {"안녕하세요~~~", "hello", "Good morning", "반갑습니다"}        
           
       // BinaryOperator를 구현한 CompareString 객체를 reduce에 넣어준다.
       System.out.println(Arrays.stream(greetings).reduce(new CompareString()).get());
    }

}

 

 

'Java > Java 올인원 패키지' 카테고리의 다른 글

31. 입출력 스트림 (Java)  (0) 2020.03.24
30. 예외 처리 (Java)  (0) 2020.03.24
28. 람다식 (Java)  (0) 2020.03.23
27. 내부 클래스 (Java)  (0) 2020.03.21
25. Set 인터페이스 (Java)  (0) 2020.03.19
댓글