java에 해당하는 글 5

Java Stream

JAVA|2020. 7. 14. 19:34

20.07.16

 

글 작성 방법을 조금 변경하려고 합니다.

업무중 소스를 까보며 혹은 책이나 로컬로 테스트를 하며 하나씩 정리해서 글을 작성하곤 했는데

아무래도 글을 작성하기 위해 쓴 코드들은 대부분 버려지다 보니

아쉬움이 있어서 github에 repo를 하나씩 파서 샘플들을 작성하며 README와 글을 작성하려고 합니다

(README와 글이 동일 할 수도 있고, 조금 더 풀어서 작성할 수 있을수도 있을것 같습니다)

 

해당 글의 Repo는

https://github.com/Meteorkor/Stream-Study

 

Meteorkor/Stream-Study

Contribute to Meteorkor/Stream-Study development by creating an account on GitHub.

github.com

스트림, 데이터의 흐름

  • 배열 또는 컬렉션, 또는 여러개의 조합으로 가공 및 필터링을 수행할 수 있도록 기능 제공

  • for, foreach에 비해 코드 복잡도를 줄일 수 있음

  • 람다를 활용하여 코드의 양을 줄이고 간결하게 표현 가능

  • 간단하게 병렬처리 가능(parallel())

  • primitive의 경우 IntStream이나 LongStream을 사용하지 않는다면, Boxing으로 인해 성능 저하가 발생할 수 있으니 주의 필요

Stream 생성

  • Array, Collection
  • Stream
    • Stream.builder()
    • Stream.of()
    • Stream.empty()
    • Stream.generate()
    • Stream.iterate()
      • (final T seed, final UnaryOperator f)
      • (T seed, Predicate<? super T> hasNext, UnaryOperator next)
        • JDK9
    • Stream.concat()
  • 기본타입(IntStream, LongStream), String, 파일 스트림(BytesReader)
  • 병렬스트림
  • StreamSupport(추후)

가공(transformer)

  • Filtering
  • Mapping
  • Sorting
  • Iterating

결과(terminal)

  • Calculating
  • Reduction
  • Collecting
  • Matching
  • Iterating

주의 사항

  • primitive

    • primitive 타입을 boxed 된 Stream을 사용하게 된다면 boxing unboxing이 반복되어 나타날수 있음
    • 필요에 따라 IntStream, LongStream, DoubleStream 을 잘 구분하여 사용할것
      • mapToInt, mapToLong, mapToDouble 도 마찬가지
  • 병렬 스트림

    • 메인 스레드 혹은 일반 스레드에서 parallel()의 경우 ForkJoinPool.common을 사용
      • ForkJoinPool.commonPool()은 보통 Runtime.getRuntime().availableProcessors() 만큼의 스레드를 가지고 있음
      • 다른 각각 스레드에서 parallel()을 사용하는 경우에도 같은 ForkJoinPool.commonPool() 공유해서 사용하기 때문에 Blocking 작업으로 인해 전체적으로 성능이 떨어질수 있음
        • 방지하기 위해서는 ForkJoinPool을 신규로 만들고 신규로 만든 ForkJoinPool에 submit을 하면 ForkJoinPool.commonPool() 이 아닌 신규로 만든 Pool에서 병렬처리로 동작
  • 파이프라이닝

    • Stream은 하나의 데이터를 파이프라이닝 방식으로 처리
      • {A,B,C}.map(변환1).map(변환2)... 를 수행할때, A,B,C 변환1 을 수행하는것이 아니라 A에 대해 변환1, 변환2, B에 대해 변환1, 변환2 방식으로 동작
        • 물론 병렬의 경우 이 작업들을 서로 다른 스레드에서 처리 할 수 있음
    • 흐름 정의에 따라 처리내용이 수행되지 않을 수 있음
      • {A,B,C}.peek().map().count() 의 경우 peek와 map이 count()에 영향을 주지 않기 때문에 동작하지 않을 수 있음
        • unit-test에서는 동작하지 않았으나 travis-ci에서는 동작하던...
      • {A,B,C}.peek().map() , terminal(결과처리들, calc, reduce, collect 등) 호출이 없을 경우 결국 peek나 map나 의미가 없기 때문에 수행되지 않음

'JAVA' 카테고리의 다른 글

ActiveMQ JDK Version  (0) 2020.09.09
DCL(Double Checked Locking)  (0) 2020.09.08
Java Time  (0) 2020.07.06
SortedQueue...  (0) 2020.07.02
java.util.function 인터페이스  (0) 2019.12.30

댓글()

SortedQueue...

JAVA|2020. 7. 2. 14:05

자바에.. SortedQueue가 있는줄 알았는데...

없다..?;;;

 

"왜 있는줄 알았지?" 하고 찾아보니 SortedQueue는 없지만 SortedSet이 있었다..

역시 툴 자동완성을 자주 쓰다보니..

헤깔렸다보다..(뭐.. 그냥 인터페이지 차이 뿐이니..)

 

다만 한가지 더는 TreeSet은 Queue쪽 인터페이스는 안되고

(하긴 지금 생각해보니 당연한건가.. set이랑 queue랑 조금 의미가 안맞긴하겠다.. 그냥 쌓이는 queue랑 중복 제거하는 set이랑..)

 

의도대로 하려면 Queue queue = new PriorityQueue<>(Comparator)...

Queue queue = new PriorityQueue<>((o1,o2)->o2.cnt-o1.cnt)...

 

그리고 하나더

 

TreeSet은 add한 후 add한 객체를 변경하면 순서가 변경되지 않는다.

PriorityQueue도 그런가? 했는데 테스트 해보니 마찬가지로 동작한다(add할때 순서가 정해지는 가보다..).

 

마지막으로

TreeSet에 add한 객체를 수정해도 순서가 안바뀌긴 하는데

remove를 하고 add하면 당연히 바뀌겠지만..

remove 안하고 add하면 어떻게 될까..?

 

테스트 해보니 결과는 "순서가 바뀌지 않았다"

 

필요한대로 동작하는지

항상 조금씩 유닛테스트를 돌리면서 진행하다보니..

이런 폐해가...

 

 

이런 실수도 실력이니..

다시 실수 안하기 위해 까먹지 않기위해 끄적끄적..

'JAVA' 카테고리의 다른 글

Java Stream  (0) 2020.07.14
Java Time  (0) 2020.07.06
java.util.function 인터페이스  (0) 2019.12.30
JEP 218: Generics over Primitive Types  (0) 2019.12.10
[CompletableFuture][#3] 메소드 정리-1  (0) 2019.09.01

댓글()

reactor Schedulers

JAVA/Spring|2019. 12. 16. 20:47

Mono 혹은 Flux를 다룰때 map 혹은 subscribe 동작들을
subscribeOn()이나 publishOn()을 통해 다른 스레드에서 실행될 수 있도록 위임할수 있는데
인자는 Scheduler를 받습니다.


Spring WebFlux에서 Controller 스레드에서는 blocking 작업을 할수 없도록 되어있기에
필요한 경우에 subscribeOn() 를 사용하여 blocking 작업을 다른 스레드에서 사용할 수 있는데
Scheduler 종류마다 blocking 작업이 가능한 Scheduler가 있고 아닌 Scheduler 가 있습니다.
(non-blocking 스케줄은 블럭킹 작업이 불가능합니다.)





새로 신규로 생성하여 넘길수 있겠지만 Schedulers가 기본적으로 몇가지를 지원합니다.

  • parrallel
    • optimized for fast non-blocking executions
    • 속도 최적, non-blocking
  • single
    • optimized for low-latency one-off executions
    • 스레드 하나를 공유함, non-blocking
  • elastic
    • optimized for longer executions, alternative for blocking tasks where the number of active tasks can grow indefinitely
    • 긴작업에 최적, non-blocking 아님, blocking 작업 가능 스레드, 필요시 무한히 늘어남
  • boundedElastic
    • optimized for longer executions, alternative for blocking tasks where the number of active tasks is capped
    • 긴작업에 최적, non-blocking 아님, blocking 작업 가능 스레드, 정해진 사이즈
  • immediate
    • to run a task on the caller Thread
    • 콜러 스레드에서 실행
  • fromExecutorService
    • 기존 java.util.concurrent.Executors 를 활용

댓글()

JEP 218: Generics over Primitive Types

JAVA|2019. 12. 10. 19:23

이전에

List list = new ArrayList<>();

list.add(3);

int val = list.get(0);

에 대한 질문을 본적이 있습니다.

현재(지금까지 접했던)까지의 Java는 Generic에 primitive인 가 아닌 로 적어야 맞는것

그리고 list.add(3); 에서 auto-boxing 에 대해 언급했었습니다.

그리고 int val = list.get(0); 에서는 un-boxing이 일어나게 되죠

즉, 불필요한 객체가 생성되고 사라집니다.

검색을 하다보니 이부분을 "어쩔수 없다"가 아닌 해결해보려는 프로젝트가 있었습니다.

 

Valhalla 프로젝트

Valhalla 프로젝트에서는 크게 2가지 내용이 있었습니다.(https://openjdk.java.net/projects/valhalla/)

  • Value Types
  • Generic Spcialization(JEP 218)

그중 Generic Spcialization(JEP 218) 가 Generics over Primitive Types 에 다루고 있는 항목이였습니다.
https://openjdk.java.net/jeps/218

 

JEP 218: Generics over Primitive Types

JEP 218: Generics over Primitive Types Summary Extend generic types to support the specialization of generic classes and interfaces over primitive types. Goals Generic type arguments are constrained to extend Object, meaning that they are not compatible wi

openjdk.java.net

JEP(JDK Enhancement Proposal) 내용이기 때문에 언제 이루어질지 알수 없지만

하나씩 하나씩 추가되고 개선될때마다, 코틀린이나 스칼라가 아닌 자바

그 자체로 간편하고 더더욱 효율적인 언어가 될것을 기대한다.

 

 

'JAVA' 카테고리의 다른 글

SortedQueue...  (0) 2020.07.02
java.util.function 인터페이스  (0) 2019.12.30
[CompletableFuture][#3] 메소드 정리-1  (0) 2019.09.01
[Quartz] Trigger  (0) 2019.07.10
[CompletableFuture][#2] staticMethod  (0) 2019.07.09

댓글()

[MyBatis] MyBatis 문법 파서

DB|2019. 5. 29. 19:13

업무상 MyBatis를 그대로 활용하기보다 해당 기능을 녹이고

MyBatis 문법을 가능한 그대로 입력 받기 위해, 그리고 파싱하기위해 

MyBatis 문법을 파악하고 녹일 필요가 있었다.

 

MyBatis은 보통 XML 파일에 작성이 되며 내부 문법도 XML 문서내에 xml 형식으로 입력된다.

 

대략 작성해보면...(parameter랑 다 생략)

ex)

<select id="aaa">

  SELECT ename, empno, dept FROM EMP

  <where>

  <if test="ename !=null">

      ename=#{ename}

  </if>

  </where>

</select>

 

지금 예로는 if element 안에 test라는 attribute가 나온다는걸 알수 있는데

메뉴얼만 보기에는 모든 attribute나 element가 어떤것들이 더 사용되는지

element간에 관계가 어떻게 되는지 파악하기 어렵다

(예를 들어 <select>안에 <where> 가 들어갈수 있는데 <if>안에는 어떤 element가 들어갈 수 있는지)

 

그래서 혹시 xsd(XML Schema Definition, 말그대로 XML의 정의서)이 없을까?

해서 소스를 열어보니 마침 xsd 파일이 존재 했다

 

mybatis/org.apache.ibatis.builder.xml/mybatis-mapper.xsd

 

업무상 문법을 확장할 필요도 있기 때문에 그대로 가져다 사용하진 않았지만

xsd 파일을 통해 element관계가 엮이고 엮여있는것을 확인했고

덕분에 문법(입력할 element) 들을 빠르게 파악할수 있어

mybatis에 대한 파서를 커스텀 하여 만들수 있었다.

 

 

 

 

 

'DB' 카테고리의 다른 글

[DB] 기초부터다시, ACID, CAP  (0) 2020.09.14
GraphQL 끄적끄적  (0) 2020.08.20
기초부터다시, 조인  (0) 2020.08.18
[MongoDB] 해킹된 후 보안 설정 관련  (0) 2019.12.23
DB 스키마를 관리하자  (0) 2018.12.20

댓글()