JAVA 8 새로운 특성 Stream 의 사용 방법 총화

10057 단어 learning자바
왜 스 트림 이 필요 해
Stream 은 자바 8 의 하 이 라이트 로 자바.io 가방 의 InputStream 과 OutputStream 과 는 전혀 다른 개념 입 니 다.이 는 StAX 가 XML 에 대한 스 트림 과 달리 Amazon Kinesis 가 빅 데 이 터 를 실시 간 으로 처리 하 는 스 트림 도 아니다.자바 8 의 Stream 은 집합(Collection)대상 의 기능 을 강화 하 는 것 으로 집합 대상 에 대해 각종 매우 편리 하고 효율 적 인 집합 작업(aggregate operation)이나 대량의 데이터 조작(bulk data operation)에 전념 합 니 다.Stream API 는 같은 새로운 Lambda 표현 식 을 통 해 프로 그래 밍 효율 과 프로그램 가 독성 을 크게 향상 시 킵 니 다.이 동시에 직렬 과 병렬 두 가지 모델 을 제공 하여 집합 작업 을 할 수 있 습 니 다.병렬 모드 는 다 중 핵 프로세서 의 장점 을 충분히 이용 하여 fork/join 병렬 방식 으로 작업 과 가속 처리 과정 을 나 눌 수 있 습 니 다.보통 병렬 코드 를 만 드 는 것 은 어렵 고 오류 가 발생 하기 쉽 지만 Stream API 를 사용 하면 다 중 스 레 드 코드 를 만 들 지 않 아 도 고성능 병렬 프로그램 을 편리 하 게 쓸 수 있 습 니 다.그래서 자바 8 에 처음 등장 한 자바 util.stream 은 함수 식 언어+다 핵 시대 의 종합 적 인 영향 을 미 친 결과 물이 다.
stream 의 주요 사용 방법 을 직접 소개 합 니 다.
1:map,조작 요 소 는 하나의 stream 의 요 소 를 처리 하여 다른 stream 에 넣 습 니 다.
List<CustomerStatisticsDTO> dtos = datas.stream().map(r->ConvertHelper.convert(r, CustomerStatisticsDTO.class)).collect(Collectors.toList());

이 예 에서 저 희 는 ConvertHelp 을 사용 하여 datas 라 는 list 의 모든 노드 대상 을 customer Statistics DTO 로 바 꾸 고 List 라 는 새로운 list 에 넣 었 습 니 다.자바 7 이전 쓰기 에 대응 합 니 다.
List dtos = new ArrayList<>();
for(CustomerStatistics data : datas){
   dtos.add(ConvertHelper.convert(r, CustomerStatisticsDTO.class));
}

순간적으로 격 이 많이 올 라 간 것 같 고 stream 자 체 를 사용 하 는 효율 도 높 아 집 니 다.
map 또 하나의 좋 은 점 은 pojo 류 중의 특정한 속성 을 편리 하 게 추출 할 수 있 는 집합 이다.예 를 들 어:
List ids = datas.stream().map(CustomerStatistics::getId).collect(Collectors.toList());

이 방법 은 datas 집합 에 있 는 모든 노드 의 id 를 꺼 내 ids 목록 에 넣 는 것 입 니 다.대응 하 는 자바 7 함 수 는?
List ids = new ArrayList<>();
for(CustomerStatistics data : datas){
   ids.add(data.getId());
}

2.foreach,요 소 를 옮 겨 다 니 며 작업 합 니 다.
stream 에 또 하나의 좋 은 함수 가 있 는데 바로 foreach 입 니 다.자바 7 의 foreach 를 완벽 하 게 대체 할 수 있 습 니 다.코드 를 직접 올 립 니 다.
Lock lock = new ReentrantLock();
……
cmd.getContacts().parallelStream.forEach((c) -> {
    lock.lock();
    CustomerContact contact = ConvertHelper.convert(c, CustomerContact.class);
    contact.setCustomerId(cmd.getId());
    contact.setCommunityId(cmd.getCommunityId());
    contact.setNamespaceId(cmd.getNamespaceId());
    contact.setStatus(CommonStatus.ACTIVE.getCode());
    contact.setCustomerSource(cmd.getCustomerSource());
    if(StringUtils.isNotBlank(contact.getName()) && StringUtils.isNotBlank(contact.getPhoneNumber())){
        invitedCustomerProvider.createContact(contact);
    }
    lock.unlock();
});

원래 foreach:
for(CustomerContactDTO dto : cmd.getContacts()){
    CustomerContact contact = ConvertHelper.convert(dto, CustomerContact.class);
    contact.setCustomerId(cmd.getId());
    contact.setCommunityId(cmd.getCommunityId());
    contact.setNamespaceId(cmd.getNamespaceId());
    contact.setStatus(CommonStatus.ACTIVE.getCode());
    contact.setCustomerSource(cmd.getCustomerSource());
    if(StringUtils.isNotBlank(contact.getName()) && StringUtils.isNotBlank(contact.getPhoneNumber())){
        invitedCustomerProvider.createContact(contact);
    }
}

이 foreach 는 foreach 와 차이 가 크 지 않 지만 dto 를 취 하 는 절 차 를 생략 할 뿐만 아니 라 parallelStream 을 사용 하면 list 를 병행 처리 할 수 있 습 니 다.복잡 한 논리 에 있어 서 특히 효과 적 입 니 다.그러나 parallelStream 은 스 레 드 가 안전 하지 않 으 므 로 사용 할 때 자 물 쇠 를 잠 그 는 것 을 기억 하 세 요.만약 에 마음 이 놓 이지 않 으 면...stream().foreach()를 직접 사용 해도 됩 니 다.
3.filter,조건 을 통 해 집합 요 소 를 걸 러 냅 니 다.
filter 도 좋 은 방법 입 니 다.우리 가 제시 한 조건 에 따라 기 존의 집합 에서 원 하 는 노드 를 걸 러 새로운 집합 을 구성 할 수 있 습 니 다.예 를 들 어:
List exists = existItemList.stream().filter(r-> r.getFieldId().equals(item.getFieldId()) && r.getDisplayName().equals(item.getItemDisplayName())).collect(Collectors.toList());

이 예 에서 exist ItemList 도 List 입 니 다.한 정 된 조건 을 통 해 우 리 는 exist ItemList 라 는 list 를 옮 겨 다 니 며 우리 의 여과 조건 에 맞 는 배열 의 집합 을 꺼 낼 수 있 습 니 다.자바 7 과 이전 방법 을 사용 하면 우 리 는 이렇게 썼 습 니 다.
List exists = new ArrayList<>();
for(FieldItem item : existItemList){
    if(item.equals(item.getFieldId()) && r.getDisplayName().equals(item.getItemDisplayName())){
        exists.add(item);
    }
}

이것 도 한 줄 코드 로 6 줄 코드 를 직관 적 이 고 간결 하 게 쓸 수 있 는 효과 로 사용 하기 편 하 다.
4.통계 에서 stream 사용
stream 또 하나의 중요 한 의 미 는 통계 입 니 다.mapToInt 방법 을 제공 하여 우리 가 더욱 간결 한 코드 로 더욱 높 은 효율 ps 를 쓸 수 있 도록 도와 주 었 습 니 다.통 계 는 기본적으로 log 로 돌아 가기 때문에 저 는 유형 전환 을 했 습 니 다.
data.setTrackingNum(Integer.valueOf(String.valueOf(tempResult.stream().map(StatisticDataDTO::getTrackingNum).collect(Collectors.toList()).stream().mapToInt(x->x).summaryStatistics().getSum())));

여기 서 나 는 stream 의 조작 을 두 번 사용 하여 다음 과 같은 조작 으로 나 눌 수 있다.
    list tempResult,   StatisticDataDTO   ,       tempResult      DTO  trackingNum   ,    :
List trackingNums = tempResult.stream().map(StatisticDataDTO::getTrackingNum).collect(Collectors.toList());

    mapToInt
//  stream       Long  ,      DTO  Integer  ,        
Long trackingSum = trackingNums.stream().mapToInt(x->x).summaryStatistics().getSum();
data.setTrackingNum(Integer.valueOf(String.valueOf(trackingSum)));


stream 효율 이 높 아 foreach 보다 훨씬 좋 습 니 다.
Integer trackingSum = 0;
for(StatisticDataDTO tempNote : tempResult){
    trackingSum += tempNote.getTrackingNum();
}

그 다음 에 저 는 테스트 코드 테스트 효율 을 썼 습 니 다.이것 은 자바 8 의 흐름 통계 와 우리 의 전통 적 인 방법 효율 의 차이 입 니 다.먼저 가장 간단 한 더하기 알고리즘 입 니 다.먼저 1,000,000 만 개의 수 를 더 해 보 세 요.
public static void main(String[] args)
    {
        List filterLists = new ArrayList<>();
        for(int i=0;i<1000000;i++)
        {
            filterLists.add(i);
        }

        Long sum = 0L;
        Date a = new Date();
        for(Integer i : filterLists)
        {
            sum += i;
        }
        System.out.println(sum);
        Date b = new Date();
        sum = 0L;
        Date c = new Date();
        sum = filterLists.stream().mapToInt(x->x).summaryStatistics().getSum();
        System.out.println(sum);
        Date d = new Date();

        long interval = b.getTime()-a.getTime();
        long interval2 = d.getTime()-c.getTime();
        System.out.println("      1:"+interval);//
        System.out.println("      2:"+interval2);//
    }


499999500000
499999500000
두 시간 차이 1:21
두 시간 차이 2:91
이 때 전통 적 인 foreach 순환 이 더 빨 라 집 니 다.
그 다음 에 데 이 터 를 10 배 확대 하여 10,000,000 개 수의 합 을 취한 다.
public static void main(String[] args)
    {
        List filterLists = new ArrayList<>();
        for(int i=0;i<10000000;i++)
        {
            filterLists.add(i);
        }

        Long sum = 0L;
        Date a = new Date();
        for(Integer i : filterLists)
        {
            sum += i;
        }
        System.out.println(sum);
        Date b = new Date();
        sum = 0L;
        Date c = new Date();
        sum = filterLists.stream().mapToInt(x->x).summaryStatistics().getSum();
        System.out.println(sum);
        Date d = new Date();

        long interval = b.getTime()-a.getTime();
        long interval2 = d.getTime()-c.getTime();
        System.out.println("      1:"+interval);//7251
        System.out.println("      2:"+interval2);//307
    }


49999995000000
49999995000000
두 시간의 차 이 는 1:1462 이다.
두 시간의 차 이 는 2:98 이다.
마지막 으로 데 이 터 량 을 10 배 더 늘 려 100,000,000 개 수의 합 을 취한 다.
public static void main(String[] args)
    {
        List filterLists = new ArrayList<>();
        for(int i=0;i<100000000;i++)
        {
            filterLists.add(i);
        }

        Long sum = 0L;
        Date a = new Date();
        for(int j=0;j<100000000;j++)
        {
            sum += filterLists.get(j);
        }
        System.out.println(sum);
        Date b = new Date();
        sum = 0L;
        Date c = new Date();
        sum = filterLists.stream().mapToInt(x->x).summaryStatistics().getSum();
        System.out.println(sum);
        Date d = new Date();

        long interval = b.getTime()-a.getTime();
        long interval2 = d.getTime()-c.getTime();
        System.out.println("      1:"+interval);//7251
        System.out.println("      2:"+interval2);//307
    }


4999999950000000
4999999950000000
두 시간의 차 이 는 1:4386 이다.
두 시간 차이 2:188
데이터 양 이 많 지 않 은 집합 을 처리 할 때 성능 은 차이 가 별로 없 지만 복잡 한 논리 나 대량 계산 과 관련 이 있다 면 stream 의 통계 와 전통 적 인 for 순환 의 시간 복잡 도 는 같은 등급 이 아니 므 로 통계 와 관련 된 부분 에서 stream 의 통 계 를 사용 하 는 것 을 강력 히 추천 합 니 다.정말 효율 적 입 니 다.

좋은 웹페이지 즐겨찾기