자바 기본기 정리 4

유승선 ·2023년 2월 8일
0

자바 독학

목록 보기
5/10
post-thumbnail

스트림

스트림이란?

  • 데이터의 흐름을 만들어 준다.
  • 컬렉션 형태로 구성된 데이터를 람다로 이용해 간결하고 직관적으로 프로세스를 할 수 있게 합니다.
  • For, while 등을 이용하던 기존 loop을 대체한다.
  • 일회성으로 한번 사용하고 나면 사용할 수 없다.

스트림 생성


Stream<String> nameStream = Stream.of("Alice","Bob"); 
List<String> names = nameStream.collect(Collectors.toList()); 
System.out.println(names); 

String[] cityArray = new String[] {"Sam", "Seoul"}; 
Stream<String> cityStream = Arrays.stream(cityArray); 
List<String> cityList = cityStream.collect(Collectors.toList()); 
System.out.println(cityList); 

Set<Integer> numberSet = new HashSet<>(Arrays.asList(3,5,7)); 
Stream<Integer> numberStream = numberSet.stream(); 
List<Integer> numberList = numberStream.collect(Collectors.toList()); 
System.out.println(numberList); 

위에 언급된 3가지 방법으로 Stream을 생성할 수 있다.

  • Stream.of()
  • Arrays.stream()
  • Collection.stream()

주로 Collection.stream()으로 사용한다.

Filter

Stream<T> filter(Predicate<? super T> predicate);

Stream의 Filter API는 Predicate에서 true를 반환하는 데이터만 존재하는 Stream을 리턴하는 기능을 제공한다.

public class Main {
    public static void main(String[] args) {
        List<Integer> container = Arrays.asList(1,2,3,4).stream()
                                  .filter(x -> x % 2 == 0)
                                  .collect(Collectors.toList()); 
        
        System.out.println(container); 
    }
}

결국 .filter() 안에 존재하는 컨디션이 true를 반환해야 하기 때문에 위와 같이 작성한다면은 짝수인 숫자만 가지고 있는 리스트를 가지고 올 수 있다.

Map

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

Stream의 map API는 stream 흐름에 있는 데이터들을 변형해서 변형된 결과물을 stream으로 반환해준다.

public class Main {
    public static void main(String[] args) {
        List<Integer> container = Arrays.asList(1,2,3,4).stream()
                                  .filter(x -> x % 2 == 0)
                                  .map(x -> x * 2) // stream 데이터들을 2배하여 stream으로 반환
                                  .collect(Collectors.toList()); // stream 데이터를 리스트로 반환
        
        System.out.println(container); 
    }
}

Stream Pipline

스트림은 3부분으로 구성된다.

  • Source
    - 스트림의 시작을 알려주는 부분이다
    • 컬렉션이나 배열 등으로 .stream()을 하며 stream을 만들었던것이 예시다
  • Intermediate Operations (중간처리)
    - filter나 map같이 가공하는 중간 역활이다
    • 여러가지의 중간 처리를 이어붙히는것이 가능하다
  • Terminal Operation (종결처리)
    - .collect로 스트림 데이터를 리스트로 받아오는 과정

sorted()

Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);

데이터가 순서대로 정렬된 Stream을 리턴하는 기능을 제공한다. 서로 비교할 수 없다면은 comparator을 사용해도 괜찮다.

List<Integer> sortedNumber = Arrays.asList(3,-5,7,4).stream()
					   								.sorted()
                                                    .collect(Collectors.toList()); 

distinct()

Stream<T> distinct();

distinct는 stream 데이터 중에서 중복이 제거된 stream을 반환해주는 기능을 제공한다.

List<Integer> numbers = Arrays.asList(3, -5, 4, -5, 2, 3);
		List<Integer> distinctNumbers = numbers.stream()
				.distinct() // 중복된 정수 제거한 스트림을 반환
				.collect(Collectors.toList());
		System.out.println(distinctNumbers);

Stream 종결 처리

종결 처리는 Stream 안의 데이터를 모아 반환하는 역활을 한다.

Collectors

스트림의 결과값들을 컬렉션으로 만드는 방식이다.

public class StreamCollectorsTest {
	public static void main(String[] args) {
		List<Integer> numberList = Stream.of(3, 5, -3, 3, 4, 5)
				.collect(Collectors.toList()); // 리스트로 변환
		System.out.println(numberList);
		
		Set<Integer> numberSet = Stream.of(3, 5, -3, 3, 4, 5)
				.collect(Collectors.toSet()); // Set으로 변환
		System.out.println(numberSet);

		List<Integer> numberList2 = Stream.of(3, 5, -3, 3, 4, 5)
				// map이 우선적으로 적용되고 결과값들을 리스트로 반환
				.collect(Collectors.mapping(x -> Math.abs(x), Collectors.toList()));
		System.out.println(numberList2);

		Set<Integer> numberSet2 = Stream.of(3, 5, -3, 3, 4, 5)
				// map이 우선적으로 적용되고 결과값들을 set으로 반환
				.collect(Collectors.mapping(x -> Math.abs(x), Collectors.toSet()));
		System.out.println(numberSet2);
		
		int sum = Stream.of(3, 5, -3, 3, 4, 5)
				// Stream의 값들을 reduce 해서 반환
				.collect(Collectors.reducing(0, (x, y) -> x + y));
		System.out.println(sum);
	}
}

forEach

void forEach(Consumer<? super T> action);

특징으로는 Java의 iterable 인터페이스에서도 forEach가 있기 때문에 Stream의 중간처리가 필요없다면 굳이 안만들어도 괜찮다.

public class StreamForEachTest {

	public static void main(String[] args) {
		List<Integer> numbers = Arrays.asList(3, 5, 2, 1);
		// stream에 모든 데이터에 대한 처리
		numbers.stream().forEach(number -> System.out.println("The number is " + number));

		// 컬렉션에 기본적으로 forEach가 제공되기 때문에 중간처리가 필요 없다면 굳이 stream으로 만들어서 사용할 필요는 없습니다.
		numbers.forEach(number -> System.out.println("The number is " + number));
	}
}

Optional

NullPointerException 에러는 Null 상태의 오브젝트를 reference 했을때 발생한다. 그리고 이것은 런타임 에러이기 때문에 실행 전까지는 발생 여부를 알기 쉽지 않다.

이런 문제를 해결하기 위해 등장한게 Optional 이다.
Optional은 Null일 수도, 아닐 수도 있는 오브젝트를 담은 상자다.

출처

모든 자료는 백토니 블로그에서 온다. Optional이 궁금하다면은 가서 더 확인하는게 좋을듯하다.

profile
성장하는 사람

0개의 댓글