Java 8 새로운 기능 스트림 프로그래밍

스트림 요약 및 사용 시나리오

스트림 요약

Stream은 InputStream 및 outputStream과 다릅니다.보다 효율적인 집계 작업 (필터링, 정렬, 통계적 그룹화) 또는 대규모 데이터 작업을 완료 할 수 있도록 컬렉션 반복기를 향상시키는 데 사용됩니다. 또한 스트림 및 람바다 식을 사용하여 휴일 후 코딩 효율이 크게 향상되고 가독성이 더 강해

Stream은 SQL 문을 사용하여 데이터베이스에서 데이터를 쿼리하는 것과 유사한 직관적 인 방법을 사용하여 Java 집합 작업 및 식의 높은 수준의 추상화를 제공합니다.

스트림을 배우기 전에 Lambda 표현식에 대해 어느 정도 이해해야합니다.

다음 예제는 Stream이 수행 할 수있는 작업을 설명 할 수 있습니다.

[외부 링크 이미지 전송에 실패했습니다. 소스 사이트에 안티 리치 링크 메커니즘이있을 수 있습니다. 이미지를 저장하고 직접 업로드하는 것이 좋습니다 (img-uDjczjF4-1599051678458) (/ Users / faro_z / Library / Application Support / typora- user-images / image-20200902144322581 .png)]

위의 예에서 일부 컬러 플라스틱 볼이 데이터 소스로 얻어지고 빨간색 볼이 먼저 필터링되어 임의의 삼각형으로 녹아 듭니다. 다시 필터링하고 작은 삼각형을 삭제합니다. 마지막으로 나머지 그래픽의 둘레를 계산합니다.

위의 그림과 같이 스트림 처리에는 주로 스트림 생성, 중간 작업, 터미널 작업의 세 가지 주요 작업이 있습니다.

더 간결한 용어로, 그것은에 컬렉션의 요소를 넣어하는 것입니다 조립 라인조건을 추가 각 단계에서 몇 가지 요소를 필터링 , 그리고 마지막으로 떠나 요소 당신이 원하는합니다.

스트림 운영 프로세스

스트림 처리에는 주로 스트림 생성, 중간 작업 및 터미널 작업의 세 가지 주요 작업이 있습니다.

  • 스트림 생성 : stream () 메서드입니다.
  • 중간 작업 : 필터링 및 정렬 작업
  • 최종 작업 :이 작업을 꺼내 인쇄

다음은 이러한 세 가지 유형의 작업에 대한 구체적인 소개를 제공합니다.

파이프 라인 소스 / 스트림 생성

컬렉션을 파이프 라인 소스로 전환하는 것은 간단합니다. 호출 스트림

heros.stream();

그러나 배열에는 스트림 메서드가 없으므로 사용해야합니다.

Arrays.stream(hs);

또는

Stream.of(hs);

여기서 I / O 작업에서 InputStream과 OutputStream을 혼동하지 마십시오. 둘은 같은 개념이 아닙니다.

중간 작업

각 중간 작업은 Stream을 반환합니다. 예를 들어 .filter ()는 Stream을 반환합니다. 중간 작업은 "지연"작업이며 순회되지 않습니다.
주로 두 가지 범주
, 필터링 요소 및 다른 형태의 흐름으로 변환하는 많은 중간 작업이 있습니다.

필터 요소 :

필터는
중복을 제거하기 위해 구별 일치 (같음으로 판단) // 참고 : 같음 객체가 동일한 객체인지 여부를 판단합니다. 다음은 Object의 equals () 소스 코드입니다.

public boolean equals(Object obj)
{
     
     
	return this == obj;
}

그러나 equals in String은 문자열 내용이 동일한 지 여부를 판단합니다 (물론 동일한 문자열 객체이면 true를 반환합니다).

정렬 됨 자연 정렬
정렬 됨 (비교기) 정렬
제한 지정 ,
건너 뛰기 및 무시

다른 형태의 스트림으로 변환 :

mapToInt
(), mapToLong ()과 유사한 이중 스트림으로 변환 된 mapToDouble

지도는 모든 유형의 스트림으로 변환됩니다.

package lambda;
  
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
import charactor.Hero;
  
public class TestAggregate {
    
    
  
    public static void main(String[] args) {
    
    
        Random r = new Random();
        List<Hero> heros = new ArrayList<Hero>();
        for (int i = 0; i < 5; i++) {
    
    
            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));
        }
        //制造一个重复数据
        heros.add(heros.get(0));
        System.out.println("初始化集合后的数据 (最后一个数据重复):");
        System.out.println(heros);
        System.out.println("满足条件hp>100&&damage<50的数据");
          
        heros
            .stream()
            .filter(h->h.hp>100&&h.damage<50)
            .forEach(h->System.out.print(h));
          
        System.out.println("去除重复的数据,去除标准是看equals");
        heros
            .stream()
            .distinct()
            .forEach(h->System.out.print(h));
        System.out.println("按照血量排序");
        heros
            .stream()
            .sorted((h1,h2)->h1.hp>=h2.hp?1:-1)
            .forEach(h->System.out.print(h));
          
        System.out.println("保留3个");
        heros
            .stream()
            .limit(3)
            .forEach(h->System.out.print(h));
          
        System.out.println("忽略前3个");
        heros
            .stream()
            .skip(3)
            .forEach(h->System.out.print(h));
          
        System.out.println("转换为double的Stream");
        heros
            .stream()
          //这里虽然获取的是血量
          //但是操作的还是对象
            .mapToDouble(Hero::getHp)
            .forEach(h->System.out.println(h));
          
        System.out.println("转换任意类型的Stream");
        heros
            .stream()
            .map((h)-> h.name + " - " + h.hp + " - " + h.damage)
            .forEach(h->System.out.println(h));
          
    }
}

[외부 링크 이미지 전송에 실패했습니다. 소스 사이트에 안티 리치 링크 메커니즘이있을 수 있습니다. 이미지를 저장하고 직접 업로드하는 것이 좋습니다 (img-acom9UEy-1599051678462) (/ Users / faro_z / Library / Application Support / typora- user-images / image-20200902191427499 .png)]

다른 예를보세요

List<String> strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
Stream s = strings.stream()
  .filter(string -> string.length()<= 6)
  .map(String::length)
  .sorted()
  .limit(3)
  .distinct();

다음 그림은 Stream 개체의 변경 프로세스를 보여줍니다.

[외부 링크 이미지 전송에 실패했습니다. 원본 사이트에 안티 리치 링크 메커니즘이있을 수 있습니다. 이미지를 저장하고 직접 업로드하는 것이 좋습니다. (img-JPggVXPb-1599051678467) (/ Users / faro_z / Library / Application Support / typora- user-images / image-20200902193853184 .png)]

최종 작업

Stream의 중간 작업의 결과는 여전히 Stream이므로 Stream을 필요한 유형으로 변환하는 방법은 무엇입니까? 예를 들어, 스트림의 요소 수를 계산하고 스트림을 세트로 대체하는 등의 작업이 있습니다. 이것은 터미널 작동이 필요합니다

최종 작업은 스트림을 소비하고 최종 결과를 생성합니다. 즉, 최종 작업 후 스트림을 다시 사용할 수 없으며 중간 작업을 사용할 수 없습니다. 그렇지 않으면 예외가 발생합니다.
일반적인 종료 작업은 다음과 같습니다.

대해 forEach ()는 각 요소를 통과
부담 ()
toArray ()는 배열로 변환
(비교기) 분 작은 소자 걸리는
최대 (비교기)에 가장 큰 요소 소요
개수 ()되는 데 사용 카운트 스트림의 요소 번호
로 findFirst ()를 제 소자

다음은 수집을 사용하는 예입니다.

List<String> strings = Arrays.asList("Hollis", "HollisChuang", "hollis","Hollis666", "Hello", "HelloWorld", "Hollis");
strings  = strings
  .stream()
  .filter(string -> string.startsWith("Hollis"))
  .collect(Collectors.toList());
//找出以“Hollis”开头的元素
System.out.println(strings);
//Hollis, HollisChuang, Hollis666, Hollis

요약하자면

Java의 스트림은 데이터베이스 쿼리 기능과 유사하므로보다 효율적인 코드를 작성할 수 있습니다.

추천

출처blog.csdn.net/weixin_44062380/article/details/108370326