CS/Java

[Java] 스트림(Stream)

싱브이 2024. 2. 19. 13:34
728x90
반응형

자바 프로젝트를 하면서 아주아주 유용하게 사용하고 있는 람다식과 스트림(둘 다 Java 8부터 추가됨)을 확실하게 정리해버리게 나을 것 같아서 글을 적기로 한다 !

 

 

1. 람다식 (lambda expression)

2. 스트림 (stream)

 

 

 

스트림

연속되는 요소들의 흐름으로 배열, 콜렉션, 파일 등에서 만들어질 수 있다.

  • Java 8부터 추가됨
  • 컬렉션(배열 등)의 저장 요소를 하나씩 참조하여 람다식으로 처리할 수 있도록 해주는 반복자 (Iterator와 비슷한 역할로 코드 간결하게 할 수 있음)

* Iterator와의 차이점

스트림은 내부 반복자를 사용하므로 병렬처리가 쉽다. 

 

 

스트림 사용법

1. 배열

//배열 : 정적 메서드 이용 (Arrays.stream)
String[] array = new String[]{"a", "b", "c"};
Stream<String> stream1 = Arrays.stream(array);
Stream<String> stream2 = Arrays.stream(array, 1, 3); // 인덱스 1포함, 3제외 ("b", "c")

stream1.forEach(a -> System.out.print(a + ","));

 

2. 컬렉션 (클래스)

class Student {    
	private String name;    
    private int score;	    
    
    public Student(String name, int score) {        
    	this.name = name;        
        this.score = score;    
    }     
    
    public String getName() { return name; }    
    public int getScore() { return score; }
}  
    
public class FromCollectionExample {    
	public static void main(String[] args) {        
    	List<Student> studentList = Arrays.asList(            
        	new Student("사람1", 10),            
            new Student("사람2", 20),            
            new Student("사람3", 30)        
        );		        
        
        // 스트림 객체 생성
        Stream<Student> stream = studentList.stream();        
        stream.forEach(s -> System.out.println("이름 : "+ s.getName()));    
    }
}

 

3. 빌더

String<String> stream = Stream<String>builder()
                          .add("Apple")
                          .add("Banana")
                          .build();

 

4. Generator

Stream<String> stream = Stream.generate(() -> "Hi").limit(5);

 

5. Iterator

// (100, 110, 120, 130, 140)
Stream<String> stream = Stream.iterate(100, n -> n + 10).limit(5);

 

 

예제)

홀수만 골라내어 정렬하여 문자열로 만들기 (1, 3, 5..)

List<Integer> int0To9 = new ArrayList<>(
        Arrays.asList(5, 2, 0, 8, 4, 1, 7, 9, 3, 6)
);
// 기존의 방식
List<Integer> odds = new ArrayList<>();
for (var i : int0To9) {
    if (i % 2 == 1) odds.add(i);
}
odds.sort(Integer::compare);
List<String> oddsStrs = new ArrayList<>();
for (var i : odds) {
    oddsStrs.add(String.valueOf(i));
}
var oddsStr = String.join(", ", oddsStrs);
// 스트림을 이용한 방식
var oddsStrStreamed = int0To9
        .stream()
        .filter(i -> i % 2 == 1)
        .sorted(Integer::compare)
        .map(String::valueOf)
        .collect(Collectors.joining(", "));

 

 

 

 

스트림 연산

peek 연산 과정 중에 스트림에 영향을 주지 않으면서 주어진 Consumer 작업을 실행한다. (쉽게 말해서 그냥 한번 해본다 ->중간에 로깅같은거에 사용)
filter 주어진 Predicate에 충족하는 요소만 남긴다.
distinct 중복되지 않는 요소들의 스트림을 반환
map 주어진 Function에 따라 각 요소들을 변경
sorted 요소들을 정렬
limit 주어진 수 만큼의 요소들은 스트림으로 반환
skip 주어진 개수만큼의 요소를 제거
takewhile / dropwhile 주어진 Predicate을 충족하는 동안 갖거나 / 건너뛰거나
forEach 각 요소들에 주어진 Consumer를 실행 (return 안함)
count 요소들의 개수를 반환
min / max 주어진 Comparator에 따라 최소 / 최대값을 반환
reduce 주어진 초기값과 BinaryOperator로 값들을 하나의 값으로 줄여나감

 

 

 

예제)

 

1. Peek

int sum = IntStream.range(1, 10)
  .peek(System.out::println)
  .sum();

 

2. Filter

Stream<Integer> stream = IntStream.range(1, 10).boxed();
stream.filter(v -> ((v % 2) == 0))
            .forEach(System.out::println);
// 2, 4, 6, 8

 

3. Map

Stream<Integer> stream = IntStream.range(1, 10).boxed();
stream.filter(v -> ((v % 2) == 0))
            .map(v -> v * 10)
            .forEach(System.out::println);
// 20, 40, 60, 80

 

4. forEach

Set<Integer> evenNumber = IntStream.range(1, 1000).boxed()
                                    .filter(n -> (n%2 == 0))
                                    .forEach(System.out::println);

// 1~999까지 짝수 출력

 

 

728x90
반응형