chapter 4. Introducing streams

4.1 What are Streams

  • 마치 SQL 쿼리 같이 데이터를 처리
  • 많은 요소를 포함하는 커다란 컬렉션을 단순히 처리

Before(Java 7)

List<Dish> lowCaloricDishes = new ArrayList<>();  
for(Dish d: menu){  
  if(d.getCalories() < 400){
    lowCaloricDishes.add(d);
  }
}

Collections.sort(lowCaloricDishes, new Comparator<Dish>() {  
  @Override
  public int compare(Dish d1, Dish d2) {
    return Integer.compare(d1.getCalories(), d2.getCalories());
  }
});

List<String> lowCaloricDishesName = new ArrayList<>();  
for(Dish d: lowCaloricDishes){  
  lowCaloricDishesName.add(d.getName());
}

자바8 코드

List<String> lowCaloricDishesName =  
  menu.stream()
  //menu.parallelStream()
  .filter(d -> d.getCalories() < 400)
  .sorted(Comparator.comparing(Dish::getCalories))
  .map(Dish::getName)
  .collect(toList());

4.2 Getting started with streams

  • Sequence of elements

    • Collections are about data

    • streams are about computations

  • Source
    • 정렬된 컬렉션으로 스트림을 생성하면 정렬이 그대로 유지된다. 즉 리스트로 스트림을 만들면 스크림의 요소는 리스트의 요소와 같은 순서를 유지한다.
  • Data processing operations
    • 함수형 프로그래밍 언어에서 일반적으로 지원하는 연산과 데이터베이스와 비슷한 연산을 지원
    • 예) filter, map, reduce, find, match, sort 등
    • 스트림연산은 순차적으로 또는 병렬로 실행될 수 있다.

In addition

  • Pipelining
    • 스트림 연산 끼리 연결하여 커다란 파이프라인을 구성 할 수 있음.
    • 게으름(laziness), 쇼트서킷(sort-cicuiting) 같은 최적화를 얻을 수 있음.
    • 데이터베이스의 SQL 쿼리 와 비슷
  • Internal iteration
    • 반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 스트림은 내부 반복을 지원
List<String> threeHightCaloricDishNames =  
            menu.stream()
            .filter(d -> d.getCalories() > 300)
            .map(Dish::getName)
            .limit(3)
            .collect(toList());
  • filter

    • 람다를 인수로 받아 스트림에서 특정 요소를 제외

    filter(d -> d.getCalories() > 300)

  • map

    • 람다를 이용해서 한 요소를 다른 요소로 변환하거나 정보를 추출

    map(Dish::getName)

  • limit

    • 정해진 개수 이상을 추출 못하게 한계를 지정

    limit(3)

  • collect

    • 스트림을 다른 형식으로 변환

    collect(toList());

4.3 Streams vs. Collections

  • DVD vs. Internet stream
  • 모든 값을 메모리에 저장하여 계산 vs. 필요할때만 요소를 계산
  • 브라우저 인터넷 검색

  • Traversavle only once

  List<String> title = Arrays.asList("java8", "In", "Action");
      Stream<String> s = title.stream();
      s.forEach(System.out::println);
      s.forEach(System.out::println);

  output :
  java8
  Exception in thread "main" In
  Action
  java.lang.IllegalStateException: stream has already been operated upon or closed
      at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:274)
      at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
      at Solution.IllegalStateException(Solution.java:77)
      at Solution.main(Solution.java:102)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:497)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
  • External vs. internal iteration

    for-each loop

  List<String> names = new ArrayList<>();
  for(Dish d: menu){
    names.add(d.getName());
  }

iterator

  List<String> names = new ArrayList<>();
  Iterator<String> iterator = menu.iterator();
  while(iterator.hasNext()){
    Dish d = iterator.next();
    names.add(d.getName());
  }

stream: internal iteration

  List<String> names = menu.stream()
                           .map(Dish::getName)
                           .collct(toList());

4.4 Stream operations

  • intermediate operations

  • terminal operations

  • Intermediate operations

    • 다른 intermediate operations 와의 상호연동을 통하여 pipe line 을 형성한다.
    • intermediate operations의 동작들이 하나의 terminal operations으로 모이기 때문에 terminal operations이 호출되어서 파이프라인이 시작하기전 까지의 흐름이 동작하지 않는다( lazy)
    • 파이프라인이 어떻게 동작되고 있는지 확인하기 위하여 각각의 람다함수에 print 문을 삽입한다.(이러한 코딩은 흔히 사용되지 않지만 배우는 과정이기 때문에 특별한 경우이다.)
  List<String> names =
              menu.stream()
              .filter(d -> {
                System.out.println("filtering " + d.getName());
                return d.getCalories() > 300;
              })
              .map(d -> {
                System.out.println("mapping " + d.getName());
                return d.getName();
              })
              .limit(3)
              .collect(toList());
      System.out.println(names);


  filtering pork
  mapping pork
  filtering beef
  mapping beef
  filtering chicken
  mapping chicken
  [pork, beef, chicken]
  1. 칼로리가 300보다 큰 dish 중에 오직 3개만 추출하고 동작이 끝난다.(Short-circuitinge)
  2. filter 와 map 의 명령이 하나의 경로로 합쳐져서 동작한다.(loop fusion)

    • Terminal operations
  3. Stream pipe 로의 결과를 처리한다.

  4. List 나 Integer, 혹은 void 등의 스트림이 아닌 다양한 포맷으로 데이터를 변환하여 리턴한다.

    menu.stream().forEach(System.out::println);

    • Working with streams
  5. Builder pattern 과 비슷

  6. intermediate operations
    • filter
    • map
    • limit
    • sorted
    • distinct
  7. Terminal operations
    • forEach
    • count
    • collect

Summary

  • stream은 데이터처리동작을 지원하는 source에서 연속된 요소이다.
  • Stream은 내부반복을 사용한다.
  • intermediate 와 terminal operations 이 있다.
  • intermediate operations 은 filter와 map 등 stream을 반환하고 다른 stream와 연동된다. 파이프라인이 설정될뿐 어떤 result 동작을 하지 않는다.
  • forEach 와 같은 terminal operations 은 스트림이 아닌 결과를 리턴한다.
  • 스트림의 요소는 요청시에 계산된다.


Posted by 빨강토끼
,

특정 한달 간의 날짜 출력

SELECT TO_CHAR(TO_DATE('20160701','yyyymmdd') + LEVEL - 1, 'yyyymmdd') AS DAY  
FROM DUAL  
CONNECT BY LEVEL <= ADD_MONTHS(TO_DATE('201607','yyyymm'),1) - TO_DATE('201607','yyyymm');  

1~30 까지 출력 
SELECT LEVEL 
FROM DUAL 
CONNECT BY LEVEL <= 30;

Posted by 빨강토끼
,

기존의 Maven 으로 작성된 프로젝트를 Gradle 로 변경하는 작업을 하였다.

자신있게 gradle build 를 했다.

그런데 Maven 으로 잘되던 것이 갑자기 test step 에서 error 가 나는것이다.

이유는 
import static org.hamcrest.CoreMatchers.containsString; 
에서 containsString 을 못찾는것이다.

이유를 찾아보니 
JUnit 에 종속적인 hamcrest 의 org.hamcrest 와 
org.mockito에 있는 org.hamcrest 가 충돌나는 것이었다.

정확한 해결책인지는 아직도 확신은 안들지만 
아래같은 순서로 [프로젝트네임].gradle 파일의 내용을 수정하니 잘되었다.

dependencies {  
  testCompile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3'
  testCompile group: 'org.mockito', name: 'mockito-all', version:'1.10.19'
  testCompile group: 'junit', name: 'junit', version:'4.12'
}

아마도 dependencies 하는 순서대로 호출시 참조하는 것 같다.

Posted by 빨강토끼
,

나는 java 에서 배열을 shift 하는 방법이 가끔 헛갈릴때가 있다.

그중 rotation left 하는 방법을 정리하였다.

그런데 이 방법은 메모리를 주어진 배열의 2배를 사용한다. 주어진 배열만큼의 배열을 하나 더 생성하여서 옮겨진(rotation left) 위치에 copy를 하는 방식이다.

좀 더 효율을 높히기 위하여 생각할수있는 방법은 크게 2가지이다.

  1. 메모리 사용을 줄이기 위하여 직접 in-place 방법으로 처리하는 방식
  2. 속도를 높히기 위해서 하나하나를 copy하는 방식이 아닌 block단위로 copy하는 방식

1번 소스

2번 소스

Posted by 빨강토끼
,
  1. lsof 파일명 
    지정한 파일을 엑세스 하고 있는 프로세스의 정보를 보여준다.

  2. lsof 경로명 
    지정한 디렉토리를 엑세스 하고 있는 프로세스의 정보를 보여준다.

  3. lsof -i 
    모든 네트워크에 연결되어 있는 프로세스와 파일의 정보를 보여준다. 
    ex)lsof -iTCP // TCP에 연결되어있는 프로세스와 포트의 정보를 보여준다.

  4. lsof -p 프로세스ID 
    지정한 프로세스와 고나련된 프로세스와 파일의 정보를 보여준다.

  5. 해킹추적 시나리오 
    $ lsof -i // 기본포트연것을 확인한다. 
    $ lsof -p // 프로세스를 분석한다. 
    $ lsof /home/홈페이지 디렉토리 // 특정디렉토리에 있는 프로세스 검사 
    $ lsof /tmp // 임시파일 관련 프로세스 분석 
    $ lsof /dev // 정규 해킹 디렉토리 분석


Posted by 빨강토끼
,

맥북에 이것저것 깔았다 지우다 보니 finder의 다음으로 열기(Open with) 항목이 이런저런 이유로 복잡해졌다(중복된 어플, 지워진 어플)

인터넷을 검색해 보니 이게 제일 간단한 방법 같았다.

http://www.clien.net/cs2/bbs/board.php?bo_table=cm_mac&wr_id=575678

$ /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user


Posted by 빨강토끼
,

이 간단한 insert sort가 어제 커뮤니티 행사 이벤트때엔 생각이 잘 안나서 해맸다.

C 도 그렇고 기본적인 알고리즘은 항상 반복해서 봐둬야겠다.

#include <stdio.h>

int printArr(int* arr){  
    for (int k = 0; k < 6; ++k) {
        printf("%d",arr[k]);
    }
    printf("\n");
}
int main() {  
    int i=0 ;
    int j=0;
    int arrays[]  = {5,2,4,6,1,3};

    printf("hello : ");
    printArr(arrays);
    for( i = 1 ; i< 6 ; i++)
    {

        int offset = arrays[i];
        printf("offset : %d\n", offset);
        for(j = i-1; j >=0 ;j--)
        {
            printf("comp : %d , %d\n", arrays[j], offset);
            if ( arrays[j] > offset)
            {
                arrays[j+1] = arrays[j];

            }
            else{
                break;
            }

        }
        arrays[j+1] = offset;

        printArr(arrays);


    }

    for (int k = 0; k < 6; ++k) {
        printf("%d",arrays[k]);

    }
    return 0;
}


Posted by 빨강토끼
,

SpringBoot를 사용하는데 요청하는 기존 레거시 시스템이 한글 인코딩을 EUC-KR로 보내고 있다.

한글처리가 잘안되서 검색해보니 http://theeye.pe.kr/archives/2206 
라는 글을 발견하였다.

그런데도 잘 안되었다.

그런데 이것 저것 조금더 수정해보니 된다. ㅎ

주요한것은 
public Filter characterEncodingFilter() -> public CharacterEncodingFilter characterEncodingFilter(
로 바꾸었다.

참조 http://emflant.tistory.com/97

Posted by 빨강토끼
,

jvm을 사용하는 R 패키지를 사용하려고 할때 
아래와 같은 에러메시지가 나오면서 JVM을 Load 하지 못할 수 있습니다.

JavaVM: requested Java version ((null)) not available. Using Java at "" instead.  
JavaVM: Failed to load JVM: /bundle/Libraries/libserver.dylib  
JavaVM FATAL: Failed to load the jvm library.  
Error : .onLoad failed in loadNamespace() for 'xlsx', details:  
  call: .jinit()
  error: JNI_GetCreatedJavaVMs returned -1

이럴때는 먼저 터미널 창에서 
$ sudo R CMD javareconf

그리고 R창에서 
>install.packages("rJava", type='source')

라고 해보시면 될겁니다.

http://stackoverflow.com/questions/35179151/cannot-load-r-xlsx-package-on-mac-os-10-11

Posted by 빨강토끼
,

Thrift는 페이스북이 개발한 규모 가변적인(scalable) 이종 언어 서비스 개발을 위한 소프트웨어 프레임워크이다.

Thrift을 이용하는 목적은 다양한 언어를 사용하여 개발한 소프트웨어를 쉽게 결합(통신)하기 위함이다.

Apache에서 제공하는 Thrift 는 다양한 플랫폼간에 매우 편리하게 사용할 수 있는 통합 RPC환경을 제공한다.

Thrift는 쉽게 다른 언어간 RPC 통신을 지원한다고 생각하시면 될지도.....

Thrift 스크립트를 한번 작성해 놓으면 다양한 언어에서 사용될 수 있는 코드를 자동으로 생성할 수 있습니다.

.thrift란 파일을 생성하고 Thrift compiler로 이 파일을 컴파일하면 C++이나 Java등 여러 언어에서 사용할 수 있는 인터페이스를 자동으로 생성해 준다. 이 인터페이스를 사용해 RPC(Remote Procedure Call) 통신을 한다..

  • 서블릿 제공(org.apache.thrift.server.TServlet)
  • 멀티쓰레드 지원 (org.apache.thrift.server.ThreadPoolServer : worker thread 지정)
  • Async 지원 (org.apache.thrift.server. TNonblockingServer : single threaded)
  • Multi-thread Half-Sync/Half-Async지원 : org.apache.thrift.server. THsHaServer
  • Exception을 제공 (Google Protocol Buffer에는 없는 기능)
  • Set, Map 지원 (Google Protocol Buffer에는 없는 기능)

https://thrift.apache.org/ 
http://coreawin.tistory.com/245 
http://mwmw7.tistory.com/311 
http://theeye.pe.kr/archives/2063 
http://knight76.tistory.com/1427 
http://rocksea.tistory.com/100

Posted by 빨강토끼
,