# BigDecimal의 선언

BigDecimal bigNumber = new BigDecimal("10000.12345");

BigDecimal java.math안에 있으며 위와 같이 선언하시면 됩니다. 특이한 점은 BigDecimal을 초기화하기 위해서는 문

자열을 인자 값으로 넘겨주어야 한다는 점입니다. BigDecimal문자열로 되어 있기 때문입니다.

 

 

# BigDecimal의 사측연산

BigDecimal bigNumber1 = new BigDecimal("100000.12345");
BigDecimal bigNumber2 = new BigDecimal("10000");
						
System.out.println("덧셈(+) :" +bigNumber1.add(bigNumber2));			 // 덧셈(+) :110000.12345
System.out.println("뺄셈(-) :" +bigNumber1.subtract(bigNumber2));		 // 뺄셈(-) :90000.12345
System.out.println("곱셈(*) :" +bigNumber1.multiply(bigNumber2));		 // 곱셈(*) :1000001234.50000
System.out.println("나눗셈(/) :" +bigNumber1.divide(bigNumber2));		// 나눗셈(/) :10.000012345
System.out.println("나머지(%) :" +bigNumber1.remainder(bigNumber2));	// 나머지(%) :0.12345	

 

# BigDecimal의 두 수 비교

BigDecimal bigNumber_down = new BigDecimal("100000.12345");
BigDecimal bigNumber_up = new BigDecimal("1000000.6789");
				
//두 수 비교 compareTo
int compare = bigNumber_down.compareTo(bigNumber_up);
System.out.println(compare);
더보기

-. 같다면                      : 0

-. compartTo(param) 

           param이 크면    : -1

           param이 작으면 : 1

 

programmers.co.kr/learn/courses/30/lessons/43162

 

코딩테스트 연습 - 네트워크

네트워크란 컴퓨터 상호 간에 정보를 교환할 수 있도록 연결된 형태를 의미합니다. 예를 들어, 컴퓨터 A와 컴퓨터 B가 직접적으로 연결되어있고, 컴퓨터 B와 컴퓨터 C가 직접적으로 연결되어 있

programmers.co.kr

DFS 와 BFS 두 가지로 문제를 해결해 봤다.

 

BFS

package eun;

import java.util.*;

public class Solution {
	public static void main(String[] args) {
		int[][] computers  = {{1, 1, 0}, {1, 1, 0}, {0, 0, 1}};
		int n = 3;
		solution(n, computers);
	}
	
	public static int solution(int n, int[][] computers) {
		int answer = 0;
		Queue<Integer> q = new LinkedList<>();
		boolean[] visited = new boolean[n];
		
		// 시작점 for 문
		for (int i=0; i<n; i++) {
			if (!visited[i]) {
				q.add(i);
				
				while(!q.isEmpty()) {
					int cur = q.poll();
					visited[cur] = true;
					
					// 시작점에서 갈 수 있는곳 탐색
					for (int j=0; j<n; j++) {
						if(!visited[j] && computers[cur][j] == 1) q.add(j);
					}
				}
				
				answer++;
			}
		}
		System.out.println(answer);
		return answer;
    }
}

 

DFS

package eun;

public class Eun {
	public static int answer =0;
	public static int[] dx = { 0, 1, 0, -1 };
	public static int[] dy = { 1, 0, -1, 0 };
	public static void main(String[] args) {
		int[][] computers  = {{1, 1, 0}, {1, 1, 0}, {0, 0, 1}};
		//int[][] computers  = {{1, 1, 0}, {1, 1, 1}, {0, 1, 1}};
		int n = 3;
		
		solution(n, computers);
	}
	
	public static int solution(int n, int[][] computers) {
		
        for(int y=0; y<n; y++) {
        	for(int x=0; x<n; x++) {
        		if(computers[y][x] == 1) {
        			dfs(x, y, computers, n);
        			answer++;
        		}
        	}
        }
        System.out.println(answer);
		return answer;
    }
	
	public static void dfs(int x, int y, int[][] computers, int n) {
		computers[y][x] = 0;
		
		for (int i=0; i<4; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			
			if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
			if (computers[ny][nx] == 0) continue;
			dfs(nx, ny, computers, n);
		}
	}
	
}

 

'Algorithm > solution' 카테고리의 다른 글

[프로그래머스 #level2] 조이스틱.java  (0) 2021.02.23
[HASH] 완주하지 못한 선수  (0) 2019.11.02
#2178. 미로탐색  (0) 2018.12.24
#14503. 로봇 청소기  (1) 2018.01.22
#14891. 톱니바퀴  (0) 2018.01.17

programmers.co.kr/learn/courses/30/lessons/42839

 

코딩테스트 연습 - 소수 찾기

한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다. 각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이

programmers.co.kr

완전탐색

 

모든 경우의 수 를 다 따져봐야 하는 문제이다.

 

크게 2가지 스텝으로 나눴다.

    STEP 1) 조합으로 모든 경우의 수 완전 탐색

    STEP 2) 소수 인지 판별

 

1단계에서 중복된 숫자가 나올 수 있는 경우를 제외해 줘야 한다.

    -. 중복 제거를 위해 SET 자료 구조 활용.

    -. 맨 앞이 0인 경우는 제외!

package eun;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

public class Eun {
	private static int count;
	private static TreeSet<String> ts = new TreeSet<>();
	
	public static void main(String[] args) {
		String numbers = "011";
		
		System.out.println(solution(numbers));
	}
	
	private static int solution(String numbers) {
		List<Character> origin = new ArrayList<>();
		List<Character> result = new ArrayList<>();
		int n = numbers.length();
		
		for (int i=0; i<n; i++) {
			origin.add(numbers.charAt(i));
		}
		
		for (int i=1; i<=n; i++) {
			recursion(origin, result, n, i);			
		}
		
		int answer = count;
		return answer;
	}
	
	private static void recursion(List<Character> origin, List<Character> result, int n, int pick) {
		// 탈출
		if (pick == 0) {
			// 0으로 시작하는거 제거
			if (result.get(0) == '0') return;
				
			// result에 담긴 결과 String화
			String strResult = "";
			for (char c : result) {
				strResult += c;
			}
			
			// 중복 되지 않으면
			if( !ts.contains(strResult) ) {
				// 결과에 추가하고
				ts.add(strResult);
				
				// 소수 판별
				if ( isPrime(Integer.parseInt(strResult)) ) {
					System.out.println(strResult);
					count++;
				}
			}
			
		}
		
		for (int i=0; i<n; i++) {
			result.add(origin.remove(i));
			recursion(origin, result, n-1, pick-1);
			origin.add(i, result.remove(result.size() -1));
		}
	}
	
	
	// 소수 판별
	private static boolean isPrime(int n) {
		int sqrt = (int) Math.sqrt(n);
		
		// 2는 소수
		if (n == 2) return true;
		
		// 1 또는 짝수는 소수가 아님
		if (n == 1 || n%2 == 0) return false;
		
		// 제곱근까지만 홀수로 나눠보면 됨
		for (int i=3; i<=sqrt; i +=2) {
			if ( n%i ==0 ) return false;
		}
		
		return true;
	}
}

 

직렬화 객체를 전송가능한 형태로 말아주는걸 의미 (java object to json)

역직렬화 그 데이터들을 다시 자바 객체로 변환해주는 걸 의미 (json to java object)

 

java object to json

ObjectMapper mapper = new ObjectMapper();

String json = mapper.writeValueAsString(data); // java Object -> String
jsonNode = mapper.readTree(json); // String -> jsonNode

 

json to java object

JsonResponse response = doPost(request);
JsonNode getResData = response.getResponseBodyAsJson();

ObjectMapper mapper = new ObjectMapper();

String jsonString = mapper.writeValueAsString(data); // json -> String
postCjmallQnaList = mapper.readValue(jsonString,class); // String -> java Object

 

Dependencies jackson-databind

maven

더보기

<dependency>

    <groupId>com.fasterxml.jackson.core</groupId>

    <artifactId>jackson-databind</artifactId>

    <version>2.11.0</version>

</dependency>

gradle

더보기

mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind

compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.11.0'

 

참고 블로그

 -. pjh3749.tistory.com/281

 -. soulduse.tistory.com/22

문제 링크

 

코딩테스트 연습 - 조이스틱

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다. ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA 조이스틱을 각 방향으로 움직이면 아래와 같습니다. ▲ - 다

programmers.co.kr

그리디(Greedy)

package eun;

// 알파벳은 모두 더하고,
// 이동경로의 최소를 찾는 문제

public class Solution {
	static public int solution(String name) {
        int answer = 0;
        
        int len = name.length();
        
        //최대로 가질 수 있는 min값은 끝까지 가는것
        int min_move = len-1;
        
        for(int i=0; i<len; i++) {
        	answer += Math.min(name.charAt(i)-'A', 'Z'-name.charAt(i)+1);
        	
        	//BEAABA
            //012345
        	
        	//좌우: 연속된 A의 등장에 따라 최소 움직임이 달라진다
        	int next = i+1;// 현재 다음 위치부터
        	//내 다음이 A라면 계속 NEXT++
        	while(next<len && name.charAt(next) == 'A')
        		next++;
        	
        	min_move = Math.min(min_move, i+len-next + i);
        }//for
        
        answer += min_move;
        
        return answer;
    }
	
    
	public static void main(String[] args) {
		System.out.println(solution("BEAABA"));
	}
}

'Algorithm > solution' 카테고리의 다른 글

[프로그래머스 #level3] 네트워크.java  (0) 2021.03.16
[HASH] 완주하지 못한 선수  (0) 2019.11.02
#2178. 미로탐색  (0) 2018.12.24
#14503. 로봇 청소기  (1) 2018.01.22
#14891. 톱니바퀴  (0) 2018.01.17

TCP(Transmission Control Protocol)

간단하게 말하면 데이터 전달 규칙!

ex) A라는 데이터를 보낸다면,
 A-1, A-2, ..., A-10 이런식으로 잘게 나누어 데이터를 전송한다.
잘게 나누어진 것들이 패킷!

데이터를 패킷으로 나누는 기준이 MTU(Maximum Trasmission Unit)
MTU란 패킷의 최대 크기를 나타내는 수치.

-. MTU값이 작으면 패킷수가 많아진다

                   => 패킷이 가지고 있는 공통 header들을 처리하는 양이 늘어나므로 overhead가 늘어나는 문제 발생.
-. MTU값이 크면 패킷수가 줄어들기 때문에 한번에 많은 데이터를 보낼수 있으므로 대량의 데이터를 처리할 때 이점이 있다. 

                   => 하지만 패킷이 훼손되어 오는 경우에는 다시 큰 패킷을 요청해야하는데, 패킷이 큰 만큼 오는데 오랜                         시간이 걸리게 된다.

패킷은 하나의 루트로만 전송되지 않는다. 여러 루트를 통해서 전송이 가능한데 여러 루트마다 도착시간이 달라서 순서가 보장되지 않는다.
데이터를 받는쪽은 A-2,A-10,…, A-1 데이터를 순서에 맞게 A-1,A-2,…,A-10으로 재조립 한다. 순서에맞게 재조립이 가능한 이유는, TCP 방식으로 데이터 전송시 Header가 붙게되는데 Header에 순서에 관한 정보(Sequence Number)가 있기 때문이다.

 

[참고] TCP 헤더


TCP헤더 구조를 보면
Source Port는 송신측의 port 번호를 나타낸다.
Destination Port는 수신측의 port번호를 나타낸다.
CheckSum은 패킷의 훼손여부를 체크하는 역할을 한다.
SYN은 통신을 하는 양측의 Sequence Number를 동기화 하기위해 사용된다.
ACK는 데이터를 잘 받았다는 응답을 전달하기 위해 사용되며 Sequence Number에 + 1을 붙이는 방법을 이용한다.

 

IP(Internet Protocol)

인터넷상에서 사용되는 주소

'자기계발 일지' 카테고리의 다른 글

HTTP/HTTPS 란?  (0) 2021.02.22

 

API 개발을 하게 되면서 요새 무척이나 자주쓰는 용어들이 있다.

그중에 하나가 HTTP 인데... 이번기회에 정리를 함으로써 리마인드 하기로 했다

HTTP(HyperText Transfer Protocol)

HTTP는 인터넷상에서 클라이언트와 서버가 데이터를 주고 받는 방법이다.

Text Transfer라는 단어가 들어간걸 봐서는 둘이서 문자를 서로 주고 받는 것인데, Hyper가 들어가서 인지 글을 주고 받았지만 엄청난 일들이 이루어진다. HTTP 방식이 없었다면 지금 이렇게 글을 쓰고 조회 할 수 있는 이런 일들이 가능했을까?

클라이언트(Client)는 HTTP를 통해 데이터를 서버로 요청(Request)하는 요청자이며, 흔히 크롬, IE, FireFox 같은 웹 브라우저가 그 역할을 한다. 응용 프로그램에서는 Http 요청을 위해 사용하는 라이브러리가 그 역할을 한다.

서버(Server)는 클라이언트가 요청한 데이터를 제공하는 제공자이며 이미지, HTML 파일처럼 파일을 제공하는 서버, 요청 주소에따라 다른 내용을 제공하는 API서버 등 다양하게 있다. HTTP 통신에서는 서버가 제공하는 결과를 응답(Response)이라고 한다.

 

 

HTTP 메시지 구조

요청 메시지와 응답 메시지 구조 첫 줄을빼고는 구조가 똑같다.

HTTP통신을 위해 생성되는 메시지를 뜯어보면 크게 Header Body로 나눌수 있다.

Header는 General Header, Request header, Response Header, Entity header로 나뉜다.

  • General Header : 요청과 응답에서 모두 공통으로 들어가는 Header를 의미한다.
    주요 정보들로 Date (HTTP 메시지 생성 시간), Connection (서버와 클라이언트의 연결옵션), Via(메시지가 어느 중개자를 거쳐서 왔는지), Transfer-Encoding (메시지에 적용된 인코딩 값) 등등이 있다.
  • Request Header : 요청시에만 있는 Header이다.
    주요 정보들로 Host(서버의 호스트명과 포트), User-Agent (브라우저 및 기기 버전 등 요청자에 관한 정보), Referer(요청을 보낸 URL), Accept(클라이언트가 받을 수 있는 미디어 타입), Accept-Encoding(클라이언트가 받을 수 있는 인코딩), Authorization(서버 인증을 위한 정보) 등등이 있다.
  • Response Header : 응답시에만 있는 Header이다.
    주요 정보들로 Server(서버 어플리케이션 이름과 버전), Age(응답이 캐쉬된 시점부터 얼마나 오래 되었는지), Set-Cookie(서버에서 클라이언트에게 설정한 쿠키정보), Allow(서버측에 요청가능한 HTTP 요청방식) 등등이 있다.
  • Entity Header: HTTP메시지의 BODY(본문)에 관한 정보가 있는 Header.
    주요 정보들로 Content-Encoding(본문에 적용된 인코딩), Content-Length(본문의 크기), Content-Type(본문의 응답이 어떤 타입인지), Content-Location(본문이 실제존재하는 위치), Expires(본문이 캐시되어 유효한 시간), Last-Modified(본문이 마지막으로 갱신된 시간), ETag(본문의 고유 태그, 본문이 수정되면 태그 갱신됨) 등등이 있다.

Body는 요청시 전달하는 데이터 내용, 응답시 받는 데이터 내용으로 HTTP 문서 마지막에 들어간다. Body는 요청과 응답에 따라 있을수도 없을수도 있으며 Body가 없으면 Entity Header도 없다.

 

HTTPS

HTTP 통신은 앞서 말한것 처럼 HTTP 메시지(텍스트)를 주고 받으며 통신을 한다. 이 메시지에는 보안 장치가 따로 없다. 누군가 악의적인 목적으로 HTTP 메시지를 통신 중간에 가로채서 HTTP 메시지를 볼 수도 있다. HTTP 메시지는 암호화없이 평문으로 전송되기 때문에 통신을 가로채면 보낸 내용을 쉽게 볼 수 있다.

만약 회원가입을 하는 경우에 이런 일이 발생하면 개인정보는 바로 노출되게 된다. 이를 보완하기위해 나온것이 HTTPS(HyperText Transfer Protocol over Secure Socket Layer)이다. 약자를 보면 Secure라는 단어가 들어가는데, HTTP의 보안적인 단점을 커버한 HTTP 프로토콜의 강화버전이다.

결론만 간단하게 말하면 HTTP 메시지가 암호화 되어 통신을 하게 된다.

 

 

HTTPS통신과정

HTTPS 통신과정을 알기 위해서는 대칭 키,공개 키의 개념을 알아야 한다.

대칭 키(Symmetric Key)는 정보를 암호화하고 복호화를 할때 같은 값을 이용하는 경우에 사용되는 키이다.

예를들어 ABCD라는 문자를 1111이라는 값으로 암호화를 하고
암호화된 문자를 1111이라는 값으로 풀어서 ABCD를 볼 수 있다면
1111이 대칭 키가 되는 것이다.

대칭 키는 암호화, 복호화가 간단한 방법이다. 하지만 대칭 키를 다른 사람이 알게 되면 그 사람도 암호화된 문자를 생성하고 풀 수 있기 때문에 대칭 키가 노출되는 경우에는 보안에 부정적인 영향이 발생 할 수 있다.

공개 키(Public Key) 방식은 암호화에 사용하는 키와 복호화에 사용되는 키를 분리하는 것이다.

암호화를 할때는 공개 키를 이용해 암호화를 하고 복호화를 할 때는 비밀 키(private key)를 이용한다. 이렇게 되면 공개 키가 노출 되더라도 복호화를 위해 필요한 비밀 키를 모르면 복호화를 할 수가 없다.

공개 키 방식은 대칭 키 방식의 보안 문제를 해결한 방법이지만 컴퓨터 자원이 더 많이 들어가는 단점이 있다.

추가로 SSL인증서는 클라이언트가 접속한 서버가 신뢰할수 있는 서버라는걸 입증해 주는 역할을 하고, SSL 통신에 필요한 공개키를 클라이언트에게 제공한다.(서비스 정보 & 공개 키에 관한 내용이 있음.)

CA(Certificate Authority)는 SSL인증서를 보증해주는 외부 기관들이다.

HTTPS 통신 과정을 간단히(??) 정리해보면.

  1. 서버는 CA기관으로 사이트 정보와 공개 키를 전달함.
  2. CA기관에서 해당 사이트를 검증하고 나서 사이트 정보와 공개 키를 인증기관의 개인 키로 암호화 하여 SSL 인증서를 제작함.
  3. 해당 사이트에 SSL인증서를 발급 함.
  4. CA 기관은 브라우저에게 CA기관의 공개 키를 제공함.
  5. 클라이언트가 서버로 접속시, 서버로 random 값과 클라이언트 측에서 사용가능한 암호화 기법을 서버로 전송. (Client Hello)
  6. 서버에서 random 값과 서버에서 처리가능한 암호화(동일한 암호화 알고리즘을 사용하기 위해 협상 하는 단계) 기법과 SSL인증서를을 함께 클라이언트에게 전송. (Server Hello)
  7. 브라우저에 내장된 CA 리스트 정보로 부터 CA가 제공한 공개 키를 이용해 SSL인증서를 복호화 함. 복호화가 성공한다면 인증된 서버임이 확인되고, 공개 키를 클라이언트가 얻게 됨. 서버는 비밀 키를 가지고 있음.
  8. 클라이언트는 클라이언트 측 random 값과 서버로 부터 받은 random 값을이용해서 대칭 키 생성함. 이 대칭 키는 실제 데이터를 주고 받을때 사용됨.
  9. 클라이언트는 SSL인증서 안에있는 공개 키를 이용해 생성한 대칭 키를 암호화 시켜 서버로 전송함. 이때 전송된 내용은 암호화 됨.
  10. 서버는 대칭 키를 비밀 키를 이용해 복호화함. 이제 클라이언트와 서버 모두 대칭 키를 가지고 있음.(5~10번까지의 과정을 handshake라고 함.)
  11. 이후 부터는 클라이언트와 서버는 대칭 키를 이용해 데이터를 암호화, 복호화를 하며 요청과 응답을 처리함.

'자기계발 일지' 카테고리의 다른 글

TCP/IP 정리  (0) 2021.02.22

운영하던 쇼핑몰을 종합쇼핑몰에 제휴하기 위한 API개발을 진행하기 위해 POSTMAN을 사용하게 되었습니다.

 

페이로드 란?

페이로드(payload)는 전송되는 데이터를 의미합니다. 데이터를 전송할 때, 헤더와 메타데이터, 에러 체크 비트 등과 같은 다양한 요소들을 함께 보내어, 데이터 전송의 효율과 안정성을 높히게 됩니다. 이 때, 보내고자 하는 데이터 자체를 의미하는 것이 바로 페이로드입니다. 우리가 택배 배송을 보내고 받을 때, 택배 물건이 페이로드이고, 송장이나 박스, 뾱뾱이와 같은 완충재 등등은 부가적인 것이기 때문에 페이로드가 아닙니다.

추가적으로 위키피디아에 아주 이해하기 좋은 예시가 아래와 같이 나와있어서 첨부합니다.

 

페이로드(payload)라는 단어는 운송업에서 비롯하였는데, 지급(pay)해야 하는 적화물(load)을 의미합니다. 예를 들어, 유조선 트럭이 20톤의 기름을 운반한다면 트럭의 총 무게는 차체, 운전자 등의 무게 때문에 그것보다 더 될 것이다. 이 모든 무게를 운송하는데 비용이 들지만, 고객은 오직 기름의 무게만을 지급(pay)하게 된다. 그래서 ‘pay-load’란 말이 나온 것이다

 

json으로 보는 실제 데이터에서의 payload는 아래의 json에서 “data”입니다. 그 이외의 데이터들은 전부 통신을 하는데 있어 용이하게 해주는 부차적인 정보들입니다.

 

더보기

{ 

    "status" : 

    "from": "localhost", 

    "to": "http://silverbell.com/sbell92/1", 

    "method": "GET", 

    "data":{ "message" : "There is a my Bang!" } 

}

 

REST란 말을 많이 들어봤을거 같아요. API 개발할때 요구사항이 RESTFUL하게 였으니, REST가 뭔지 알아봤습니다.

REST 란 ?

REST  “Representational State Transfer” 의 약자이다. 월드 와이드 웹과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식이다.

REST란, “웹에 존재하는 모든 자원(이미지, 동영상, DB 자원)에 고유한 URI를 부여해 활용하는 것으로, 자원을 정의하고 자원에 대한 주소를 지정하는 방법론을 의미한다고 한다.

이런 REST의 형식을 따른 시스템을 RESTful 이라고 부른다.

HTTP URI 를 통해 자원을 명시하고 HTTP Method를 통해 해당 자원의 대한 CRUD Operation을 적용한다.

 

CRUD Operation , HTTP Method

  1. Create : POST (자원 생성)
  2. Read : GET (자원의 정보 조회)
  3. Update : PUT (자원의 정보 업데이트)
  4. Delete : DELETE (자원 삭제)

 

REQUEST

POSTMAN으로 API의 데이터를 확인할때 2가지를 Request 했습니다. 

  • Request URL : [HTTP Method] URL
  • Request body : Request-payload

저 같은 경우는 개발서버, 운영서버 2가지의 Request URL을 사용했어야 했으므로

URL 부분을 전역변수로 사용했습니다.

 

[참고] POSTMAN 전역변수 사용방법

Environments 탭에 key-value 형식으로 mapping하여,

Send버튼을 눌러 Request를 요청하기전 toggle 버튼으로 url을 변경하였습니다.

 

 

Request를 보내고 Response를 받아오는 화면은 전체적으로 다음과 같습니다.

POSTMAN을 통해 Request하고 Response를 받아오는 화면

 

 

'spring > project' 카테고리의 다른 글

[DB] 테이블 생성하기  (0) 2018.05.21

# chapter 2. 동작 파라미터화 코드 전달하기    

 

-. 동작파라미터화 : 어떻게 실행할 것인지 결정하지 않은 코드 블록

                                이 코드블록은 나중에 프로그램에서 호출. 즉, 코드 블록의 실행은 나중으로 미뤄진다.

    why)) 변화하는 요구사항에 대응하기 위해

    how)) 나중에 실행될 메서드의 인수로 코드블록을 전달할 수 있다.

 

    example) 룸메이트에게 빵, 치즈, 와인등의 식료품을 사달라 부탁

                    작업 수행 메서드 : go 

                    원하는 동작         : go 메서드의 인수

 

[step 1] interfaca 객체를 parameter로 설정

interface ApplePredicate {

    boolean test(Apple a);

}

[step 2] 원하는 조건을 넣어 interface를 구현(implements)하여 클래스 정의

static class AppleRedAndHeavyPredicate implements ApplePredicate {

    @Override

    public boolean test(Apple apple) {

      return apple.getColor() == Color.RED && apple.getWeight() > 150;

    }

}

[step 3] 메서드 사용시 parameter로 구현된 class를 new 로 생성

List<Apple> redAndHeavyApples = filter(inventory, new AppleRedAndHeavyPredicate());

 

=> 이렇게 되면 step2와 같이 로직과 상관없는 소스들이 많아질 수 있다.   

      then, JAVA는 익명클래스를 제공

 

익명클래스 : 클래스의 선언과 인스턴스화를 동시에 수행.

 

익명 클래스를 사용하면 step2step3 단계를 합칠 수 있다.

List<Apple> redAndHeavyApples = filter(inventory, new ApplePredicate() {

    public boolean test(Apple apple) {

        return apple.getColor() == Color.RED && apple.getWeight() > 150;

    }

});

      

가독성이 떨어진다.. 이 부분을 람다로 해결 가능

List<Apple> redAndHeavyApples = 

                        filter(inventory, (Apple apple) -> apple.getColor() == Color.RED && apple.getWeight() > 150 );

 

# chapter 3. 람다 표현식

 

why use)) 동작 파라미터를 이용할 때 익명 클래스 등 판에 박힌 코드를 구현할 필요가 없다.

 

ex1) 커스텀 Comparator 객체

Comparater<Apple> nyWeight = new Comparator<Apple>() {

      public int comparator(Apple a1, Apple a2) {

             ruturn a1.getWeight().comparator(a2.getWeight());

      }

};

 

ex2) 람다 표현식       

Comparater<Apple> nyWeight = (Apple a1, Apple a2) ->  a1.getWeight().comparator(a2.getWeight());

 

    -. (Apple a1, Apple a2)                      : 람다 파라미더

    -. ->                                        : 화살표

    -. a1.getWeight().comparator(a2.getWeight()) : 람다바디

 

함수형 인터페이스 란) 정확히 하나의 추상메서드를 지정하느 인터페이스다. 

 

 

 

#chapter 3. 람다 표현식

 

-. 람다 표현식 : 메서드로 전달할 수 있는 익명함수를 단순화한 것

[example]

Comparator<Apple> byWeight = new Comparator<Apple>() {

    public int compare(Apple a1, Apple a2) {

        return a1.getWeight().compareTo(a2.getWeight());

    }

};

 

[람다 이용]

Comparator<Apple> byWeight = 

    (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

        람다 파라미터   화살표              람다 바디

 

[람다 포멧]

-. (parameters) -> expression

-. (parameters) -> {expression;}

 

-. 함수형 인터페이스  : 정확히 하나의 추상메서드를 지정하는 인터페이스

public interface Comparator<T> {

    boolean test(T t);

}

 

?) 많은 디폴트 메서드가 있더라도 추상 메서드가 오직 하나면 함수형 인터페이스다.

   디포트 메서드 : 인터페이스의 메서드를 구현하지 않은 클래스를

 

@FunctionalInterface 

해당 어노테이션을 쓰면 

 

???) 함수형 인터페이스로 뭘 할 수 있을까?

       람다 표현식으로 함수형 인터페이스의 추상 메서드 구현을 직접 전달할 수 있으므로 전체 표현식을 함수형 인터         페이스의 인스턴스로 취급

 

자바8 설계자들은 java.util.function.* 패키지로 여러가지 새로운 함수형 인터페이스를 제공. 

 

-. Predicate

test 라는 추상 메서드를 정의하며, test는 제네릭형식의 T의 객체를 인수로 받아 불리언을 반환한다.

[java.util.function.Predicate]

       @FunctionalInterface

       public interface Predicate<T> {

             boolean test(T t);

       }

[Predicate 예제]       

       public <T> List<T> filter(List<T> list, Predicate<T> p) {

             List<T> results = new ArrayList<>();

             for (T t:list) {

                    if(p.test(t)) {

                           results.add(t);

                    }

             }

             return results;

       }

       

       Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();

       List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

 

-. Comsumer

accept 라는 추상 메서드를 정의하며, accept는 제네릭형식의 T의 객체를 인수로 받아 void를 반환한다.

[java.util.function.Consumer]

       @FunctionalInterface

       public interface Consumer<T> {

             void accept(T t);

       }

[Comsumer 예제]

       public <T> void foreach(List<T> list, Consumer<T> c) {

             for (T t: list) {

                    c.accept(t);

             }

       }

       

       private void forEach() {

             Arrays.asList(1, 2, 3, 4, 5),

             (Integer i) -> System.out.println(i)

       }

 

-. Function

java.util.function.Function<T, R> 인터페이스는 제네릭 형식 T를 인수로 받아서 제네릭 형식 R객체를 반환하는 추상메서드 apply를 정의한다.

[java.util.function.Function]

       @FunctionalInterface

       public interface Function<T, R> {

             R apply(T t);

       }

[Function 예제]

       public <T,R> List<R> map(List<T> list, Function<T, R> f) {

             List<R> result = new ArrayList<>();

             for (T t: list) {

                    result.add(f.apply(t));

             }      

             return result;

       }

       

       List<Integer> l = map(

                    Arrays.asList("lamdas", "in", "action"),

                    (String s) -> s.length()

       );

 

cf> java의 형식

 

     참조형 : Byte, Integer, Object, List

     기본형 : int, double, byte, char

 

-. 박싱         : 기본형 -> 참조형 으로 형 변환

-. 언박싱     : 참조형 -> 기본형 으로 형 변환

-. 오토박싱 : 박싱과 언박싱이 자유롭게 이뤄짐

 

람다로 함수형 인터페이스의 인스턴스를 만들수 있다.

 

[형식검사 문제] 다음 코드를 컴파일할 수 없는 이유는?

 

Object o = () -> { System.out.println("Eun example"); };

 

(solution)

람다 표현식의 콘텍스트 = Object(대상형식) 이다. 

하지만 Object는 함수형 인터페이스가 아니다.

따라서 ()-> void 형식의 함수 디스크립터를 갖는 Runnable로 대상 형식을 바꿔서 문제를 해결할 수 있다.

 

    sol) Object o = (Runnable) () -> { System.out.println("Eun example"); };

 

(추가) 예를 들어 execute (() -> {})라는 람다 표현식이 있다면 Runnable과 Action의 함수 디스크립터가 같으므로 누구를 가리키는지가 명확하지 않다.

 

public void excute(Runnable runnable) {

    runnable.run();

}

public void excute(Action<T> action) {

    action.act();

}

 

@FunctionlInterface

interface Action {

        void act();

}

 

    sol) execute ( (Action) () -> {})

 

-. 형식추론

자바 컴파일러는 람다표현식이 사용된 콘텍스트(대상 형식)를 이용해서 람다 표현식과 관련된 함수형 인터페이스를 추론한다.

[Comparator 객체 예제]

Comparator<Apple> c = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());    // 형식을 추론하지 않음.

Comparator<Apple> c = (a1, a2) -> a1.getWeight().compareTo(a2.getWeight());                // 형식을 추론함

=> 개발자 스스로 어떤 코드가 가독성을 향상 시킬 수 있는지 결정해야 한다.

 

-. 지역변수 사용

 

람다 캡쳐링 :  람다 표현식에서는 익명 함수가 하는 것처럼 자유변수를 활용할 수 있다.

    cf> 자유변수란) 파라미터로 넘겨진 변수가 아닌 외부에서 정의된 변수

 

[Question]

int portNumber = 1337;

Runnable r = () -> System.out.println(portNumber);        // 컴파일 ERROR 발생

portNumber = 31337;

 

(solution)

2번째 줄에서 컴파일에러 발생,

    why?) 자유변수의 사용에도 약간의 제약이 있다.

 

지역변수는 final로 선언되어 있어야 한다.

 

final int portNumber = 1337;

Runnable r = () -> System.out.println(portNumber);

portNumber = 31337;                                        // 컴파일 ERROR 발생(final 변수를 수정했으므로)

 

 

[자유변수 사용에 제약이 생긴 이유?]

 

(저장공간)

인스턴스변수 => 힙

지역 변수    => 스택

 

람다에서 지역변수에 바로 접근할 수 있다는 가정하에 람다가 스레드에서 실행된다면 변수를 할당한 스레드가 사라져서 변수 할당이 해제되었는데도 람다를 실행하는 스레드에서는

해당 변수에 접근하려 할 수 있다. 따라서 자바 구현에서는 원래 변수에 접근을 허용하는것이 아닌 자유 지역 변수의 복사본을 제공한다. 

따라서 복사본의 값이 바뀌지 않아야 하므로 지역 변수에서는 한 번만 값을 할당해야 한다는 제약이 생긴것이다.

 

-. 메서드 참조

메서드 참조를 사용함으로써 가독성을 높일 수 있고, 간결하게 구현할 수 있다.

[예제]

inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

inventory.sort(comparing(Apple::getWeight));

 => Apple클래스에 정의된 getWeight의 메서드 참조.

 

생성자, 배열 생성자, super 호출 등에 사용할 수 있는 특별한 형식의 메서드 참조도 있다.

 

1) 기존의 메서드 구현을 재활용해서 메서드 참조를 만드는 방법

[예제] List에 포함된 문자열을 대,소문자를 구분하지 않고 정렬하는 프로그램.

 

List<String> str = Arrays.asList("a", "b", "A", "B");

str.sort((s1, s2) -> s1.compareToIgnoreCase(s2));

str.sort(String::compareToIgnoreCase);

 

2) 생성자 참조 (ClassName::new)

Supplier<Apple> c1 = Apple::new;

Apple a1 = c1.get();                                                      // Supplier의 get메서드를 호출해서 새로운 Apple 객체를 만들 수 있다.

 

Function<Integer, Apple> c2 = Apple::new;              // (weight) -> new Apple(weight)

Apple a2 = c2.apply(110);                                            // Function의 get메서드를 호출해서 새로운 Apple 객체를 만들 수 있다. 

 

 

119 ~ 131 페이지 

생성자 참조~ 부터는 다음에 한번 더 보기! (이해가 잘 안감)

 

 

 

 

 

 

 

 

 

 

+ Recent posts