Java 스트림 탐색

이 자습서를 이해하려면 Java로 코드를 작성하는 기본 사항을 잘 알고 있어야 합니다. 따라하고 일부 코드를 시도하려면 선호하는 IDE를 사용할 수 있습니다. 저는 개인적으로 IntelliJ를 사용합니다.

스트림이란 무엇입니까?



Java의 스트림은 본질적으로 주어진 데이터 소스(배열 또는 컬렉션)의 요소 시퀀스입니다. 스트림은 데이터를 저장하지 않고 대신 해당 데이터에 대해 일부 작업을 수행할 수 있도록 하는 파이프라인 역할을 합니다.

이러한 작업에는 중간 및 터미널의 두 가지 유형이 있습니다. 중간 작업은 항상 Stream을 반환하므로 여러 중간 작업을 계속 연결할 수 있습니다. 가장 일반적인 것은 map() 및 filter()입니다. 그러나 터미널 작업은 void 또는 일부 다른 반환 유형을 반환하고 이름에서 알 수 있듯이 파이프라인을 종료합니다. 가장 일반적인 터미널 작업은 forEach()입니다.

스트림을 어떻게 생성합니까?



스트림을 만드는 방법에는 여러 가지가 있습니다.

이들 중 가장 일반적인 것은 아마도 컬렉션에 대한 컬렉션 인터페이스와 배열에 대한 Arrays 클래스의 stream() 메서드를 사용하는 것입니다.

// Stream from a list
List<Integer> numList = List.of(3, 56, 7, 6);
Stream<Integer> numListStream = numList.stream();


// Stream from an array
Integer[] numArray = new Integer[]{3, 56, 7, 6};
Stream<Integer> numArrayStream = Arrays.stream(numArray);


스트림의 요소를 매개변수로 받는 Stream.of()를 사용하여 스트림을 만들 수도 있습니다.

Stream<Integer> numbersStream = Stream.of(3, 56, 7, 6);


스트림을 생성하는 또 다른 방법은 Stream.generate() 또는 Stream.iterate()를 사용하는 것입니다. 이 두 메서드는 무한 스트림을 생성하므로 항상 limit() 메서드를 통해 스트림의 일부가 될 요소 수를 제한해야 합니다. 이러한 메소드는 모두 요소를 생성하기 위해 공급자를 매개변수로 사용합니다. Stream.iterate() 메서드는 추가로 초기 요소를 매개변수로 사용하며 후속 요소를 생성하는 데에도 사용됩니다.

Stream<String> stringStream = Stream.generate(() -> "Streams are cool").limit(10);
// Print "Streams are cool" 10 times
stringStream.forEach(System.out::println);

Stream<Integer> multiplesOfThreeStream = Stream.iterate(3, num -> num + 3).limit(10);
// Print the first 10 multiples of 3
multiplesOfThreeStream.forEach(System.out::println);


기본 유형 int, long 및 double의 경우 각각 IntStream, LongStream 및 DoubleStream과 같은 세 가지 특수 인터페이스를 사용하여 해당 유형에 대한 스트림을 만들 수도 있습니다. 여기에는 주어진 범위, 즉 range() 및 rangeClosed() 메서드 내의 값으로 정렬된 스트림을 생성할 수 있는 편리한 메서드가 함께 제공됩니다.

IntStream intStream = IntStream.of(3, 56, 7, 6);
LongStream longStream = LongStream.of(3L, 56L, 7L);
DoubleStream doubleStream = DoubleStream.of(3.2, 5.6, 7.0);

IntStream intStreamRange = IntStream.range(1, 11);
// Print 1 2 3 4 5 6 7 8 9 10
intStreamRange.forEach(System.out::println);

IntStream intStreamRangeClosed = IntStream.rangeClosed(1, 10);
// Print 1 2 3 4 5 6 7 8 9 10
intStreamRangeClosed.forEach(System.out::println);


어쨌든 스트림에 대한 큰 문제는 무엇입니까?



Streams의 가장 큰 장점 중 하나는 명령형 프로그래밍에서 선언형 프로그래밍으로 이동할 수 있다는 것입니다. Java에서는 강력하고 간결한 코드로 이어지는 Lambdas를 활용하는 함수형 스타일 프로그래밍을 사용하여 이를 달성합니다.

예를 들어 설명하겠습니다. 다음을 수행하려는 문자열 목록이 있다고 상상해 보십시오.
  • 목록을 사전순으로 정렬합니다
  • .
  • 중복 제거
  • 모든 글자를 대문자로 표기하십시오
  • .
  • 문자 "x"로 끝나는 문자열 유지
  • 콘솔로 인쇄

  • 목록:

    List<String> words = new ArrayList<>(List.of("track", "enfix", "spell", "complex","impulse", "comedy", "magnetic", "complex", "witch", "plead", "spell", "thesis", "thesis"));
    


    명령형 접근 방식에서는 다음과 같은 방법을 사용할 수 있습니다.

    Collections.sort(words);
    Set<String> wordsWithoutDuplicates = new LinkedHashSet<>(words);
    for(String word : wordsWithoutDuplicates) {
        if (word.endsWith("x")) {
            String wordCapitalized = word.toUpperCase();
            System.out.println(wordCapitalized);
        }
    }
    


    선언적 접근 방식을 사용하면 다음과 같은 잠재적 솔루션이 있습니다. 코드가 얼마나 깨끗한지 확인하십시오.

    words.stream()
            .sorted()
            .distinct()
            .filter(word -> word.endsWith("x"))
            .map(String::toUpperCase)
            .forEach(System.out::println);
    


    이것은 데이터를 조작하는 강력한 수단을 제공하는 Java 8에 도입된 Streams에 대한 매우 간략한 개요였습니다.

    좋은 웹페이지 즐겨찾기