Map이란?

map은 스트림 내부의 요소 하나하나에 접근해서 제가 파라미터로 넣어준 함수를 실행한 뒤 최종연산에서 지정한 형식으로 반환해주는 메서드 입니다.

   List<Person> people = Arrays.asList(
                new Person("personA", 24),
                new Person("personB", 26),
                new Person("personC", 28),
                new Person("personD", 30)
        );

위와 같은 리스트를 예시로 만들어보겠습니다.

List<String> nameList = people.stream()
                .map(person -> person.getName())
                .collect(Collectors.toList());

map 메서드 내부를 보면 람다 표현식이 인자로 들어간 것을 알 수 있습니다.

람다 표현식은

  1. people 리스트의 Person 객체 하나하나에 접근한다.
  2. getName 메서드를 통해 name값을 얻는다.
  3. name값들을 포함하는 list를 최종적으로 만들어서 반환한다.

라는 과정을 나타냅니다.

스트림을 쓰지 않을때는 for문을 사용해서 요소 하나하나에 접근해야 했지만, map이 반복문의 역할을 대신해주는 것입니다.

nameList = [personA, personB, personC, personD]

결과를 출력했을때 정상적으로 name값들로 만들어진 리스트가 반환된 것을 알 수 있습니다.

flatMap이란?

map에 대해서는 간략하게 알아봤는데, flatMap은 어떤 기능을 가지고 있을까요? flatMap은 스트림 평면화라는 이름으로도 불립니다. flatMap은 예시를 먼저 보는것이 이해하기 쉽기 때문에 아래의 코드를 한번 보겠습니다.

animal = ["cat","dog"]

위의 리스트에 스트림을 적용하여 cat과 dog의 철자 하나하나를 분리해서 새로운 리스트로 만드는 작업을 진행해보겠습니다.

원하는 결과  = [ "c", "a", "t", "d", "o", "g" ]

먼저 map을 사용해서 철자들을 분리해보겠습니다.

List<String[]> results = animals.stream().map(animal -> animal.split(""))
                                .collect(Collectors.toList());

분명 split 메서드를 이용하여 철자를 모두 분리했는데 반환값 타입을 보면 List<String[]>이 나온것을 알 수 있습니다.

[  [  "c", "a", "t"  ] , [ "d", "o", "g" ]  ]

즉, 위의 그림과 같이 animals 리스트 내부에서 각각의 요소별로 리스트을 중복으로 만들었다고 할 수 있습니다. 우리가 원하는 것은 리스트가 중복되는 것이 아니라 하나의 스트림에 철자 하나하나가 다 들어가는 것입니다. 이때 사용되는것이 flatMap, 다시 말해 중복된 스트림을 1차원으로 평면화 시키는 메서드입니다.

List<String> results = animals.stream().map(animal -> animal.split(""))
        .flatMap(Arrays::stream)
        .collect(Collectors.toList());

여기서 flatMap 내부의 Arrays::stream은 배열을 스트림으로 변환해주는 메서드 참조 표현입니다. flatMap을 사용하면 각각의 String 리스트를 스트림으로 만드는 것이 아니라, String 리스트를 감싸고 있는 더 큰 스트림의 컨텐츠, 즉 구성 요소로 만들어 줄 수 있습니다.

results = [c, a, t, d, o, g]

이처럼 flatMap을 사용하면 중복 구조로 되어있는 리스트를 하나의 스트림처럼 다룰 수 있습니다.

'JAVA > Java' 카테고리의 다른 글

Stream.reduce()  (1) 2024.07.15
LocalDate (LocalDate to Date, Date to LocalDate)  (0) 2023.08.24
[RegExp] 전화번호, 휴대폰번호, 주민번호 정규식  (0) 2021.09.10

1. Stream.reduce()

Stream.reduce(accumulator) 함수는 Stream의 요소들을 하나의 데이터로 만드는 작업을 수행합니다.

예를 들어, Stream에서 1부터 10까지 숫자가 전달될 때, 이 값을 모두 합하여 55의 결과가 리턴되도록 만들 수 있습니다. 여기서 연산을 수행하는 부분은 accumulator 함수이며, 직접 구현해서 인자로 전달해야 합니다.

아래는 reduce()를 사용하여 Stream에서 전달되는 요소들의 숫자를 모두 합하는 예제입니다.

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Optional<Integer> sum = numbers.reduce((x, y) -> x + y);
sum.ifPresent(s -> System.out.println("sum: " + s));

Output:

sum: 55

위의 예제를 설명하면서 reduce()의 동작 방식에 대해서 소개하겠습니다.

reduce()는 인자로 BinaryOperator 객체를 받는데, BinaryOperator는 T 타입의 인자 두개를 받고 T 타입의 객체를 리턴하는 함수형 인터페이스입니다.

BinaryOperator는 (total, n) -> total + n와 같은 형식으로 인자가 전달되는데요. Stream의 1이 전달될 때, total(0) + n(1) = 1와 같이 계산되고, 여기서 리턴되는 1이 다음에 Stream에서 2가 전달될 때 total로 전달됩니다. 따라서, total(1) + n(2) = 3이 됩니다.

다시 정리하면 아래와 같이 연산되면서, 마지막에는 1에서 10까지의 숫자를 더한 55가 리턴됩니다.

  • total(0) + n(1) = 1
  • total(1) + n(2) = 3
  • total(3) + n(3) = 6
  • total(6) + n(4) = 10
  • total(10) + n(5) = 15
  • total(15) + n(6) = 21
  • total(21) + n(7) = 28
  • total(28) + n(8) = 36
  • total(36) + n(9) = 45
  • total(45) + n(10) = 55

1.1 메소드 레퍼런스로 구현

(x, y) -> x + y와 같이 합을 계산하는 함수는, JDK에서 Integer.sum(a, b) 라는 기본 함수를 제공합니다.

여기서 메소드 레퍼런스를 이용하면, Integer::sum 처럼 더 짧은 코드로 동일한 결과를 리턴하는 코드를 구현할 수 있습니다.

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Optional<Integer> sum = numbers.reduce(Integer::sum);
sum.ifPresent(s -> System.out.println("sum: " + s));

2. 초기값이 있는 Stream.reduce()

위의 예제에서는 total의 초기 값이 0이였습니다.

하지만 Stream.reduce(init, accumulator) 처럼 초기 값을 인자로 전달할 수 있습니다.

위의 예제에서 초기 값이 10으로 설정하면, '10 + 1 + 2 + 3... 10'과 같이 연산을 합니다.

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = numbers.reduce(10, (total, n) -> total + n);
System.out.println("sum: " + sum);

Output:

sum: 65

3. reduce()의 병렬 처리

Stream.parallel()은 Stream 연산을 병렬 처리로 수행하도록 합니다. 즉, parallel()과 함께 reduce()를 사용하면 순차적으로 연산을 수행하지 않고 여러개의 연산을 동시에 진행하고, 그 작업들을 다시 병합하여 최종적으로 1개의 결과를 생성합니다.

예를 들어, (1 + 2) + (3 + 4) + ... + (9 + 10) 처럼 두개씩 묶어서 먼저 계산하고, 그 결과들을 다시 계산할 수 있습니다.

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = numbers.parallel().reduce(0, (total, n) -> total + n);
System.out.println("sum: " + sum);

Output:

sum: 55

하지만 빼기 연산의 경우 병렬처리는 순차적인 처리(병렬이 아닌)와 결과가 다릅니다. 아래 코드를 실행해보면 -55가 아니라 -5가 리턴됩니다. 결과가 다른 이유는 (1 - 2) - (3 - 4) - ... - (9 - 10) 처럼 연산이 수행되면서 순차적으로 연산하는 것과 결과가 달라지기 때문입니다.

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = numbers.parallel().reduce(0, (total, n) -> total - n);
System.out.println("sum: " + sum);

Output:

sum: -5

병렬 처리 과정에서 reduce()를 사용할 때는 위와 같은 문제가 없는지 확인을 해야 합니다.

4. 병렬 처리에서 reduce()는 순차적으로 처리

병렬처리에서 연산 순서에 따라 발생하는 문제를 해결하기 위해, 아래 예제와 같이 다른 규칙을 추가할 수 있습니다.

위의 예제와 비교해보면 (total1, total2) -> total1 + total2가 추가되었는데, 병렬로 처리된 결과들의 관계를 나타냅니다. 다시 설명하면, 첫번째 연산과 두번째 연산은 합해야 한다는 규칙을 추가한 것인데요. 이렇게 규칙을 추가하면, 첫번째 연산의 결과가 다음 연산에 영향을 주기 때문에 reduce()는 작업을 나눠서 처리할 수 없게 됩니다.

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = numbers.reduce(0,
        (total, n) -> total - n,
        (total1, total2) -> total1 + total2);
System.out.println("sum: " + sum);

Output:

sum: -55

LocalDate Java version 8 이상만 가능

개념 : 로컬 날짜 클래스로 날짜 정보만 필요할 때 사용

 

LocalDate <->  Date 변환

private final Function<Date, LocalDate> convertDateToLocalDate
date -> date.toInstant().atZone(ZONE_SEOUL).toLocalDate();

private final Function<LocalDateTime, Date> convertLocalDateTimeToDate
localDateTime -> Date.from(localDateTime.atZone(ZONE_SEOUL).toInstant());

LocalDate localDate = convertDateToLocalDate.apply(dateType);

Date date = convertLocalDateTimeToDate.apply(date.atTime(LocalTime.MIN))

 

'JAVA > Java' 카테고리의 다른 글

Stream.map() / Stream.flatMap()  (0) 2024.07.15
Stream.reduce()  (1) 2024.07.15
[RegExp] 전화번호, 휴대폰번호, 주민번호 정규식  (0) 2021.09.10

휴대전화 번호 : 01(?:0|1|[6-9])[.-]?(\d{3}|\d{4})[.-]?(\d{4})
전화번호 : 0[2-7][0-5]?[.-]?(\d{2}|\d{3}|\d{4})[.-]?(\d{4})
주민번호 : (?:[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[1,2][0-9]|3[0,1]))[-]?[1-4][0-9]{6}

 

 

'JAVA > Java' 카테고리의 다른 글

Stream.map() / Stream.flatMap()  (0) 2024.07.15
Stream.reduce()  (1) 2024.07.15
LocalDate (LocalDate to Date, Date to LocalDate)  (0) 2023.08.24

pom.xml 파일에서 아래와 같은 오류가 발생시..

마지막 업데이트 삭제 후 upadte.

 

failure to transfer org.apache.maven:maven-core:pom:2.0.6 from https://repo1.maven.org/maven2/ was cached in the local repository, resolution will not be reattempted until the update interval of central.mirror has elapsed or updates are for

windows 

> cd %userprofile%\.m2\repository

> for /r %i in (*.lastUpdated) do del %i

1. Eclipse IDE 다운로드

www.eclipse.org -> Download

클릭하여 eclipse-inst-win64.exe 파일 다운로드

다운로드 받은 파일은 실행하여 Enterprise java Developers 선택하여 설치

 

2. 설치된 Eclipse 실행하여 Spring Boot 설치

Help - Eclipse Marketplace... 선택

Spring 검색하여 Spring Tools 4  - for Spring Boot 설치

3. File - New - Other에서 Spring Boot 항목 확인

 

'JAVA > Spring' 카테고리의 다른 글

[Spring] SiteMesh 설정 방법  (0) 2019.03.27
스프링 모듈 목록  (0) 2019.03.21
Eclipse에서 Spring Project 설정 (Maven)  (0) 2019.03.21

1. Jar File Download

http://wiki.sitemesh.org/wiki/display/sitemesh/Download

jar 다운로드. (테스트 버전 sitemesh-2.4.2.jar)


** Maven dependency 추가 

<!-- sitemesh -->

<dependency>

<groupId>opensymphony</groupId>

<artifactId>sitemesh</artifactId>

<version>2.4.2</version>

</dependency>



2.필터설정 (web.xml)

- filter를 설정하여 요청받은 url을 가로채기 위해 web.xml에 아래 설정을 추가한다.

(모든 url에 적용되도록 설정하였다)

<!-- sitemesh -->

 <filter>

  <filter-name>sitemesh</filter-name>

  <filter-class>

   com.opensymphony.module.sitemesh.filter.PageFilter

  </filter-class>

 </filter>

 <filter-mapping>

  <filter-name>sitemesh</filter-name>

  <url-pattern>/*</url-pattern>

 </filter-mapping>

 <!-- // sitemesh -->


3.레이아웃 설정파일 추가 

WEB-INF 하위에 sitemesh.xml과 decorators.xml 을 추가.


4. sitemesh.xml 

샘플소스에 있는 sitemesh.xml을 그대로 적용.


<?xml version="1.0" encoding="UTF-8"?>

<sitemesh>

<!--decorator 결정 -->

<property name="decorators-file" value="/WEB-INF/decorators.xml" />

<excludes file="${decorators-file}" />


<!--parser를 설정:해당 페이지의 content-type에 따라 데코레이터 결정 -->

<page-parsers>

<parser content-type="text/html"

class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />

<parser content-type="text/html;charset=UTF-8"

class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />

</page-parsers>


<decorator-mappers>

<mapper

class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper">

<param name="decorator" value="printable" />

<param name="parameter.name" value="printable" />

<param name="parameter.value" value="true" />

</mapper>


<mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">

<param name="property" value="meta.decorator" />

</mapper>


<!-- mapper결정 : 설정파일 사용하여 decorator정하기 -->

<mapper

class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">

<param name="config" value="${decorators-file}" />

</mapper>

</decorator-mappers>

</sitemesh>


5. decorators.xml

header, footer 추가.


<?xml version="1.0" encoding="UTF-8"?>

 <!-- Default Diretory 설정 footer, header 등 jsp파일 위치 -->

 <decorators defaultdir="/WEB-INF/views/decorators">

 <decorator name="_sidebar" page="sidebar.jsp" />

 <decorator name="_header" page="header.jsp" />

 <decorator name="_footer" page="footer.jsp" /> 

</decorators>


6. 적용 예제

<body>

<div id="wrap">

 <div id="header">

       <page:applyDecorator name="_header" />

 </div><hr /><!--end header-->

 <div id="body">

  <div id="sidebar">

   <page:applyDecorator name="_sidebar" />

  </div>

   <decorator:title />

  <decorator:body />

 </div><!-- end body -->

 <div id="footer">

  <page:applyDecorator name="_footer" />

 </div><!-- end footer -->

</div><!-- end wrap -->

</body>


decorators.xml에서 설정한 _header, _sidebar, _footer 파일 내용이 페이지의 지정된 위치에 삽입된다.




'JAVA > Spring' 카테고리의 다른 글

[Spring] Eclipse 설치 및 Spring Boot 설정  (0) 2019.04.15
스프링 모듈 목록  (0) 2019.03.21
Eclipse에서 Spring Project 설정 (Maven)  (0) 2019.03.21
** 스프링 모듈 목록

모듈명

 설명

 core

DI 기능을 비롯한 프레임워크의 기반을 제공한다. 

 beans

BeanFactory 인터페이스를 통해 구현된다.

 expression

객체에 접근하고 객체를 조작하기 위한 표현 언어를 제공한다. JSP 2.1규약에 명시된 통합 EL을 확장하였다

 context

spring-core와 spring-beans 모듈을 확장해서 국제화, 이벤트 처리, 리소스 로딩, 서블릿 컨테이너를 위한 컨텍스트 생성 등의 기능을 추가로 제공한다. Application Context 인터페이스를 통해 구현된다. 

 context.support

Ehcache, 메일, 스케줄링, UI의 Velocity 지원 기능을 제공한다. 

 aop

AOP Alliance에 호환되는 AOP구현을 제공한다.

 aspects

AspectJ와의 통합을 제공한다. 

 web

파일 업로드, Locale 처리 등 웹을 위한 통합 기능을 제공한다.

또한 원격 지원 기능중 웹 관련 기능을 제공한다. 

 web.servlet

스프링 MVC를 제공한다. JSP, Velocity에 대한 뷰 연동을 지원한다. 

 web.struts

스프링과 스트러츠 연동 기능을 제공한다. 

 web.portlet

포틀릿 환경에서 사용하는 MVC 구현을 제공한다. 

 transaction

AOP를 이용한 선언적 트랜잭션 관리 및 코드를 이용한 트랜잭션 관리 기능을 제공한다. 

 jdbc

JDBC 프로그래밍을 위한 추상 레이어를 제공한다. JDBC 템플릿을 제공함으로써 

간결한 코드로 JDBC 프로그래밍을 할 수 있게 돕는다.

 orm

하이버네이트, JPA, iBatis, JDO 등 ORM API를 위한 통합 레이어를 제공한다.

스프링이 제공하는 트랜잭션 관리와의 연동을 지원한다. 

 oxm

객체와 XML 사이의 매핑을 처리하기 위한 추상 레이어를 제공한다.

JAXB, Castor, XMLBeans, JiBX, XStream과의 연동을 지원한다. 

 jms

JMS의 메시지를 생성하고 수신하는 기능을 제공한다. 

 test

JUnit이나 TestNG를 이용한 스프링 컴포넌트의 테스트를 지원한다.

 instrument

Instrumentation 지원 클래스를 제공한다.

 instrument.tomcat

톰캣 서버를 위한 Instrumentation 지원 클래스를 제공한다. 

 asm

ASM 라이브러리를 재패키징 한 모듈 

 



 

출처 

최범균 : Spring 3.0 프로그래밍

출처 토비의 스프링 프레임워크 3.1 부록 A

스프링 모듈 목록스프링 모듈 목록스프링 모듈 목록스프링 모듈 목록스프링 모듈 목록스프링 모듈 목록

'JAVA > Spring' 카테고리의 다른 글

[Spring] Eclipse 설치 및 Spring Boot 설정  (0) 2019.04.15
[Spring] SiteMesh 설정 방법  (0) 2019.03.27
Eclipse에서 Spring Project 설정 (Maven)  (0) 2019.03.21

1. File-New-Other-Dynamic Web Project 생성



2. Project에서 우클릭 - Configure - Convert to Maven Project



3. Resource Directory 생성



4. Spring 라이브러리 pom.xml 파일에 설정






'JAVA > Spring' 카테고리의 다른 글

[Spring] Eclipse 설치 및 Spring Boot 설정  (0) 2019.04.15
[Spring] SiteMesh 설정 방법  (0) 2019.03.27
스프링 모듈 목록  (0) 2019.03.21

[Mybatis] 동적 쿼리 작성 (가변 컬럼)

* 간만에 Spring 프레임웍을 이용하여 보고서 페이지를 개발 하던중

   가변컬럼 조회 쿼리를 개발하게 되었음

.Net 만 하다가 다시 Java Web Page개발 하려니;; 익숙치 않다..

mybatis에서 가변 컬럼 동적쿼리 작성한 관련 내용을 정리함.

* 요건은 다음과 같음

1. 다음과 같은 테이블 2개가 있음(대략 중요한 컬럼만..)

 1) 계정 정의된 AcctTable

 2) 회사별 계정 금액이 저장된 AmtTable

 3) 두 테이블의 데이터는 가변적임

AcctTable

 

 AmtTable

 CD_ACCT   NM_ACCT   CD_COMP   NM_ACCT   AMT 
 A   자산   회사A   A              100
 B   유동자산   회사A   B              200
 C   비유동자산   회사A   C              300
 D   자산총계   회사A   D              100
 E   부채총계   회사B   A              200
    회사B   B              300
 회사B   C              100
 회사C   A              200
 회사C   C              300
 회사C   D              400
           ...
* Result

 

-  Acct 테이블의 데이터를 컬럼으로 회사별 계정금액 보고서 작성

- Select절을 가변적으로 설정해야함

 Result   
 CD_COMP   A   B   C   D   E   F   ...
 회사A         100                     100        300             400  ...
 회사B         200                     300        100  ...
 회사C         200        300             400  ...

 

* 쿼리는 다음과 같다.

* foreeach문 사용, 계정정보를 조회하여 List 형태 매개변수로 받음

* cdAcctList 는 Report의 속성으로 List<Object> 타입

 <!-- 보고서 조회 쿼리  -->
 <select id="selectReport" parameterType="Report" resultType="java.util.HashMap" >
        SELECT C.NM_COMP,
             <foreach collection="cdAcctList" item="i" separator="," index="index">    --> index는 0부터 시작함
                    MAX(DECODE(ACCT.CD_ACCT, #{i}, NVL(AMT.AMT, 0))) AS "${index}"   --> 컬럼명은 index로 0, 1, 2, 3 ...
             </foreach>    
        FROM COMP C
        LEFT JOIN ACCTTABLE ACCT ON 1=1
        LEFT JOIN AMTTABLE AMT
        ON C.CD_COMP=AMT.CD_COMP AND ACCT.CD_ACCT = AMT.CD_ACCT
        GROUP BY C.NM_COMP
        ORDER BY C.NM_COMP
 </select>

** #{variable} 과 ${variable}의 차이

    #{variable} : ''을 포함한 값을 반환    ex) variable 이 aaa라면 -> 'aaa'

    ${variable} : 값만 반환

 

** mybatis 동적 SQL 예제 문서

http://mybatis.org/mybatis-3/ko/dynamic-sql.html

'JAVA' 카테고리의 다른 글

Gmail로 SMTP 메일 보내기 설정 (Java Springframework)  (0) 2015.11.05

+ Recent posts