├── AWS ├── 10000_Foot_Overview.md ├── Certificate.md ├── DeployOnAWSServer.md ├── EBS.md ├── S3.md ├── VPC.md └── img │ ├── CachedVolumes.png │ ├── FileGateway.png │ ├── StoredVolumes.png │ ├── TapeGateway.png │ ├── VPC with Public & Private Subnet1.png │ ├── VPC with Public & Private Subnet2.png │ ├── VPC with Public & Private Subnet3.png │ ├── VPC with Public & Private Subnet4.png │ ├── VPC with Public & Private Subnet5.png │ ├── VPC with Public & Private Subnet6.png │ ├── VPC with Public & Private Subnet7.png │ ├── VPCdiagram.png │ └── VPCtransitivePeering.png ├── Algorithm ├── AlgorithmForSmartProgramming │ ├── README.md │ ├── Recursion01-Recursion?.md │ ├── Recursion02-RecursiveThinking.md │ ├── Recursion03-DesigningRecursion.md │ ├── Recursion04-Maze.md │ ├── Recursion05-CountingCells.md │ ├── Recursion06-nQueens.md │ └── Recursion07-PowerSet.md ├── Codewars │ ├── 001-Multiples_of_3or5.md │ ├── 002-Get_the_middle_character.md │ ├── 003-String_repeat.md │ ├── 004-Tribonacci_sequence.md │ ├── 005-Regex_validate_PIN_code.md │ ├── 006-Most_digits.md │ ├── 007-Highest_scoring_word.md │ ├── 008-The_highest_profit_wins.md │ ├── 009-Odd_or_even?.md │ ├── 010-TwoFighters_OneWinner.md │ ├── 011-Find_the_odd_int.md │ ├── 012-Isograms.md │ ├── 013-Count_all_the_sheep.md │ ├── 014-Alternating_split.md │ ├── 015-Square_every_digit.md │ ├── 016-Make_a_function_that_does_arithmetic.md │ ├── 017-Arithmetic_progression.md │ ├── 018-Duplicate_Encoder.md │ ├── 019-Your_order_please.md │ ├── 020-Row_Weights.md │ ├── 021-Maximum_Product.md │ ├── 022-Where_is_my_parent.md │ └── 023-Form_the_minimum.md └── Codility │ ├── BinaryGap.md │ ├── Brackets.md │ ├── CountDiv.md │ ├── CyclicRotation.md │ ├── Distinct.md │ ├── EquiLeader.md │ ├── Fish.md │ ├── FrogJmp.md │ ├── FrogRiverOne.md │ ├── MaxCounters.md │ ├── MaxProductOfThree.md │ ├── MinAvgTwoSlice.md │ ├── MissingInteger.md │ ├── Nesting.md │ ├── NumberOfDiscIntersections.md │ ├── OddOccurrencesInArray.md │ ├── PassingCars.md │ ├── PermCheck.md │ ├── PermMissingElem.md │ ├── StoneWall.md │ ├── TapeEquilibrium.md │ └── Triangle.md ├── Database └── DynamoDB.md ├── ETC ├── Ajax.md ├── Bcrypt.md ├── BreadCrumbs.md ├── CDATA.md ├── HowBrowsersWork.md ├── HowTheWebWorks.md ├── Hugo+Github_Page.md ├── MyBatisGenerator.md ├── OAuth&JWT.md ├── PathVariable_QueryParameter.md ├── RESTful API.md ├── RegEx.md ├── StringUtils.md ├── TemplateEngines.md ├── http.md ├── images │ ├── Connectingthedots.jpg │ ├── JAXB_architecture.gif │ ├── K-009.png │ ├── README.md │ ├── StockInfo.png │ ├── VirtualTopics.png │ ├── activemq │ │ ├── README.md │ │ ├── VirtualTopics.png │ │ ├── activemq_xml_1.png │ │ ├── activemq_xml_2.png │ │ ├── aws_sqs.png │ │ ├── aws_sqs_tv.png │ │ ├── news_hub.png │ │ ├── pubsub_activemq.png │ │ ├── pubsub_amazonmq.png │ │ ├── queue.png │ │ ├── thumbnail.png │ │ ├── topics.png │ │ └── virtual_topic.png │ ├── apply2.png │ ├── books.jpg │ ├── by20182.png │ ├── cmts1.png │ ├── cmts2.png │ ├── cmts3.png │ ├── exampleGist.png │ ├── fb.jpg │ ├── fbf.png │ ├── goqual.png │ ├── jpa_table.png │ ├── jpa_table2.png │ ├── kakao.jpg │ ├── lee.gif │ ├── mydesk.jpg │ ├── myfirstPR.png │ ├── myfirstPR2.png │ ├── myfirstPR3.png │ ├── myfirstPR4.png │ ├── nadal1.jpg │ ├── okky.png │ ├── oracleExpert.png │ ├── planner.png │ ├── planner2.png │ ├── queue.png │ ├── ryanjs.png │ ├── sist.jpg │ └── topics.png ├── mineSweeper.md └── resumeKOR.md ├── Early-Bird ├── 2018-09 │ ├── 2018-09-23.md │ ├── 2018-09-24.md │ ├── 2018-09-25.md │ ├── 2018-09-26.md │ ├── 2018-09-27.md │ ├── 2018-09-28.md │ ├── 2018-09-29.md │ ├── 2018-09-30.md │ └── README.md ├── 2018-10 │ ├── 2018-10-01.md │ ├── 2018-10-02.md │ ├── 2018-10-03.md │ ├── 2018-10-04.md │ ├── 2018-10-05.md │ ├── 2018-10-06.md │ ├── 2018-10-07.md │ ├── 2018-10-08.md │ ├── 2018-10-09.md │ ├── 2018-10-11.md │ ├── 2018-10-12.md │ ├── 2018-10-16.md │ ├── 2018-10-17.md │ ├── 2018-10-18.md │ ├── 2018-10-19.md │ ├── 2018-10-20.md │ ├── 2018-10-23.md │ ├── 2018-10-25.md │ ├── 2018-10-27.md │ ├── 2018-10-30.md │ ├── 2018-10-31.md │ └── README.md ├── 2018-11 │ ├── 2018-11-03.md │ ├── 2018-11-05.md │ ├── 2018-11-06.md │ ├── 2018-11-12.md │ ├── 2018-11-14.md │ ├── 2018-11-18.md │ ├── 2018-11-20.md │ ├── 2018-11-21.md │ ├── 2018-11-22.md │ ├── 2018-11-23.md │ ├── 2018-11-24.md │ ├── 2018-11-26.md │ ├── 2018-11-29.md │ └── README.md └── README.md ├── Git ├── Code_Review_Methods.md ├── GitTips.md ├── Git_Flow.md ├── Submodule.md └── rm_cached.md ├── Go ├── 30minGo │ ├── Function_and_Variable.md │ └── README.md └── HelloWorld.md ├── JPA └── JPA_basic.md ├── Java ├── CallByValue.md ├── CompleatableFuture.md ├── DWR.md ├── IO.md ├── Lombok.md ├── MailSender.md ├── Serialize.md ├── String_Concatenation.md ├── Try-with-resources.md ├── XML_to_Java_Object.md ├── abstract_class.md └── slf4j.md ├── LICENSE ├── Linux ├── Maintaining_Process.md ├── README.md ├── Shell_Script_Study.md └── SysAdminBasics.md ├── Message_Broker └── activemq_virtual_destinations.md ├── Node.js ├── 1_BasicConcepts.md ├── 2_HelloWorld.md └── 3_Express.js.md ├── OS └── OperatingSystemConcepts │ ├── Chapter1 │ └── 1.1_WhatOperatingSystemsDo.md │ ├── Preface.md │ └── README.md ├── README.md ├── SQL ├── OracleExpert.md └── README.md ├── Seminar ├── Google_Mobile_IO_2018.md ├── OpenSWGrandChallenge2018.md └── RedHat_API2.0_BestPractices_Workshop.md ├── Servlet_JSP └── Servlet&JSP.md ├── Spring ├── @Controller.md ├── @ModelAttribute.md ├── @RequestBody.md ├── @RequestParam.md ├── @RestController.md ├── @SessionAttributes.md ├── @Transient.md ├── AOP.md ├── AmazonMQ+SpringBoot.md ├── CRUD │ ├── Controller.java │ └── Service.java ├── Model_ModelMap_ModelAndView.md ├── SpringBootTacademy.md ├── SpringBootTest.md ├── SpringFrameworkCore.md └── TilesPreparer.md └── Tools ├── Eclipse.md └── IntelliJ.md /AWS/img/CachedVolumes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/CachedVolumes.png -------------------------------------------------------------------------------- /AWS/img/FileGateway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/FileGateway.png -------------------------------------------------------------------------------- /AWS/img/StoredVolumes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/StoredVolumes.png -------------------------------------------------------------------------------- /AWS/img/TapeGateway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/TapeGateway.png -------------------------------------------------------------------------------- /AWS/img/VPC with Public & Private Subnet1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPC with Public & Private Subnet1.png -------------------------------------------------------------------------------- /AWS/img/VPC with Public & Private Subnet2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPC with Public & Private Subnet2.png -------------------------------------------------------------------------------- /AWS/img/VPC with Public & Private Subnet3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPC with Public & Private Subnet3.png -------------------------------------------------------------------------------- /AWS/img/VPC with Public & Private Subnet4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPC with Public & Private Subnet4.png -------------------------------------------------------------------------------- /AWS/img/VPC with Public & Private Subnet5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPC with Public & Private Subnet5.png -------------------------------------------------------------------------------- /AWS/img/VPC with Public & Private Subnet6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPC with Public & Private Subnet6.png -------------------------------------------------------------------------------- /AWS/img/VPC with Public & Private Subnet7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPC with Public & Private Subnet7.png -------------------------------------------------------------------------------- /AWS/img/VPCdiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPCdiagram.png -------------------------------------------------------------------------------- /AWS/img/VPCtransitivePeering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/AWS/img/VPCtransitivePeering.png -------------------------------------------------------------------------------- /Algorithm/AlgorithmForSmartProgramming/README.md: -------------------------------------------------------------------------------- 1 | >[Infearn <영리한 프로그래밍을 위한 알고리즘 강좌> - 부경대 권오흠 교수](https://www.inflearn.com/course/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%95%EC%A2%8C/) 2 | 강의를 듣고 정리한 내용 3 | -------------------------------------------------------------------------------- /Algorithm/AlgorithmForSmartProgramming/Recursion01-Recursion?.md: -------------------------------------------------------------------------------- 1 | >[Infearn <영리한 프로그래밍을 위한 알고리즘 강좌> - 부경대 권오흠 교수](https://www.inflearn.com/course/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%95%EC%A2%8C/) 2 | 강의를 듣고 정리한 내용 3 | 4 | # 순환(Recursion) 이란? 5 | - 자기 자신을 호출하는 함수 6 | ~~~ 7 | void func(...) 8 | { 9 | ... 10 | func(...) 11 | ... 12 | } 13 | ~~~ 14 | ## 무한루프에 빠질 수 있으므로, 빠지지 않게하는 구조로 작성해야 한다. 15 | ~~~ 16 | public static void func(int k){ 17 | if(k<=0) ///////// Base case : 적어도 하나의 recursion에 빠지지 않는 경우가 존재해야한다. 18 | return; ///////// 19 | else { 20 | sysout("hello"); 21 | func(k-1); ////////// Recursive case : recursion을 반복하다보면 결국 base case로 수렴해야한다. 22 | } 23 | } 24 | ~~~ 25 | ## Factorial : n! 를 순환으로 구현하기 26 | ~~~java 27 | public static int factorial(int n){ 28 | if (n==0) 29 | return 1; 30 | else 31 | return n*factorial(n-1); 32 | } 33 | ~~~ 34 | ## X^n 을 순환으로 구현하기 35 | ~~~ 36 | public static double power(double x, int n) { 37 | if(n==0) 38 | return 1; 39 | else 40 | return x * power(x,n-1); 41 | } 42 | ~~~ 43 | ## Fibonacci Number 순환으로 구현하기 44 | - Fibonacci Number : F(n) = F(n-1) + F(n-2) 45 | ~~~ 46 | public int fibonacci(int n) { 47 | if (n<2) 48 | return n; 49 | else 50 | return fibonacci(n-1) + fibonacci(n-2); 51 | ~~~ 52 | ## 최대공약수 : Euclid Method 순환으로 구현하기 53 | ~~~ 54 | m>=n 인 두 양의 정수 m과 n에 대해서 m이 n의 배수이면 gcd(m,n)=n 이고, 55 | 그렇지 않으면 gcd(m,n)= gcd(n,m%n)이다. 56 | ~~~ 57 | ~~~ 58 | public static int gcd(int m, int n) { 59 | if (m수학함수 뿐만 아니라 다른 많은 문제들을 recursion으로 해결할 수 있다. 3 | 4 | ## 문자열 길이 계산 5 | ~~~ 6 | if the string is empty 7 | return 0; 8 | else 9 | return 1 plus the length of the string that 10 | excludes the first character; 11 | ~~~ 12 | ~~~java 13 | public static int length(String str) { 14 | if (str.equals("")) 15 | return o; 16 | else 17 | return 1+length(str.substring(1)); 18 | } 19 | ~~~ 20 | 21 | ## 문자열의 프린트 22 | ~~~java 23 | public static void printChars(String str) { 24 | if (str.length()==0) 25 | return; 26 | else { 27 | System.out.print(str.charAt(0)); 28 | printChars(str.substring(1)); 29 | } 30 | } 31 | ~~~ 32 | 33 | ## 문자열을 뒤집어 프린트 34 | ~~~java 35 | public static void printCharsReverse(String str) { 36 | if (str.length() == 0) 37 | return; 38 | else { 39 | printCharsReverse(str.substring(1)); 40 | System.out.print(str.charAt(0)); 41 | } 42 | } 43 | ~~~ 44 | 45 | ## 2진수로 변환하여 출력 46 | - 음이 아닌 정수 n을 이진수로 변환하여 인쇄한다. 47 | ~~~java 48 | public void printInBinary(int n) { 49 | if (n<2) 50 | System.out.print(n); 51 | else { 52 | printInBinary(n/2); ///// n을 2로 나눈 몫을 먼저 2진수로 변환하여 인쇄한 후 53 | System.out.print(n%2); ///// n을 2로 나눈 나머지를 인쇄한다. 54 | } 55 | } 56 | ~~~ 57 | 58 | ## 배열의 합 구하기 59 | ~~~java 60 | public static int sum(int n, int [] data) { 61 | if (n<=0) 62 | return 0; 63 | else 64 | return sum(n-1, data) + data[n-1]; 65 | } 66 | ~~~ 67 | 68 | ## 데이터파일로 부터 n개의 정수 읽어오기 69 | - Scanner in이 참조하는 파일로 부터 n개의 정수를 입력받아 배열 data에 저장한다. 70 | ~~~java 71 | public void readFrom(int n, int [] data, Scanner in) { 72 | if (n==0) 73 | return; 74 | else { 75 | readFrom(n-1, data, in); 76 | data[n-1] = in.nextInt(); 77 | } 78 | } 79 | ~~~ 80 | 81 | ## Recursion vs. Iteration 82 | - 모든 순환함수는 반복문(iteration)으로 변경 가능 83 | - 그 역도 성립한다. 즉, **모든 반복문은 recursion으로 표현 가능** 84 | - 순환함수는 복잡한 알고리즘을 단순하고 알기 쉽게 표현하는 것을 가능하게함 85 | - 하지만 함수 호출에 따른 오버헤드가 있다. (매개변수 전달, Activation Frame 생성 등) 86 | -------------------------------------------------------------------------------- /Algorithm/AlgorithmForSmartProgramming/Recursion04-Maze.md: -------------------------------------------------------------------------------- 1 | # Recursion 응용 - 미로찾기 2 | 3 | ## 1. Recursive Thinking 4 | - 현재 위치에서 출구까지 가는 경로가 있으려면 5 | 1. 현재 위치가 출구이거나 6 | 2. 이웃한 셀들 중 하나에서 현재 위치를 지나지 않고 출구까지 가는 경로가 있거나 7 | 8 | ## 2. Pseudo Code (Decision Problem (답이 yes/no인 문제)) 9 | ~~~java 10 | boolean findPath(x,y) 11 | if (x,y) is the exit 12 | return true; 13 | else 14 | for each neighbouring cell (x',y') of (x,y) do 15 | if (x', y') is on the Pathway 16 | if findePath(x',y') 17 | return true; 18 | return false; 19 | ~~~ 20 | - 위의 코드는 무한루프에 빠질 수 있으므로 아래와 같이 작성한다. 21 | ~~~java 22 | boolean findPath(x,y) 23 | if (x,y) is the exit 24 | return true; 25 | else 26 | mark (x,y) as a visited cell; 27 | for each neighbouring cell (x',y') of (x,y) do 28 | if (x', y') is on the Pathway and not visited 29 | if findePath(x',y') 30 | return true; 31 | return false; 32 | ~~~ 33 | - 아래와 같이 현재 위치를 먼저 확인할 수 있다. 위의 코드와는 취향의 차이이다. 34 | ~~~java 35 | boolean findPath(x,y) 36 | if (x,y) is either on the wall or a visited cell 37 | return false; 38 | else if (x,y) is the exit 39 | return true; 40 | else 41 | mark (x,y) as a visited cell; 42 | for each neighbouring cell (x',y') of (x,y) do 43 | if findPath(x',y') 44 | return true; 45 | return false; 46 | ~~~ 47 | 48 | ## 3. Class Maze 49 | ~~~java 50 | public class Maze { 51 | private static int N=8; 52 | private static int [][] maze = { 53 | {0,0,0,0,0,0,0,1}, 54 | {0,1,1,0,1,1,0,1}, 55 | {0,0,0,1,0,0,0,1}, 56 | {0,1,0,0,1,1,0,0}, 57 | {0,1,1,1,0,0,1,1}, 58 | {0,1,0,0,0,1,0,1}, 59 | {0,0,0,1,0,0,0,1}, 60 | {0,1,1,1,0,1,0,0}, 61 | }; 62 | 63 | private static final int PATHWAY_COLOUR = 0; //white 64 | private static final int WALL_COLOUR = 1; //blue 65 | private static final int BLOCKED_COLOUR = 2; //red 66 | private static final int PATH_COLOUR = 3; //green 67 | 68 | 69 | public static boolean findMazePath(int x, int y) { 70 | if (x<0 || y<0 || x>=N || y>=N) 71 | return false; 72 | else if (maze[x][y] != PATHWAY_COLOUR) 73 | return false; 74 | else if (x==N-1 && y==N-1) { 75 | maze[x][y] = PATH_COLOUR; 76 | return true; 77 | } 78 | else { 79 | maze[x][y] = PATH_COLOUR; 80 | if (findMazePath(x-1,y) || findMazePath(x,y+1) 81 | || findMazePath(x+1,y) || findMazePath(x,y-1) { 82 | return true; 83 | } 84 | maze[x][y] = BLOCKED_COLOUR; //dead end 85 | return false; 86 | } 87 | } 88 | 89 | public static void main(String[] args) { 90 | printMaze(); 91 | findMazePath(0,0); 92 | printMaze(); 93 | } 94 | 95 | } 96 | ~~~ 97 | -------------------------------------------------------------------------------- /Algorithm/AlgorithmForSmartProgramming/Recursion05-CountingCells.md: -------------------------------------------------------------------------------- 1 | # Recursion 응용 - Counting Cells in a Blob 2 | 3 | - 개요 4 | - Binary 이미지 5 | - 각 픽셀은 background pixel이거나 혹은 image pixel 6 | - 서로 연결된 image pixel들의 집합을 blob 이라고 부른다. 7 | - 상하좌우 및 대각 방향으로도 연결된 것으로 간주 8 | 9 | - 입력 10 | - N * N 크기의 2차원 그리드(grid) 11 | - 하나의 좌표 (x,y) 12 | - 출력 13 | - 픽셀 (x,y)가 포함된 blob의 크기 14 | - (x,y)가 어떤 blob에도 속하지 않는 경우에는 0 15 | 16 | ## Recursive Thinking 17 | 18 | ~~~ 19 | 현재 픽셀이 속한 blob의 크기를 카운트하려면 20 | 현재 픽셀이 image color가 아니라면 21 | 0을 반환한다. 22 | 현재 픽셀이 image color라면 23 | 먼저 현재 픽셀을 카운트한다 (count=1) 24 | 현재 픽셀이 중복 카운트되는 것을 방지하기 위해 다른 색으로 칠한다. 25 | 현재 픽셀에 이웃한 모든 픽셀들에 대해서 26 | 그 픽셀이 속한 blob의 크기를 카운트하여 카운터에 더해준다. 27 | 카운터를 반환한다. 28 | ~~~ 29 | 30 | ## 구현 31 | 32 | ~~~java 33 | private static int BACKGROUND_COLOR = 0; 34 | private static int IMAGE_COLOR = 1; 35 | private static int ALREADY_COUNTED = 2; 36 | 37 | public int countCells(int x, int y) { 38 | int result; 39 | if (x<0 || x>=N || y<0 || y>=N) 40 | return 0; 41 | else if (grid[x][y] != IMAGE_COLOR) 42 | return 0; 43 | else { 44 | grid[x][y] = ALREADY_COUNTED; 45 | return 1 + countCells(x-1, y+1) + countCells(x, y+1) 46 | + countCells(x+1, y+1) + countCells(x-1, y) 47 | + countCells(x+1, y) + countCells(x-1, y-1) 48 | + countCells(x, y-1) + countCells(x+1, y-1); 49 | } 50 | } 51 | ~~~ 52 | -------------------------------------------------------------------------------- /Algorithm/AlgorithmForSmartProgramming/Recursion06-nQueens.md: -------------------------------------------------------------------------------- 1 | # Recursion 응용 - N Queens Problem 2 | ![nQueens](https://github.com/namjunemy/TIL/raw/master/Algorithm/img/n_queens_01.png?raw=true) 3 | - 가로 세로 크기가 n인 2차원 체스보드 위에 n개의 말을 놓을 때, 4 | - 각 말의 상하좌우 대각선의 연장선 위에 어떠한 말도 없도록 말을 놓는 문제 5 | 6 | 7 | ## 상태공간 트리 8 | ![상태공간트리](https://github.com/namjunemy/TIL/raw/master/Algorithm/img/n_queens_02.png?raw=true) 9 | - 찾는 해를 포함하는 트리 10 | - 즉 해가 존재한다면 그것은 반드시 이 트리의 어떤 한 노드에 해당한다. 따라서 이 트리를 체계적으로 탐색하면 해를 구할수 있다. 11 | - 하지만 모든 노드를 탐색해야 하는 것은 아니다. 12 | - 해가 될 수 있는 요건을 충족하지 않는 infeasible 한 노드들의 하위 노드는 탐색할 필요가 없다. 13 | 14 | ## Backtracking (되추적 기법) 15 | - 상태공간 트리를 **깊이 우선 방식**으로 탐색하여 해를 찾는 알고리즘 16 | - Recursion을 사용하거나 Stack을 사용할 수 있지만, 대부분 recursion으로 구현한다. 17 | 18 | ## Design Recursion 19 | ~~~ 20 | return-type queens( arguments) //매개변수는 내가 현재 트리의 어떤 노드에 있는지를 지정해야 한다. 21 | { 22 | if non-promising(꽝) 23 | report failure and return; 24 | else if success 25 | report answer and return; 26 | else 27 | visit children recursively; 28 | } 29 | ~~~ 30 | ~~~java 31 | int[] cols = new int [N+1]; 32 | boolean queens( int level ) // 전역변수 cols와 매개변수 level로 노드의 현재 위치를 제공한다. 33 | { 34 | if (!promising(level)) 35 | return false; 36 | else if (level == N) { 37 | for (int i=1; i<=N; i++) 38 | System.out.println("(" + i + ", " + cols[i] + ")"); 39 | return true; 40 | } 41 | for (int i=1; i<=N; i++) { 42 | cols[level+1] = i; 43 | if (queens(level+1)) 44 | return true; 45 | } 46 | return false; 47 | } 48 | ~~~ 49 | 50 | ## Promising Test 51 | 52 | ~~~java 53 | boolean promising( int level) 54 | { 55 | for (int i=1; i멱집합 : 어떤 집합의 모든 부분집합의 집합 3 | 4 | - {a,b,c,d,e,f}의 모든 부분집합을 나열하려면 5 | - a를 제외한 {b,c,d,e,f}의 모든 부분집합들을 나열하고 6 | - {b,c,d,e,f}의 모든 부분집합에 {a}를 추가한 집합들을 나열하는데, 그럴려면 7 | - {c,d,e,f}의 모든 부분집합에 {a}를 추가한 집합들을 나열하고 8 | - {c,d,e,f}의 모든 부분집합에 {a,b}를 추가한 집합들을 나열한다. 그럴려면 ...(생략) 9 | 10 | ## Powerset 11 | ~~~ 12 | powerSet(P,S) // Mission: S의 멱집합을 구한 후 각가에 집합 P를 합집합하여 출력하라 13 | if S is an empty set 14 | print P; 15 | else 16 | let t be the first element of S; 17 | powerSet(P, S-{t}); 18 | powerSet(P U {t}, S-{t}); 19 | ~~~ 20 | 21 | ~~~java 22 | private static char data[] = {'a','b','c','d','e','f'}; 23 | private static int n=data.length; 24 | private static boolean [] include = new boolean [n]; 25 | 26 | public static void powerSet(int k) { 27 | if (k==n) { 28 | for (int i=0; i6kyu 3 | >solved with Java 4 | >http://www.codewars.com/kata/multiples-of-3-or-5/java 5 | 6 | ## Instructions 7 | >If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. 8 | >Finish the solution so that it returns the sum of all the multiples of 3 or 5 below the number passed in. 9 | >Note: If the number is a multiple of both 3 and 5, only count it once. 10 | 11 | # My Solution 12 | ~~~java 13 | public class Solution { 14 | 15 | public int solution(int number) { 16 | //TODO: Code stuff here 17 | 18 | int x = 0; 19 | 20 | for(int i=0; iPassed 33 | >Time: 2192ms 34 | 35 | ## Best Practice 36 | ~~~java 37 | public class Solution { 38 | 39 | public int solution(int number) { 40 | int sum=0; 41 | 42 | for (int i=0; i < number; i++){ 43 | if (i%3==0 || i%5==0){sum+=i;} 44 | } 45 | return sum; 46 | } 47 | } 48 | ~~~ 49 | 50 | ## Clever 51 | ~~~java 52 | import java.util.stream.IntStream; 53 | 54 | public class Solution { 55 | public int solution(int number) { 56 | return IntStream.range(0, number) 57 | .filter(n -> (n % 3 == 0) || (n % 5 == 0)) 58 | .sum(); 59 | } 60 | } 61 | ~~~ 62 | -------------------------------------------------------------------------------- /Algorithm/Codewars/002-Get_the_middle_character.md: -------------------------------------------------------------------------------- 1 | ![codewars](https://www.codewars.com/users/Integerous/badges/large) 2 | # Get the middle character 3 | >7kyu 4 | >solved with Java 5 | >https://www.codewars.com/kata/get-the-middle-character/java 6 | 7 | ## Instructions 8 | You are going to be given a word. Your job is to return the middle character of the word. If the word's length is odd, return the middle character. If the word's length is even, return the middle 2 characters. 9 | 10 | #Examples: 11 | ~~~ 12 | Kata.getMiddle("test") should return "es" 13 | 14 | Kata.getMiddle("testing") should return "t" 15 | 16 | Kata.getMiddle("middle") should return "dd" 17 | 18 | Kata.getMiddle("A") should return "A" 19 | ~~~ 20 | #Input 21 | 22 | A word (string) of length 0 < str < 1000 (In javascript you may get slightly more than 1000 in some test cases due to an error in the test cases). You do not need to test for this. This is only here to tell you that you do not need to worry about your solution timing out. 23 | 24 | #Output 25 | 26 | The middle character(s) of the word represented as a string. 27 | 28 | # My Solution 29 | ~~~java 30 | class Kata { 31 | public static String getMiddle(String word) { 32 | //Code goes here! 33 | 34 | String x = ""; 35 | int length = word.length(); 36 | 37 | if(length%2==0){ 38 | x = word.substring((length/2)-1,(length/2)+1); 39 | }else{ 40 | x = word.substring((length/2), (length/2)+1); 41 | } 42 | return x; 43 | 44 | } 45 | } 46 | ~~~ 47 | 48 | ## Result & Review 49 | >Passed (Time: 2139ms) 50 | >밑에 Best Practice 처럼 변수를 만들어서 length/2를 담았으면 더 보기에 깔끔했을 것 같다. 51 | >길이가 홀수인 경우 word.substring(Math.abs(length/2))를 사용하려 했는데 Math.abs가 안되는 이유를 모르겠다. 52 | 53 | ## Best Practice 54 | ~~~java 55 | class Kata { 56 | public static String getMiddle(String word) { 57 | String s = ""; 58 | int length = word.length(); 59 | int half = length/2; 60 | 61 | if (length % 2 == 0) { 62 | 63 | s = word.substring(half - 1, half + 1); 64 | 65 | } else { 66 | 67 | s = word.substring(half, half + 1); 68 | 69 | } 70 | 71 | return s; 72 | } 73 | } 74 | ~~~ 75 | 76 | ## Clever 77 | ~~~java 78 | class Kata { 79 | public static String getMiddle(String word) { 80 | int length = word.length(); 81 | return (length % 2 != 0) ? String.valueOf(word.charAt(length / 2)) : word.substring(length / 2 - 1, length / 2 + 1); 82 | } 83 | } 84 | ~~~ 85 | -------------------------------------------------------------------------------- /Algorithm/Codewars/003-String_repeat.md: -------------------------------------------------------------------------------- 1 | # Get the middle character 2 | >8kyu 3 | >solved with Java 4 | >http://www.codewars.com/kata/string-repeat/java 5 | 6 | ## Instructions 7 | Write a function called repeatStr which repeats the given string string exactly n times. 8 | 9 | repeatStr(6, "I") // "IIIIII" 10 | repeatStr(5, "Hello") // "HelloHelloHelloHelloHello" 11 | 12 | # My Solution 13 | ~~~java 14 | public class Solution { 15 | public static String repeatStr(final int repeat, final String string) { 16 | 17 | String x = ""; 18 | 19 | for(int i=0; iTime: 2270ms 29 | - 내 솔루션은 concatenation(+=)으로 해결하므로 매 iteration 마다 String이 새로 만들어지므로 O(n^2)로 비효율적이다. 30 | - 여기서 concatenation은 삽입된 string 만큼 시간이 소비되므로 1+2+3+4+...+repeat = repeat*(repeat+1)/2 이므로 O(n^2)이다. 31 | - 밑의 Best Practice는 StringBuilder를 사용해서 O(n)이다. 32 | 33 | ## Best Practice 34 | ~~~java 35 | public class Solution { 36 | public static String repeatStr(final int repeat, final String string) { 37 | StringBuilder sb = new StringBuilder(); 38 | 39 | for (int i = 0; i < repeat; i++) { 40 | sb.append(string); 41 | } 42 | 43 | return sb.toString(); 44 | } 45 | } 46 | ~~~ 47 | 48 | ## Clever 49 | ~~~java 50 | public class Solution { 51 | public static String repeatStr(final int repeat, final String string) { 52 | return java.util.stream.IntStream.range(0, repeat).mapToObj(i -> string) 53 | .collect(java.util.stream.Collectors.joining()).toString(); 54 | } 55 | } 56 | ~~~ 57 | -------------------------------------------------------------------------------- /Algorithm/Codewars/004-Tribonacci_sequence.md: -------------------------------------------------------------------------------- 1 | >이 문제 풀고나서 7급(7kyu)으로 승급!! 2 | ![codewars](https://www.codewars.com/users/Integerous/badges/large) 3 | # Tribonacci Sequence 4 | >6kyu 5 | >solved with Java 6 | >https://www.codewars.com/kata/tribonacci-sequence/java 7 | 8 | ## Instructions 9 | Well met with Fibonacci bigger brother, AKA Tribonacci. 10 | 11 | As the name may already reveal, it works basically like a Fibonacci, but summing the last 3 (instead of 2) numbers of the sequence to generate the next. And, worse part of it, regrettably I won't get to hear non-native Italian speakers trying to pronounce it :( 12 | 13 | So, if we are to start our Tribonacci sequence with [1, 1, 1] as a starting input (AKA signature), we have this sequence: 14 | 15 | [1, 1 ,1, 3, 5, 9, 17, 31, ...] 16 | But what if we started with [0, 0, 1] as a signature? As starting with [0, 1] instead of [1, 1] basically shifts the common Fibonacci sequence by once place, you may be tempted to think that we would get the same sequence shifted by 2 places, but that is not the case and we would get: 17 | 18 | [0, 0, 1, 1, 2, 4, 7, 13, 24, ...] 19 | Well, you may have guessed it by now, but to be clear: you need to create a fibonacci function that given a signature array/list, returns the first n elements - signature included of the so seeded sequence. 20 | 21 | Signature will always contain 3 numbers; n will always be a non-negative number; if n == 0, then return an empty array and be ready for anything else which is not clearly specified ;) 22 | 23 | # My Solution 24 | ~~~java 25 | public class Xbonacci { 26 | 27 | public double[] tribonacci(double[] s, int n) { 28 | // hackonacci me 29 | 30 | double[] x = new double[n]; 31 | 32 | if(n>2){ 33 | x[0] = s[0]; 34 | x[1] = s[1]; 35 | x[2] = s[2]; 36 | 37 | for(int i=3; iTime: 2208ms 52 | - n이 0,1,2 일 때 문제가 발생한다. 밑에 Best Practice보다 Clever로 선정된 코드가 더 마음에 든다. 왜 저런 생각을 못했을까.. 53 | 54 | ## Best Practice 55 | ~~~java 56 | import java.util.Arrays; 57 | 58 | public class Xbonacci { 59 | public double[] tribonacci(double[] s, int n) { 60 | 61 | double[] tritab=Arrays.copyOf(s, n); 62 | for(int i=3;i7kyu 3 | >solved with Java 4 | >https://www.codewars.com/kata/55f8a9c06c018a0d6e000132 5 | 6 | ## Instructions 7 | ATM machines allow 4 or 6 digit PIN codes and PIN codes cannot contain anything but exactly 4 digits or exactly 6 digits. 8 | 9 | If the function is passed a valid PIN string, return true, else return false. 10 | 11 | eg: 12 | ~~~ 13 | Solution.validatePin("1234") === true 14 | Solution.validatePin("12345") === false 15 | Solution.validatePin("a234") === false 16 | ~~~ 17 | # My Solution 18 | ~~~java 19 | public class Solution { 20 | 21 | public static boolean validatePin(String pin) { 22 | // Your code here... 23 | 24 | int length = pin.length(); 25 | 26 | if(digitCheck(pin) && (length==4 || length==6)) 27 | return true; 28 | else 29 | return false; 30 | } 31 | 32 | public static boolean digitCheck(String pin){ 33 | 34 | try{ 35 | Integer.parseInt(pin); 36 | return true; 37 | }catch(NumberFormatException e){ 38 | return false; 39 | } 40 | } 41 | } 42 | ~~~ 43 | 44 | ## Result & Review 45 | >Time: 2038ms 46 | - 문제 이름에서 알 수 있듯이 정규식으로 푸는 문제였다. 이참에 정규식을 다시 공부했다. 정규식으로 안푼다면 밑에 Clever 코드가 내 코드보다 나아보인다. 47 | 48 | ## Best Practice 49 | ~~~java 50 | import java.util.regex.*; 51 | 52 | public class Solution { 53 | 54 | public static boolean validatePin(String pin) { 55 | return pin.matches("\\d{4}|\\d{6}"); 56 | } 57 | 58 | } 59 | ~~~ 60 | 61 | ## Clever 62 | ~~~java 63 | public class Solution { 64 | 65 | public static boolean validatePin(String pin) { 66 | 67 | if (pin == null || (pin.length()!= 4 && pin.length()!= 6)) 68 | return false; 69 | 70 | 71 | try { 72 | Integer.valueOf(pin); 73 | }catch (Exception e) { 74 | return false; 75 | } 76 | 77 | return true; 78 | } 79 | 80 | } 81 | ~~~ 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Algorithm/Codewars/006-Most_digits.md: -------------------------------------------------------------------------------- 1 | # Most Digits 2 | >7kyu 3 | >failed with Java 4 | >http://www.codewars.com/kata/most-digits/java 5 | 6 | ## Instructions 7 | Find the number with the most digits. 8 | 9 | If two numbers in the argument array have the same number of digits, return the first one in the array. 10 | 11 | # My Solution 12 | ~~~java 13 | public class MostDigits { 14 | public static int findLongest(int[] numbers) { 15 | 16 | int max = numbers[0]; 17 | 18 | for(int i=0; i Math.log10(max)+1) 20 | max = numbers[i]; 21 | 22 | else if(Math.log10(numbers[i])+1 == Math.log10(max)+1) 23 | max = max; 24 | } 25 | 26 | return max; 27 | } 28 | } 29 | ~~~ 30 | 31 | ## Result & Review 32 | >Time-out! 시간 초과로 실패! 33 | - 음수 값 때문에 Math.log10()는 사용하면 안되었다. Best Practice에서 처럼 절대값을 문자열로 바꿔서 그 길이를 구해서 비교했어야 했다. 34 | 35 | ## Best Practice 36 | ~~~java 37 | public class MostDigits { 38 | public static int findLongest(int[] numbers) { 39 | int index = 0; 40 | for (int i = 0; i < numbers.length; i++) { 41 | if (String.valueOf(Math.abs(numbers[i])).length() > String.valueOf(Math.abs(numbers[index])).length()) { 42 | index = i; 43 | } 44 | } 45 | return numbers[index]; 46 | } 47 | } 48 | ~~~ 49 | -------------------------------------------------------------------------------- /Algorithm/Codewars/007-Highest_scoring_word.md: -------------------------------------------------------------------------------- 1 | # Highest Scoring Word 2 | >6kyu 3 | >failed with Java 4 | >http://www.codewars.com/kata/highest-scoring-word/java 5 | 6 | ## Instructions 7 | Description: 8 | Given a string of words, you need to find the highest scoring word. 9 | 10 | Each letter of a word scores points according to it's position in the alphabet: `a = 1, b = 2, c = 3` etc. 11 | 12 | You need to return the highest scoring word as a string. 13 | 14 | If two words score the same, return the word that appears earliest in the original string. 15 | 16 | All letters will be lowercase and all inputs will be valid. 17 | 18 | # My Solution 19 | ~~~java 20 | public class Kata { 21 | 22 | public static String high(String s) { 23 | 24 | // 빈공간 개수 구하기 25 | int spaceCount = 0; 26 | 27 | for(int i=0; iTime-out! 시간 초과로 실패! 61 | - 세상에서 제일 썩은 코드를 작성했다. 62 | - split()과 toCharArray()의 존재를 몰랐다. 63 | - ASCII Table에서 알파벳은 각각 해당하는 10진수 값이 정해져있는 사실을 잊고 있었다. 64 | - 밑의 Clever 코드가 import 없이 풀어서 매우 마음에 든다. 65 | 66 | ## Best Practice 67 | ~~~java 68 | import java.util.*; 69 | 70 | public class Kata { 71 | public static String high(String s) { 72 | return Arrays.stream(s.split(" ")) 73 | .max(Comparator.comparingInt( 74 | a -> a.chars().map(i -> i - 96).sum() 75 | )).get(); 76 | } 77 | } 78 | ~~~ 79 | 80 | ## Clever 81 | ~~~java 82 | public class Kata { 83 | 84 | public static String high(String s) { 85 | 86 | String winner = ""; 87 | int highScore = 0; 88 | 89 | for (String word : s.split(" ")) { 90 | int score = 0; 91 | for (char c : word.toCharArray()) { 92 | score += c - 'a' + 1; 93 | } 94 | if (score > highScore) { 95 | winner = word; 96 | highScore = score; 97 | } 98 | } 99 | 100 | return winner; 101 | } 102 | 103 | } 104 | ~~~ 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Algorithm/Codewars/008-The_highest_profit_wins.md: -------------------------------------------------------------------------------- 1 | # The Highest Profit Wins! 2 | >7kyu 3 | >solved with Java 4 | >http://www.codewars.com/kata/the-highest-profit-wins/java 5 | 6 | ## Instructions 7 | Description: 8 | Story 9 | Ben has a very simple idea to make some profit: he buys something and sells it again. Of course, this wouldn't give him any profit at all if he was simply to buy and sell it at the same price. Instead, he's going to buy it for the lowest possible price and sell it at the highest. 10 | 11 | Task 12 | Write a function that returns both the minimum and maximum number of the given list/array. 13 | 14 | Examples 15 | ~~~ 16 | MinMax.minMax(new int[]{1,2,3,4,5}) == {1,5} 17 | MinMax.minMax(new int[]{2334454,5}) == {5, 2334454} 18 | MinMax.minMax(new int[]{1}) == {1, 1} 19 | ~~~ 20 | Remarks 21 | All arrays or lists will always have at least one element, so you don't need to check the length. Also, your function will always get an array or a list, you don't have to check for null, undefined or similar. 22 | 23 | # My Solution 24 | ~~~java 25 | class MinMax { 26 | public static int[] minMax(int[] arr) { 27 | 28 | int min = arr[0]; 29 | int max = arr[0]; 30 | 31 | for(int i=1; i max) 33 | max = arr[i]; 34 | if( arr[i] < min) 35 | min = arr[i]; 36 | } 37 | 38 | int[] result = new int[2]; 39 | result[0] = min; 40 | result[1] = max; 41 | 42 | return result; 43 | } 44 | } 45 | ~~~ 46 | 47 | ## Result & Review 48 | >Time: 1836ms 49 | - for문 안에 if문을 여러 번 써도 된다는 사실을 잊어서 조금 돌아왔다. 50 | - Best Practice처럼 Arrays.sort(arr) 사용시 시간복잡도 O(NlogN)으로 비효율적이다. 51 | - `return new int[]{min, max}`처럼 반환값에 선언해주면 코드가 더 간결해질 수 있었다. 52 | 53 | ## Best Practice 54 | ~~~java 55 | import java.util.Arrays; 56 | 57 | class MinMax { 58 | public static int[] minMax(int[] arr) { 59 | // Your awesome code here 60 | Arrays.sort(arr); 61 | return new int[]{arr[0],arr[arr.length-1]}; 62 | } 63 | } 64 | ~~~ 65 | 66 | ## Clever 67 | ~~~java 68 | import java.util.*; 69 | class MinMax { 70 | public static int[] minMax(int[] arr) { 71 | return new int[]{Arrays.stream(arr).min().getAsInt(), Arrays.stream(arr).max().getAsInt()}; 72 | } 73 | } 74 | ~~~ 75 | 76 | -------------------------------------------------------------------------------- /Algorithm/Codewars/009-Odd_or_even?.md: -------------------------------------------------------------------------------- 1 | # Odd or Even? 2 | >7kyu 3 | >solved with Java 4 | >http://www.codewars.com/kata/odd-or-even/java 5 | 6 | ## Instructions 7 | Task: 8 | Given an array of numbers (a list in groovy), determine whether the sum of all of the numbers is odd or even. 9 | 10 | Give your answer in string format as 'odd' or 'even'. 11 | 12 | If the input array is empty consider it as: [0] (array with a zero). 13 | 14 | Example: 15 | `oddOrEven([2, 5, 34, 6]) returns "odd".` 16 | Have fun! 17 | # My Solution 18 | ~~~java 19 | public class Codewars { 20 | public static String oddOrEven (int[] array) { 21 | 22 | int length = array.length; 23 | int sum = 0; 24 | 25 | for(int i=0; iTime: 1885ms 40 | - Best Practice를 보니 stream 사용법을 공부해야겠다. 41 | - 0은 짝수라고 생각하고 풀었다. 42 | 43 | ## Best Practice 44 | ~~~java 45 | import static java.util.Arrays.stream; 46 | 47 | class Codewars { 48 | static String oddOrEven(final int[] array) { 49 | return stream(array).sum() % 2 == 0 ? "even" : "odd"; 50 | } 51 | } 52 | ~~~ 53 | 54 | ## Clever 55 | ~~~java 56 | public class Codewars { 57 | public static String oddOrEven (int[] array) { 58 | int sum = 0; 59 | for (int n : array){ 60 | sum += n; 61 | } 62 | return sum%2==0 ? "even" : "odd"; 63 | } 64 | } 65 | ~~~ 66 | 67 | -------------------------------------------------------------------------------- /Algorithm/Codewars/011-Find_the_odd_int.md: -------------------------------------------------------------------------------- 1 | # Find The Odd Int 2 | >6kyu 3 | >failed with Java 4 | >http://www.codewars.com/kata/find-the-odd-int/java 5 | 6 | ## Instructions 7 | Given an array, find the int that appears an odd number of times. 8 | 9 | There will always be only one integer that appears an odd number of times. 10 | 11 | # My Solution 12 | ~~~java 13 | public class FindOdd { 14 | public static int findIt(int[] a) { 15 | 16 | 17 | for(int i=0; iTime-out! 시간 초과로 실패! 36 | - 내 코드가 왜 틀린지 잘 모르겠다. 하지만 매우 구린 코드인 것은 분명하다. 37 | - Best Practice 코드는 XOR을 이용했다. 대박이다. 38 | 39 | ## Best Practice 40 | ~~~java 41 | public class FindOdd { 42 | public static int findIt(int[] A) { 43 | int odd=0; 44 | for (int item: A) 45 | { 46 | odd = odd ^ item; 47 | } 48 | 49 | return odd; 50 | } 51 | } 52 | ~~~ 53 | 54 | ## Clever 55 | ~~~java 56 | import static java.util.Arrays.stream; 57 | 58 | public class FindOdd { 59 | public static int findIt(int[] arr) { 60 | return stream(arr).reduce(0, (x, y) -> x ^ y); 61 | } 62 | } 63 | ~~~ 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Algorithm/Codewars/012-Isograms.md: -------------------------------------------------------------------------------- 1 | # Isograms 2 | >7kyu 3 | >solved with Java 4 | >http://www.codewars.com/kata/isograms/java 5 | 6 | ## Instructions 7 | An isogram is a word that has no repeating letters, consecutive or non-consecutive. Implement a function that determines whether a string that contains only letters is an isogram. Assume the empty string is an isogram. Ignore letter case. 8 | ~~~ 9 | isIsogram "Dermatoglyphics" == true 10 | isIsogram "moose" == false 11 | isIsogram "aba" == false 12 | ~~~ 13 | 14 | # My Solution 15 | ~~~java 16 | public class isogram { 17 | public static boolean isIsogram(String str) { 18 | 19 | char[] array = str.toLowerCase().toCharArray(); 20 | boolean answer = true; 21 | 22 | for(int i=0; iTime: 2005ms 35 | - 처음에 j=i+1 이 아닌 j=1로 풀어서 오류가 발생했다. 36 | - for문이 중첩되었으므로 좋은 코드는 아닌 것 같다. 37 | 38 | ## Best Practice 39 | ~~~java 40 | public class isogram { 41 | public static boolean isIsogram(String str) { 42 | return str.length() == str.toLowerCase().chars().distinct().count(); 43 | } 44 | } 45 | ~~~ 46 | 47 | ## Clever 48 | ~~~java 49 | import java.util.regex.Pattern; 50 | public class isogram { 51 | public static boolean isIsogram(String str) { 52 | return !Pattern.compile("(?i)\\b\\w*(\\w)\\w*(?=\\1)\\w*\\b").matcher(str).matches(); 53 | } 54 | } 55 | ~~~ 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Algorithm/Codewars/013-Count_all_the_sheep.md: -------------------------------------------------------------------------------- 1 | # Count all the sheep on farm in the heights of New Zealand 2 | >7kyu 3 | >solved with Java 4 | >http://www.codewars.com/kata/count-all-the-sheep-on-farm-in-the-heights-of-new-zealand/java 5 | 6 | ## Instructions 7 | Every week (Friday and Saturday night), the farmer and his son count amount of sheep returned to the yard of their farm. 8 | 9 | They count sheep on Friday night, the same goes for Saturday (suppose that sheep returned on Friday are not feeding back on hills on Saturday). 10 | 11 | As sheep are not coming in one flock, you will be given two arrays (one for each night) representing number of sheep as they were returning to the yard during the evenings (entries are positive ints, higher than zero). 12 | 13 | Farmer and his son know the total amount of their sheep, you will be given this number as third parameter. 14 | 15 | Your goal is to calculate the amount of sheep lost (not returned) to the farm after Saturday night counting. 16 | ~~~ 17 | Example 1: Input: {1, 2}, {3, 4}, 15 --> Output: 5 18 | Example 2: Input: {3, 1, 2}, {4, 5}, 21 --> Output: 6 19 | ~~~ 20 | Good luck! :-) 21 | 22 | # My Solution 23 | ~~~java 24 | public class Kata { 25 | public static int lostSheeps(int[] fridayNightCounting, int[] saturdayNightCounting, int sheepsTotal) { 26 | 27 | int friSum = 0; 28 | int SatSum = 0; 29 | 30 | for(int x : fridayNightCounting){ 31 | friSum += x; 32 | } 33 | 34 | for(int y : saturdayNightCounting){ 35 | SatSum += y; 36 | } 37 | 38 | return sheepsTotal - friSum - SatSum; 39 | } 40 | } 41 | ~~~ 42 | 43 | ## Result & Review 44 | >Time: 2036ms 45 | - Best Practice 코드 처럼 변수는 count와 num 두 개면 충분한데 난 4개난 만들었다. 46 | - 쉬운 문제였다. 47 | 48 | ## Best Practice 49 | ~~~java 50 | public class Kata { 51 | public static int lostSheeps(int[] fridayNightCounting, int[] saturdayNightCounting, int sheepsTotal) 52 | { 53 | int count = 0; 54 | for(int num : fridayNightCounting) 55 | { 56 | count += num; 57 | } 58 | for(int num : saturdayNightCounting) 59 | { 60 | count+= num; 61 | } 62 | return sheepsTotal - count; 63 | } 64 | } 65 | ~~~ 66 | 67 | ## Clever 68 | ~~~java 69 | import java.util.*; 70 | 71 | public class Kata { 72 | public static int lostSheeps(int[] f, int[] s, int t) { 73 | return t - Arrays.stream(f).sum() - Arrays.stream(s).sum(); 74 | } 75 | } 76 | ~~~ 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Algorithm/Codewars/016-Make_a_function_that_does_arithmetic.md: -------------------------------------------------------------------------------- 1 | # Make a Function that does arithmetic! 2 | >7kyu 3 | >solved with Java 4 | >https://www.codewars.com/kata/make-a-function-that-does-arithmetic/java 5 | 6 | ## Instructions 7 | Description: 8 | Given two numbers and an arithmetic operator (the name of it, as a string), return the result of the two numbers having that operator used on them. 9 | 10 | a and b will both be positive integers, and a will always be the first number in the operation, and b always the second. 11 | 12 | The four operators are "add", "subtract", "divide", "multiply". 13 | 14 | A few examples: 15 | ~~~java 16 | arithmetic(5, 2, "add") => returns 7 17 | arithmetic(5, 2, "subtract") => returns 3 18 | arithmetic(5, 2, "multiply") => returns 10 19 | arithmetic(5, 2, "divide") => returns 2.5 20 | ~~~ 21 | ~~~java 22 | ArithmeticFunction.arithmetic(5, 2, "add") => returns 7 23 | ArithmeticFunction.arithmetic(5, 2, "subtract") => returns 3 24 | ArithmeticFunction.arithmetic(5, 2, "multiply") => returns 10 25 | ArithmeticFunction.arithmetic(5, 2, "divide") => returns 2 26 | ~~~ 27 | **Try to do it without using if statements!** 28 | 29 | 30 | # My Solution 31 | ~~~java 32 | class ArithmeticFunction { 33 | public static int arithmetic(int a, int b, String operator) { 34 | 35 | return operator=="add"? a+b : (operator=="subtract"? a-b : (operator=="multiply"? a*b : (operator=="divide"? Math.abs(a/b) : null))); 36 | 37 | } 38 | } 39 | ~~~ 40 | 41 | ## Result & Review 42 | >Time : 1905ms 43 | - if문으로 답을 작성하고 '뭐 이렇게 쉽지? 이상한데?'라고 생각했다가 description을 제대로 읽지 않은 것을 발견. if문 없이 해결해야한다. 44 | - 삼항연산자를 사용하면서도 무언가 if문 스럽다는 죄책감이 들었는데, Best Practice로 올라온 코드가 switch로 풀어서 내께 더 낫다고 생각했지만, 45 | - if나 switch나 삼항연산자 없이 **Map으로 푼 사람이 있었다...** Map 미만 잡~ 46 | 47 | ## Best Practice 48 | ~~~java 49 | import java.util.HashMap; 50 | import java.util.Map; 51 | import java.util.Optional; 52 | import java.util.function.BinaryOperator; 53 | 54 | /** 55 | * look: no if 56 | */ 57 | public class ArithmeticFunction { 58 | static Map> operators = new HashMap<>(); 59 | 60 | static { 61 | operators.put("add", (a, b) -> a + b); 62 | operators.put("subtract", (a, b) -> a - b); 63 | operators.put("multiply", (a, b) -> a * b); 64 | operators.put("divide", (a, b) -> a / b); 65 | } 66 | 67 | public static int arithmetic(int a, int b, String operator) { 68 | return arithmetic(a, b, operators.get(operator)); 69 | } 70 | 71 | private static Integer arithmetic(int a, int b, BinaryOperator operator) { 72 | return Optional.ofNullable(operator).orElse((x, y) -> 0).apply(a, b); 73 | } 74 | } 75 | ~~~ 76 | 77 | -------------------------------------------------------------------------------- /Algorithm/Codewars/017-Arithmetic_progression.md: -------------------------------------------------------------------------------- 1 | # Arithmetic Progression 2 | >7kyu 3 | >solved with Java 4 | >https://www.codewars.com/kata/arithmetic-progression/java 5 | 6 | ## Instructions 7 | In your class, you have started lessons about arithmetic progression. Since you are also a programmer, you have decided to write a function that will return the first n elements of the sequence with the given common difference d and first element a. Note that the difference may be zero! 8 | 9 | The result should be a string of numbers, separated by comma and space. 10 | 11 | Example 12 | ~~~ 13 | # first element: 1, difference: 2, how many: 5 14 | arithmetic_sequence_elements(1, 2, 5) == "1, 3, 5, 7, 9" 15 | ~~~ 16 | 17 | # My Solution 18 | ~~~java 19 | class Progression { 20 | 21 | public static String arithmeticSequenceElements(int first, int step, long total) { 22 | 23 | 24 | String result = Integer.toString(first); 25 | int tmp = first; 26 | 27 | for(int i=1; i t + d).limit(n).mapToObj(Integer::toString).collect(joining(", ")); 50 | } 51 | } 52 | ~~~ 53 | -------------------------------------------------------------------------------- /Algorithm/Codewars/018-Duplicate_Encoder.md: -------------------------------------------------------------------------------- 1 | # Duplicate Encoder 2 | >6kyu 3 | >failed 4 | >https://www.codewars.com/kata/duplicate-encoder/java 5 | 6 | ## Instructions 7 | The goal of this exercise is to convert a string to a new string where each character in the new string is '(' if that character appears only once in the original string, or ')' if that character appears more than once in the original string. Ignore capitalization when determining if a character is a duplicate. 8 | 9 | Examples: 10 | ~~~ 11 | "din" => "(((" 12 | 13 | "recede" => "()()()" 14 | 15 | "Success" => ")())())" 16 | 17 | "(( @" => "))((" 18 | ~~~ 19 | 20 | # My Solution 21 | ~~~java 22 | 시간 내에 못품 23 | ~~~ 24 | 25 | ## Result & Review 26 | >Time out! 실패! 27 | - 우선 생각나는대로 for문을 중첩해서 풀어보고 더 나은 방법을 찾아보고자 했다. 하지만 for문 중첩으로도 풀지 못하고 시간 초과로 실패! 28 | - ASCII 코드와 toCharArray()에 대해 제대로 공부할 수 있는 기회였다. 29 | - Best Practice로 뽑힌 코드가 보기에는 좋지만 O(n^2)라는 의견들이 있어, O(n)인 코드를 Best Practice로 선정했다. 30 | - Clever 코드는 비록 O(n^2)지만, 내 뒤통수를 때리는 코드였다. 31 | 32 | ## Best Practice 33 | ~~~java 34 | public class DuplicateEncoder { 35 | static String encode(String word){ 36 | 37 | word = word.toLowerCase(); 38 | 39 | int[] count = new int[256]; 40 | 41 | for(char c : word.toCharArray()){ 42 | count[c]++; 43 | } 44 | 45 | StringBuilder result = new StringBuilder(); 46 | 47 | for(char c : word.toCharArray()){ 48 | if(count[c]>1) result.append(")"); 49 | else result.append("("); 50 | } 51 | return result.toString(); 52 | } 53 | } 54 | ~~~ 55 | 56 | ## Clever 57 | ~~~java 58 | public class DuplicateEncoder { 59 | static String encode(String word){ 60 | word = word.toLowerCase(); 61 | String result = ""; 62 | for (int i = 0; i < word.length(); ++i) { 63 | char c = word.charAt(i); 64 | result += word.lastIndexOf(c) == word.indexOf(c) ? "(" : ")"; 65 | } 66 | return result; 67 | } 68 | } 69 | ~~~ 70 | -------------------------------------------------------------------------------- /Algorithm/Codewars/019-Your_order_please.md: -------------------------------------------------------------------------------- 1 | # Your Order, Please 2 | >6kyu 3 | >passed with java 4 | >https://www.codewars.com/kata/your-order-please/java 5 | 6 | ## Instructions 7 | Your task is to sort a given string. Each word in the String will contain a single number. This number is the position the word should have in the result. 8 | 9 | Note: Numbers can be from 1 to 9. So 1 will be the first word (not 0). 10 | 11 | If the input String is empty, return an empty String. The words in the input String will only contain valid consecutive numbers. 12 | 13 | For an input: "is2 Thi1s T4est 3a" the function should return "Thi1s is2 3a T4est" 14 | 15 | Examples: 16 | ~~~ 17 | your_order("is2 Thi1s T4est 3a") 18 | [1] "Thi1s is2 3a T4est" 19 | ~~~ 20 | 21 | # My Solution 22 | ~~~java 23 | public class Order { 24 | public static String order(String words) { 25 | 26 | if(words == "") return ""; 27 | 28 | // 1. 문장의 숫자만 추출하여 문자열로 생성 29 | String nums = words.replaceAll("[^0-9]", ""); 30 | 31 | // 2. 띄어쓰기로 단어 구분해서 배열에 저장 32 | String[] ws = words.split(" "); 33 | 34 | // 3. 배열 길이 저장 35 | int length = ws.length; 36 | 37 | // 4. 결과값을 저장할 배열 생성 38 | String[] result = new String[length]; 39 | 40 | // 5. 배열 내 순서 변경 41 | for(int i=0; iTime : 2019 ms 54 | - 오랜만에 문제를 풀어서 그런지 다음 사항들을 검색해야했다. 55 | - 문자열에서 숫자만 추출하기 `replaceAll()` 56 | - split()함수가 배열로 반환되는지 `배열로 반환` 57 | - 배열 길이 구하기 `배열이름.length` 58 | - Char > int 형변환 `Character.getNumericValue()` 59 | - String.join 함수 `String.join(구분자, values)` 60 | - 차근차근 풀어나가는 것이 가장 빠른 방법이라는 것을 다시 느꼈다. 61 | 62 | ## Best Practice 63 | ~~~java 64 | import java.util.Arrays; 65 | import java.util.Comparator; 66 | 67 | public class Order { 68 | public static String order(String words) { 69 | return Arrays.stream(words.split(" ")) 70 | .sorted(Comparator.comparing(s -> Integer.valueOf(s.replaceAll("\\D", "")))) 71 | .reduce((a, b) -> a + " " + b).get(); 72 | } 73 | } 74 | ~~~ 75 | 76 | ## Clever 77 | ~~~java 78 | import java.util.Arrays; 79 | public class Order { 80 | public static String order(String words) { 81 | String[] strs = words.split(" "); 82 | Arrays.sort(strs, (String s1, String s2) -> s1.replaceAll("[a-zA-Z]","").compareTo(s2.replaceAll("[a-zA-Z]","")) ); 83 | String f = ""; 84 | for(String st:strs) f+=st + " "; 85 | return f.substring(0,f.length()-1); 86 | } 87 | } 88 | ~~~ 89 | -------------------------------------------------------------------------------- /Algorithm/Codewars/020-Row_Weights.md: -------------------------------------------------------------------------------- 1 | # Row Weights 2 | >7kyu 3 | >passed with java 4 | >https://www.codewars.com/kata/5abd66a5ccfd1130b30000a9/java 5 | 6 | ## Instructions 7 | ### Scenario 8 | Several people are standing in a row divided into two teams. 9 | The first person goes into team 1, the second goes into team 2, the third goes into team 1, and so on. 10 | 11 | ### Task 12 | Given an array of positive integers (the weights of the people), return a new array/tuple of two integers, where the first one is the total weight of team 1, and the second one is the total weight of team 2. 13 | 14 | ### Notes 15 | Array size is at least 1. 16 | All numbers will be positive. 17 | 18 | ### Input >> Output Examples 19 | ~~~ 20 | 1- rowWeights([13, 27, 49]) ==> return (62, 27) 21 | ~~~ 22 | Explanation: 23 | The first element 62 is the total weight of team 1, and the second element 27 is the total weight of team 2. 24 | 25 | ~~~ 26 | 2- rowWeights([50, 60, 70, 80]) ==> return (120, 140) 27 | ~~~ 28 | Explanation: 29 | The first element 120 is the total weight of team 1, and the second element 140 is the total weight of team 2. 30 | 31 | ~~~ 32 | 3- rowWeights([80]) ==> return (80, 0) 33 | ~~~ 34 | Explanation: 35 | The first element 80 is the total weight of team 1, and the second element 0 is the total weight of team 2. 36 | 37 | # My Solution 38 | ~~~java 39 | public class Solution { 40 | public static int[] rowWeights (final int[] weights) { 41 | 42 | int result1 = 0; 43 | int result2 = 0; 44 | 45 | for(int i=0; iTime : 2327 ms 59 | - 쉬운 문제였다. 60 | 61 | ## Best Practice 62 | ~~~java 63 | public class Solution { 64 | public static int[] rowWeights (final int[] weights) { 65 | int totals[] = new int[2], idx = 0; 66 | for (int w : weights) totals[(idx++)%2] += w; 67 | return totals; 68 | } 69 | 70 | } 71 | ~~~ 72 | -------------------------------------------------------------------------------- /Algorithm/Codewars/021-Maximum_Product.md: -------------------------------------------------------------------------------- 1 | # Maximum Product 2 | >7kyu 3 | >passed with java 4 | >https://www.codewars.com/kata/maximum-product/java 5 | 6 | ## Instructions 7 | ### Task 8 | Given an array of integers , Find the maximum product obtained from multiplying 2 adjacent numbers in the array. 9 | 10 | ### Notes 11 | - Array/list size is at least 2 . 12 | - Array/list numbers could be a mixture of positives , ngatives also zeros . 13 | 14 | ### Input >> Output Examples 15 | ~~~java 16 | adjacentElementsProduct(new int[] {1, 2, 3}); ==> return 6 17 | ~~~ 18 | Explanation: 19 | The maximum product obtained from multiplying 2 * 3 = 6, and they're adjacent numbers in the array. 20 | ~~~java 21 | adjacentElementsProduct(new int[] {9, 5, 10, 2, 24, -1, -48}); ==> return 50 22 | ~~~ 23 | Explanation: 24 | Max product obtained from multiplying 5 * 10 = 50 . 25 | ~~~java 26 | adjacentElementsProduct(new int[] {-23, 4, -5, 99, -27, 329, -2, 7, -921}) ==> return -14 27 | ~~~ 28 | Explanation: 29 | The maximum product obtained from multiplying -2 * 7 = -14, and they're adjacent numbers in the array. 30 | 31 | # My Solution 32 | ~~~java 33 | public class MaxProduct { 34 | public int adjacentElementsProduct(int[] array) { 35 | 36 | int max = array[0]*array[1]; 37 | 38 | for(int i=0; iTime : 2210 ms 49 | - 쉬운 문제였다. 50 | - 배운 점 51 | - `Integer.MIN_VALUE`, `Integer.MAX_VALUE`로 정수의 최소값 최대값을 구할 수 있다. 52 | - `Math.max(비교대상1,비교대상2...)` 53 | 54 | ## Best Practice 55 | ~~~java 56 | public class MaxProduct { 57 | public int adjacentElementsProduct(int[] array) { 58 | int ans = Integer.MIN_VALUE; 59 | for (int i = 0; i < array.length-1; i++) 60 | ans = Math.max(ans,array[i]*array[i+1]); 61 | return ans; 62 | } 63 | } 64 | ~~~ 65 | 66 | ## Clever 67 | ~~~java 68 | import java.util.stream.IntStream; 69 | 70 | public class MaxProduct { 71 | public int adjacentElementsProduct(int[] array) { 72 | 73 | return IntStream.range(0, array.length - 1) 74 | .map(x -> array[x]*array[x+1]) 75 | .max() 76 | .orElse(Integer.MIN_VALUE); 77 | } 78 | } 79 | ~~~ 80 | -------------------------------------------------------------------------------- /Algorithm/Codewars/022-Where_is_my_parent.md: -------------------------------------------------------------------------------- 1 | # Where is my parent!?(cry) 2 | >6kyu 3 | >failed 4 | >https://www.codewars.com/kata/where-is-my-parent-cry/java 5 | 6 | ## Instructions 7 | Mothers arranged dance party for children in school.On that party there are only mothers and their children.All are having great fun on dancing floor when suddenly all lights went out.Its dark night and no one can see eachother.But you were flying nearby and you can see in the dark and have ability to teleport people anywhere you want. 8 | 9 | ### Legend: 10 | -Uppercase letters stands for mothers,lowercase stand for their children. I.E "A" mothers children are "aaaa". 11 | -Function input:String contain only letters,Uppercase letters are unique. 12 | 13 | ### Task: 14 | Place all people in alphabetical order where Mothers are followed by their children.I.E "aAbaBb" => "AaaBbb". 15 | 16 | # My Solution 17 | ~~~java 18 | public class MaxProduct { 19 | public int adjacentElementsProduct(int[] array) { 20 | 21 | 시간초과로 풀이 실패! 22 | ~~~ 23 | 24 | ## Result & Review 25 | >Time out! 시간 초과로 실패! 26 | - 배운 점 27 | - `Array.sort()`와 `String.CASE_INSENSITIVE_OREDER`의 존재를 모르고 있었다. 28 | - 문자열 구분을 `text.charAt(i)`이 아닌 `text.split("")`으로도 할 수 있다. 29 | - 배열 원소들을 붙일 때에는 `String.join("", 배열이름)` 사용 가능 30 | 31 | ## Best Practice 32 | ~~~java 33 | import java.util.Arrays; 34 | 35 | class WhereIsMyParent { 36 | static String findChildren(final String text) { 37 | String[] sorted = text.split(""); 38 | Arrays.sort(sorted); 39 | Arrays.sort(sorted, String.CASE_INSENSITIVE_ORDER); 40 | return String.join("", sorted); 41 | } 42 | } 43 | ~~~ 44 | -------------------------------------------------------------------------------- /Algorithm/Codility/BinaryGap.md: -------------------------------------------------------------------------------- 1 | ## BinaryGap 2 | >1~21억 사이의 정수를 이진수로 변환했을때 1사이의 거리를 binary gap이라 가정. 3 | >주어진 정수의 가장 긴 binary gap 반환하기 4 | 5 | ### java Integer 클래스 `Integer.toBinaryString()` 사용 6 | ~~~java 7 | //import java.util.*; 8 | class Solution { 9 | public int solution(int N) { 10 | 11 | String binaryString = Integer.toBinaryString(N); 12 | char[] binaryChar = binaryString.toCharArray(); 13 | 14 | int maxGap =0; 15 | int gap = 0; 16 | 17 | for(int i=0; i maxGap) { 20 | maxGap = gap; 21 | } 22 | gap = 0; 23 | } 24 | else{ 25 | gap++; 26 | } 27 | } 28 | 29 | return maxGap; 30 | } 31 | } 32 | ~~~ 33 | 34 | ### 10진수를 2로 거듭 나눠서 2진수 구하기 35 | 36 | ~~~java 37 | class Solution { 38 | public int solution(int N) { 39 | 40 | int maxGap = 0; 41 | int gap = 0; 42 | 43 | while(N!=0) { 44 | N = N/2; 45 | if(gap > maxGap) { 46 | maxGap = gap; 47 | } 48 | if(N%2 == 1) { 49 | gap = 0; 50 | }else 51 | gap++; 52 | } 53 | 54 | return maxGap; 55 | } 56 | } 57 | ~~~ 58 | -------------------------------------------------------------------------------- /Algorithm/Codility/Brackets.md: -------------------------------------------------------------------------------- 1 | # Brakets 2 | >https://app.codility.com/programmers/lessons/7-stacks_and_queues/brackets/ 3 | 4 | ### 내 풀이 0% 5 | >실패 6 | 7 | ### 다른사람 풀이 100% 8 | >http://stroot.tistory.com/104 9 | 10 | ~~~java 11 | public int solution(String S) { 12 | Stack stack = new Stack<>(); 13 | 14 | for (int i = 0; i < S.length(); i++) { 15 | char c = S.charAt(i); 16 | 17 | if (c == '(' || c == '{' || c == '[') { 18 | stack.push(c); 19 | } 20 | else { 21 | if (stack.isEmpty()) { 22 | return 0; 23 | } 24 | 25 | char lastC = stack.pop(); 26 | 27 | if (c == ')' && lastC != '(') { 28 | return 0; 29 | } 30 | 31 | if (c == '}' && lastC != '{') { 32 | return 0; 33 | } 34 | 35 | if (c == ']' && lastC != '[') { 36 | return 0; 37 | } 38 | } 39 | } 40 | 41 | if (!stack.isEmpty()) { 42 | return 0; 43 | } 44 | 45 | return 1; 46 | } 47 | ~~~ 48 | -------------------------------------------------------------------------------- /Algorithm/Codility/CountDiv.md: -------------------------------------------------------------------------------- 1 | # Count Div 2 | >https://app.codility.com/programmers/lessons/5-prefix_sums/count_div/ 3 | 4 | ### 내 풀이 50% 5 | >correctness는 100%였지만 Performance는 0% 6 | >A, B, K의 범위가 20억인데 배열로 푼 것은 멍청했다. 7 | 8 | ~~~java 9 | class Solution { 10 | public int solution(int A, int B, int K) { 11 | 12 | int[] tmp = new int[B-A+1]; 13 | int count = 0; 14 | 15 | 16 | for(int i=0; ihttp://mingmi-programming.tistory.com/62 30 | >수학 지식으로 풀 수 있는 문제였다. 공식을 몰랐다면 손으로 규칙을 찾았어야했다. 31 | 32 | ~~~java 33 | class Solution { 34 | public int solution(int A, int B, int K) { 35 | 36 | if (A == 0) 37 | return B / K + 1; 38 | else 39 | return B / K - (A - 1) / K; 40 | } 41 | } 42 | ~~~ 43 | -------------------------------------------------------------------------------- /Algorithm/Codility/CyclicRotation.md: -------------------------------------------------------------------------------- 1 | ## CyclicRotation 2 | >https://app.codility.com/programmers/lessons/2-arrays/cyclic_rotation/ 3 | 4 | ### 내 풀이 100% 5 | 6 | ~~~java 7 | class Solution { 8 | public int[] solution(int[] A, int K) { 9 | 10 | // correectness! rather than performance 11 | 12 | // 배열의 길이 13 | int length = A.length; 14 | 15 | // 임시저장 배열 16 | int[] tmp = new int[length]; 17 | 18 | if(length != 0) { 19 | // 배열 각 원소의 이동 횟수 20 | int move = K % length; 21 | 22 | // 임시배열에 새로운 순서 담기 23 | for(int i=0; ihttp://blog.naver.com/PostView.nhn?blogId=netrance&logNo=220690184441 38 | ~~~java 39 | class Solution { 40 | public int[] solution(int[] A, int K) { 41 | 42 | int[] B = new int[A.length]; 43 | 44 | for(int i = 0; i < A.length; i++){ 45 | B[(i+K) % A.length] = A[i]; 46 | } 47 | return B; 48 | } 49 | } 50 | ~~~ 51 | -------------------------------------------------------------------------------- /Algorithm/Codility/Distinct.md: -------------------------------------------------------------------------------- 1 | # Distinct 2 | >https://app.codility.com/programmers/lessons/6-sorting/distinct/ 3 | 4 | 5 | ### 내 풀이 100% 6 | 7 | ~~~java 8 | import java.util.*; 9 | 10 | // you can write to stdout for debugging purposes, e.g. 11 | // System.out.println("this is a debug message"); 12 | 13 | class Solution { 14 | public int solution(int[] A) { 15 | 16 | Set filterSet = new HashSet<>(); 17 | 18 | for(int i=0; ihttps://app.codility.com/programmers/lessons/8-leader/equi_leader/ 3 | 4 | 5 | ### 내 풀이 0% 6 | >1시간 풀었으나 실패 7 | >다시 풀어보기 8 | 9 | 10 | ### 다른사람 풀이 100% 11 | >http://androidapptech0.blogspot.com/2017/01/codility-lesson-8-leader-equileader-java.html 12 | 13 | ~~~java 14 | import java.util.*; 15 | 16 | class Solution { 17 | public int solution(int[] A) { 18 | int leader=-1; 19 | int countOfLeader=0; 20 | 21 | HashMap hashMap=new HashMap<>(); 22 | 23 | for(int i=0;i=0;i--){ 45 | if(A[i]==leader){ 46 | counterOfrLeaderInRight++; 47 | counterOfrLeaderInLeft--; 48 | } 49 | 50 | if(counterOfrLeaderInLeft>i/2 && counterOfrLeaderInRight>((A.length-i)/2)){ 51 | countEquil++; 52 | } 53 | } 54 | return countEquil; 55 | } 56 | } 57 | ~~~ 58 | -------------------------------------------------------------------------------- /Algorithm/Codility/FrogJmp.md: -------------------------------------------------------------------------------- 1 | # FrogJmp 2 | >https://app.codility.com/programmers/lessons/3-time_complexity/frog_jmp/ 3 | 4 | ~~~java 5 | import java.util.*; 6 | 7 | class Solution { 8 | public int solution(int X, int Y, int D) { 9 | 10 | if( (Y-X)%D == 0) 11 | return (Y-X)/D; 12 | else 13 | return (int)Math.floor((Y-X)/D)+1; 14 | } 15 | } 16 | ~~~ 17 | -------------------------------------------------------------------------------- /Algorithm/Codility/FrogRiverOne.md: -------------------------------------------------------------------------------- 1 | # FrogRiverOne 2 | >https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/ 3 | 4 | ### 내 풀이 5 | >int배열의 각 원소는 int의 기본값 0으로 초기화되는 것을 잊고 헤맸다. 6 | ~~~java 7 | class Solution { 8 | public int solution(int X, int[] A) { 9 | 10 | int[] B = new int[X+1]; 11 | int count = 0; 12 | 13 | for(int i=0; ihttps://stackoverflow.com/questions/19459197/java-codility-frog-river-one 30 | >Set은 유일한 값만 추가할 수 있는 성질 활용 31 | ~~~java 32 | import java.util.HashSet; 33 | import java.util.Set; 34 | 35 | class Solution { 36 | public int solution(int X, int[] A) { 37 | 38 | Set values = new HashSet(); 39 | 40 | for (int i = 0; i < A.length; i++) { 41 | if (values.add(A[i])) X--; 42 | if (X == 0) return i; 43 | } 44 | return -1; 45 | } 46 | } 47 | ~~~ 48 | -------------------------------------------------------------------------------- /Algorithm/Codility/MaxCounters.md: -------------------------------------------------------------------------------- 1 | # MaxCounters 2 | >https://app.codility.com/programmers/lessons/4-counting_elements/max_counters/ 3 | 4 | ### 내 풀이 77% 5 | >O(N*M)으로 풀어서 그런지 감점 요인은 Timeout 6 | 7 | ~~~java 8 | class Solution { 9 | public int[] solution(int N, int[] A) { 10 | 11 | // N+1일때의 연산 12 | // 최대값으로 counters 통일 13 | // 1~N일때의 연산 14 | // 해당 위치의 값 +1 15 | 16 | //A의 길이는 연산 횟수 17 | //N이 반환되는 배열 길이 18 | 19 | int[] result = new int[N]; 20 | int max = 0; 21 | 22 | for(int i=0; i max) { 27 | max = result[A[i]-1]; 28 | } 29 | } 30 | 31 | if(A[i] == N+1) { 32 | for(int j=0; jhttp://stroot.tistory.com/93 44 | >O(N+M) 45 | >max counter 연산이 일어날 때 마다 값을 대입하지 않고, 변수에 저장해두고 그 다음 increase 연산에서 해당 원소가 max값보다 작으면 max값을 대입하고 46 | 해당 원소에 1을 더한다. 아예 increase 연산이 일어나지 않는 원소는 마지막에 for문 돌면서 max 변수에 담아둔 값을 넣어준다. 47 | 48 | ~~~java 49 | class Solution { 50 | public int[] solution(int N, int[] A) { 51 | 52 | int[] counter = new int[N]; 53 | int tmpMaxCounter = 0; 54 | int doneMaxCounter = 0; 55 | 56 | for (int i = 0; i < A.length; i++) { 57 | if (A[i] > N) { 58 | doneMaxCounter = tmpMaxCounter; 59 | } 60 | else { 61 | if (counter[A[i] - 1] < doneMaxCounter) { 62 | counter[A[i] - 1] = doneMaxCounter; 63 | } 64 | 65 | counter[A[i] - 1]++; 66 | 67 | if (counter[A[i] - 1] > tmpMaxCounter) { 68 | tmpMaxCounter = counter[A[i] - 1]; 69 | } 70 | } 71 | } 72 | 73 | if (doneMaxCounter > 0) { 74 | for (int i = 0; i < counter.length; i++) { 75 | if (counter[i] < doneMaxCounter) { 76 | counter[i] = doneMaxCounter; 77 | } 78 | } 79 | } 80 | 81 | return counter; 82 | } 83 | } 84 | ~~~ 85 | -------------------------------------------------------------------------------- /Algorithm/Codility/MaxProductOfThree.md: -------------------------------------------------------------------------------- 1 | # Max Product Of Three 2 | >https://app.codility.com/programmers/lessons/6-sorting/max_product_of_three/ 3 | 4 | ### 내 풀이 44% 5 | >내가 만든 테스트케이스 중 일부를 통과하지 못했지만 제출해봤다. 6 | >최대값이 되는 경우를 단순화하지 못했고, for문을 사용할 필요가 전혀 없었다. 7 | 8 | ~~~java 9 | import java.util.*; 10 | 11 | class Solution { 12 | public int solution(int[] A) { 13 | 14 | Arrays.sort(A); 15 | int result = 0; 16 | int length = A.length; 17 | 18 | for(int i=0; i (A[length-2]*A[length-1])) { 20 | result = A[i]*A[i+1]*A[length-1]; 21 | }else 22 | result = A[length-3]*A[length-2]*A[length-1]; 23 | } 24 | return result; 25 | } 26 | } 27 | ~~~ 28 | 29 | ### 다른사람 풀이 100% 30 | >http://reddeco.tistory.com/entry/MaxProductOfThree 31 | >최대값이 되는 경우를 2가지로 단순화했다. 32 | 33 | ~~~java 34 | import java.util.*; 35 | 36 | class Solution { 37 | public int solution(int[] A) { 38 | 39 | Arrays.sort(A); 40 | 41 | int caseA = A[A.length-1]*A[A.length-2]*A[A.length-3]; 42 | int caseB = A[0]*A[1]*A[A.length-1]; 43 | 44 | return caseA > caseB ? caseA : caseB; 45 | } 46 | } 47 | ~~~ 48 | -------------------------------------------------------------------------------- /Algorithm/Codility/MinAvgTwoSlice.md: -------------------------------------------------------------------------------- 1 | # MinAvgTwoSlice 2 | >https://app.codility.com/programmers/lessons/5-prefix_sums/min_avg_two_slice/ 3 | 4 | ## 다른사람 풀이 5 | >http://stroot.tistory.com/97 6 | 7 | 평균의 성질을 이해하고 풀었어야 하는 문제였다. 8 | 나처럼 코드부터 작성하려고 덤볐다가는 날 밤 샐 문제인 것 같다. 9 | 10 | 1. 인자 2개의 평균은 인자 중 하나보다 같거나 큰 값이다. 11 | 2. 평균값들의 평균은 각 인자들의 평균과 같다. 12 | 3. 즉, 평균값들의 평균은 그 인자가 되는 평균들보다 항상 같거나 크다. 13 | 4. 그러므로, 인자가 2개인 경우와 3개인 경우만 생각하면 된다. 14 | 15 | ~~~java 16 | public int solution(int[] A) { 17 | double minAvg = (A[0] + A[1]) / 2.0; 18 | int minStartIndex = 0; 19 | 20 | for (int i = 2; i < A.length; i++) { 21 | double avg = (A[i - 2] + A[i - 1] + A[i]) / 3.0; 22 | 23 | if (avg < minAvg) { 24 | minAvg = avg; 25 | minStartIndex = i - 2; 26 | } 27 | 28 | avg = (A[i - 1] + A[i]) / 2.0; 29 | 30 | if (avg < minAvg) { 31 | minAvg = avg; 32 | minStartIndex = i - 1; 33 | } 34 | } 35 | 36 | return minStartIndex; 37 | } 38 | ~~~ 39 | -------------------------------------------------------------------------------- /Algorithm/Codility/MissingInteger.md: -------------------------------------------------------------------------------- 1 | # MissingInteger 2 | >https://app.codility.com/programmers/lessons/4-counting_elements/missing_integer/ 3 | 4 | ### Set 사용 100% 5 | >O(N) or O(N * log(N)) 6 | ~~~java 7 | import java.util.*; 8 | 9 | class Solution { 10 | public int solution(int[] A) { 11 | 12 | Set checkSet = new HashSet<>(); 13 | 14 | for(int i=0; ihttps://app.codility.com/programmers/lessons/7-stacks_and_queues/nesting/ 3 | 4 | ### 내 풀이 100% 5 | >스택 없이 +-로만 풀어도 될 것 같다. 6 | 7 | ~~~java 8 | import java.util.*; 9 | 10 | class Solution { 11 | public int solution(String S) { 12 | 13 | Stack stk = new Stack<>(); 14 | 15 | for(int i=0; ihttps://app.codility.com/programmers/lessons/6-sorting/number_of_disc_intersections/ 3 | 4 | ### 다른사람 풀이 100% 5 | >https://github.com/Mickey0521/Codility/blob/master/NumberOfDiscIntersections.java 6 | >while 부분이 새로웠다. 7 | 8 | ~~~java 9 | import java.util.*; 10 | 11 | // System.out.println("this is a debug message"); 12 | 13 | class Solution { 14 | public int solution(int[] A) { 15 | 16 | // main idea: 17 | // 1. store all the "lower points" and "upper points" of the discs 18 | // 2. count the intersections (if one upper point > one lower point) 19 | 20 | // note: use "long" for big numbers (be careful) 21 | long[] lower = new long[A.length]; 22 | long[] upper = new long[A.length]; 23 | 24 | for(int i=0; i= lower[j]){ 41 | intersection = intersection + j; // add j intersections 42 | intersection = intersection - i; // minus "i" (avoid double count) 43 | j++; 44 | } 45 | } 46 | 47 | // for the overflow cases 48 | if(intersection > 10_000_000) 49 | return -1; 50 | 51 | return intersection; // number of intersections 52 | } 53 | } 54 | ~~~ 55 | -------------------------------------------------------------------------------- /Algorithm/Codility/OddOccurrencesInArray.md: -------------------------------------------------------------------------------- 1 | # OddOccurrencesInArray 2 | >https://app.codility.com/programmers/lessons/2-arrays/odd_occurrences_in_array/ 3 | 4 | 5 | ### 내 풀이 0% 6 | 7 | ~~~java 8 | import java.util.*; 9 | 10 | class Solution { 11 | public int solution(int[] A) { 12 | 13 | Arrays.sort(A); 14 | int result = 0; 15 | 16 | for(int i=1; i< Math.ceil(A.length/2); i++) { 17 | if(A.length == 1){ 18 | result = A[0]; 19 | } 20 | else if(A[2*i-2]-A[2*i-1] != 0) { 21 | result = A[2*i-2]; 22 | } 23 | } 24 | return result; 25 | } 26 | } 27 | ~~~ 28 | 29 | ### 다른사람 풀이 1 30 | >XOR 이용 31 | 32 | ~~~java 33 | class Solution { 34 | public int solution(int[] A) { 35 | 36 | int result = 0; 37 | 38 | for(int i=0; iHashSet 이용 49 | 50 | ~~~java 51 | class Solution { 52 | public int solution(int[] A) { 53 | 54 | Set set = new HashSet<>(); 55 | 56 | for(int i : A) { 57 | if(set.contains(i)) { 58 | set.remove(i); 59 | }else { 60 | set.add(i); 61 | } 62 | } 63 | 64 | return set.iterator().next(); 65 | } 66 | } 67 | ~~~ 68 | -------------------------------------------------------------------------------- /Algorithm/Codility/PassingCars.md: -------------------------------------------------------------------------------- 1 | # Passing Cars 2 | >https://app.codility.com/programmers/lessons/5-prefix_sums/passing_cars/ 3 | 4 | 5 | ### 내 풀이 90% 6 | >passingCars가 음수일 경우에도 -1을 반환하게 했어야했다. 7 | >근데 테스트케이스에서 어떻게 passingCars가 음수가 될 수 있는거지? 8 | 9 | ~~~java 10 | class Solution { 11 | public int solution(int[] A) { 12 | 13 | int toEast = 0; 14 | int passingCars = 0; 15 | 16 | for(int i=0; i 1000000000) 24 | return -1; 25 | 26 | return passingCars; 27 | } 28 | } 29 | ~~~ 30 | -------------------------------------------------------------------------------- /Algorithm/Codility/PermCheck.md: -------------------------------------------------------------------------------- 1 | # PermCheck 2 | >https://app.codility.com/programmers/lessons/4-counting_elements/perm_check/ 3 | 4 | ### 내 풀이 75% 5 | >[2,2,2] 상황에서 합이 6인데 걸러내지 못하는 코드다. 6 | 7 | ~~~java 8 | class Solution { 9 | public int solution(int[] A) { 10 | 11 | // 원소의 합 12 | int sum = 0; 13 | int check = 0; 14 | 15 | for(int i=0; i A.length) { 17 | return 0; 18 | } 19 | sum += A[i]; 20 | check += i+1; 21 | } 22 | 23 | if(sum == check) 24 | return 1; 25 | else 26 | return 0; 27 | } 28 | } 29 | ~~~ 30 | 31 | ### 다른사람 풀이 100% 32 | >http://stroot.tistory.com/90 33 | >완전한 순열이 안되게 하는 조건 2가지만 체크하는 방식 34 | >O(N) or O(N * log(N)) 35 | 36 | ~~~java 37 | import java.util.*; 38 | 39 | class Solution { 40 | public int solution(int[] A) { 41 | 42 | Set check = new HashSet<>(); 43 | 44 | for(int i=0; i A.length) { 46 | return 0; 47 | } 48 | 49 | if(check.contains(A[i])) { 50 | return 0; 51 | } 52 | 53 | check.add(A[i]); 54 | } 55 | return 1; 56 | } 57 | } 58 | ~~~ 59 | -------------------------------------------------------------------------------- /Algorithm/Codility/PermMissingElem.md: -------------------------------------------------------------------------------- 1 | ## Perm Missing Elem 2 | >https://app.codility.com/programmers/lessons/3-time_complexity/perm_missing_elem/ 3 | 4 | ### 내 풀이 100% 5 | ~~~java 6 | import java.util.*; 7 | 8 | class Solution { 9 | public int solution(int[] A) { 10 | 11 | Arrays.sort(A); 12 | 13 | for(int i=0; ihttps://app.codility.com/programmers/lessons/7-stacks_and_queues/stone_wall/ 3 | 4 | ### 내 풀이 50% 5 | >스택에 현재 높이보다 높은 것들을 while문을 돌려서 모두 pop()해야 했는데 6 | >직전의 것만 pop()해서 오답인 경우들이 생겼다. 7 | >Stack 문제는 while문을 잘 활용해야 할 것 같다. 8 | 9 | ~~~java 10 | import java.util.*; 11 | 12 | class Solution { 13 | public int solution(int[] H) { 14 | 15 | Stack stk = new Stack<>(); 16 | 17 | int count = 0; 18 | 19 | for(int i=0; i stk.peek()){ 28 | stk.push(H[i]); 29 | count++; 30 | } 31 | else if(H[i] < stk.peek()) { 32 | 33 | stk.pop(); 34 | 35 | if(stk.isEmpty()) { 36 | stk.push(H[i]); 37 | count++; 38 | } 39 | else if(H[i] != stk.peek()) { 40 | stk.push(H[i]); 41 | count++; 42 | } 43 | } 44 | } 45 | return count; 46 | } 47 | } 48 | ~~~ 49 | 50 | ### 다른사람 풀이 100% 51 | >http://romanticcode.tistory.com/37 52 | 53 | ~~~java 54 | import java.util.Stack; 55 | 56 | class Solution { 57 | public int solution(int[] H) { 58 | 59 | Stack stack = new Stack(); 60 | int blockCnt = 0; 61 | 62 | for(int i =0 ; i < H.length; i++){ 63 | 64 | while(stack.size() > 0 && stack.peek() > H[i]){ 65 | stack.pop(); 66 | } 67 | 68 | if(stack.size() == 0 || stack.peek() < H[i]){ 69 | stack.push(H[i]); 70 | blockCnt++; 71 | } 72 | } 73 | return blockCnt; 74 | } 75 | } 76 | ~~~ 77 | -------------------------------------------------------------------------------- /Algorithm/Codility/TapeEquilibrium.md: -------------------------------------------------------------------------------- 1 | ## TapeEquilibrium 2 | >https://app.codility.com/programmers/lessons/3-time_complexity/ 3 | 4 | ### 내 풀이 100% 5 | ~~~java 6 | class Solution { 7 | public int solution(int[] A) { 8 | 9 | int left = 0; 10 | int right = 0; 11 | 12 | for(int i=0; ihttps://app.codility.com/programmers/lessons/6-sorting/triangle/ 3 | 4 | ### 내 풀이 0% 5 | 6 | >배열을 정렬하고, for문으로 A[i]+A[i+1]>A[i+2] 를 만족하면 1을 반환하고 아니면 0을 반환하게끔 작성하다가 스스로 함정에 빠졌다. 7 | 8 | 문제에 주어진 테스트케이스를 정렬하면 [1, 2, 5, 8, 10, 20] 이고 [5, 8, 10]에 의해 Triangle이 된다. 9 | 나는 [5, 8 ,10] 처럼 연속되는 배열의 원소가 Triangle이 되는 경우가 아닌 케이스 [1, 3, 5, 8, 10, 20]를 고려해서 10 | [3, 8, 10] 처럼 Triangle 조건을 만족하지만 연속되지 않는 것들을 어떻게 처리해야 할지 고민하는데 시간을 쏟았다. 11 | 12 | 그런데 [3, 8, 10]이 만족하면 3과 8사이에 어떤 정수라도 조건을 만족하기 때문에 13 | 연속된 원소들(A[i], A[i+1], A[i+2])를 조건문에 사용해서 for문을 돌려도 상관없는 것이었다. 14 | 15 | 문제를 풀다가 경우가 너무 다양해서 막막해지면, 그 경우들을 어떻게 처리할 지 고민하기보다 경우를 통합하고 간소화할 방법을 먼저 고민해야될 것 같다. 16 | 17 | ### 다른사람 풀이 100% 18 | >https://wildcatsy.blogspot.com/2017/05/codility-lesson-6-sorting-triangle-100.html 19 | 20 | ~~~java 21 | import java.util.Arrays; 22 | // you can write to stdout for debugging purposes, e.g. 23 | // System.out.println("this is a debug message"); 24 | 25 | class Solution { 26 | public int solution(int[] A) { 27 | // write your code in Java SE 8 28 | Arrays.sort(A); 29 | 30 | 31 | for( int i = 0 ; i < A.length-2 ; i++){ 32 | if(A[i] < 0 ) continue; 33 | if((long)A[i] + A[i+1] > A[i+2]) return 1; 34 | } 35 | return 0; 36 | } 37 | } 38 | ~~~ 39 | -------------------------------------------------------------------------------- /ETC/Ajax.md: -------------------------------------------------------------------------------- 1 | 2 | >(작성중) 3 | 4 | # Ajax 이 녀석! 5 | >토이프로젝트(Haru Sketch)에서 Ajax로 댓글을 구현하다가 에러 앞에 막혔다. 6 | >Ajax를 제대로 모르고 있다는 확신이 들어 Ajax 이 녀석을 박살내버리기로 했다.(엄근진) 7 | 8 | ### 한마디로 ? 9 | 10 | 11 | ### 작성중 12 | - 웹을 통해 작업할 때 REST 방식이 가장 많이 쓰이는 형태는 Ajax와 같이 결합된 형태이다. 13 | - Ajax는 'Asynchronous JavaScript and XML'(비동기화된 JavaScript와 XML)의 약어로 주로 브라우저에서 대화형으로 서버와 데이터를 주고받는 형태의 메세지 전송 방식을 의미한다. 14 | - Ajax를 가장 쉽게 설명하는 방법은 화면의 전환이나 깜빡임 없이 서버에서 데이터를 받는 방법이다. 15 | - 구글맵이나 포털사이트의 자동완성 기능들이 Ajax를 활용한 가장 대표적인 서비스이다. 16 | - 비동기화된(Asyschronous)의 의미는 결과의 데이터를 기다리는 방식이 아닌, 결과를 통보받는 형식이라고 볼 수 있다. 17 | - 대부분의 프로그래밍은 특정 로직을 호출하고, 결과를 받아서 다음 로직을 실행하는 방식이라면, 비동기화된 방식은 로직을 호출하고, 결과를 기다리지 않는다. 대신에 결과가 통보될 때 실행할 로직을 지정하는 방식이다. 18 | - REST 방식이 데이터를 호출하고 사용하는 방식을 의미한다면, Ajax는 실제로 그를 이용하는 수단에 가깝다. 19 | ## Ajax의 특징 20 | - 브라우저의 화면 전환이 없다. 21 | - 서버에서 화면에 필요한 모든 데이터를 만드는 대신, 서버는 필요한 데이터만 전달하기 때문에 개발의 무게 중심이 브라우저 쪽으로 많이 배분된다. 22 | - Ajax의 시작 시점에는 서버와 메세지 전달에 있어서 일반 텍스트나 XML을 주로 사용했지만 최근에는 JSON을 많이 사용한다. 23 | 24 | 25 | 26 | 27 | 28 | # Reference 29 | - 구멍가게코딩단,『코드로 배우는 스프링 웹 프로젝트』, 남가람북스, p.366~8 30 | - https://www.opentutorials.org/course/3281 31 | - http://krespo.net/55 32 | -------------------------------------------------------------------------------- /ETC/Bcrypt.md: -------------------------------------------------------------------------------- 1 | 2 | # Bcrypt 3 | >회사에서 쓰고있는 Bcrypt를 공부하다가 비밀번호 해싱에 대해 공부하였다. 4 | >직접 정리하려 했지만 [네이버 직원분들이 작성한 블로그에 정리가 잘 되어있어](https://d2.naver.com/helloworld/318732) 따로 정리할 필요를 못느꼈다. 5 | >[Bcrypt 개념에 대한 짧은 유튜브 영상](https://www.youtube.com/watch?v=O6cmuiTBZVs)에서 Bcrypt의 특징을 이해할 수 있었다. 6 | >[짧은 유튜브 강의](https://www.youtube.com/watch?v=YLCoDK0OwYM)도 Salting과 Peppering 개념을 잡는 데에 도움이 되었다. 7 | >한 편, 실무와 관련된 내용은 [이 번역글](http://starplatina.tistory.com/entry/%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%ED%95%B4%EC%8B%9C%EC%97%90-%EC%86%8C%EA%B8%88%EC%B9%98%EA%B8%B0-%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%93%B0%EA%B8%B0)에서 얻을 수 있었다. 8 | 9 | # *Reference 10 | - https://d2.naver.com/helloworld/318732 11 | - http://starplatina.tistory.com/entry/%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%ED%95%B4%EC%8B%9C%EC%97%90-%EC%86%8C%EA%B8%88%EC%B9%98%EA%B8%B0-%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%93%B0%EA%B8%B0 12 | - https://www.youtube.com/watch?v=YLCoDK0OwYM 13 | - https://www.youtube.com/watch?v=O6cmuiTBZVs 14 | -------------------------------------------------------------------------------- /ETC/CDATA.md: -------------------------------------------------------------------------------- 1 | # CDATA 섹션 2 | - CDATA 섹션에 의해 포함된 문자에 태그(>,<)가 없음을 파서에 알릴 수 있다. 3 | ~~~xml 4 | 15 | ~~~ 16 | 17 | # Reference 18 | - https://msdn.microsoft.com/ko-kr/library/ms256076(v=vs.120).aspx 19 | -------------------------------------------------------------------------------- /ETC/HowTheWebWorks.md: -------------------------------------------------------------------------------- 1 | > *개인적인 학습을 위해 작성한 내용입니다. 옳은 내용만 작성하려 노력했지만 내용에 오류가 있을 수 있습니다.* 2 | 3 | > 면접에서 웹의 동작 원리에 대해 질문을 받았는데, 제대로 답변하지 못하고 Controller-Service-Dao-DB 정도로만 대답했다. 그래서 시작! 4 | # 웹의 동작 원리(How the web works) 5 | 0. Web은 분산환경을 기반으로 한다. 분산환경은 Client-Server 구조. 6 | 1. 클라이언트가 URL을 입력하면, 7 | 2. 브라우져가 DNS서버로 가서 요청한 URL의 실제 주소(IP)를 찾는다. 8 | 3. 브라우져는 서버에 웹사이트의 사본을 요청하는 HTTP 요청메세지를 보낸다. 9 | 4. 이러한 메세지와 데이터들은 TCP/IP 연결을 통해 클라이언트와 서버 사이에 전송된다. 10 | - *TCP는 한쪽 노드에서 다른 쪽 노드로 파일을 보내는 프로토콜(파일 분할하여 전송가능)* 11 | - *IP는 한 호스트에서 목적지 호스트까지 패킷을 옮기고 이동하기 위한 기반 프로토콜* 12 | - 서버 사이드는 웹서버 - 웹어플리케이션서버(WAS) - 데이터베이스로 구성된다. 13 | - **웹서버** 14 | - 브라우져의 요청을 받고 결과를 응답하는 역할 15 | - 정적인 페이지 처리 담당 16 | - 요청에 필요한 페이지 로직이나 DB와의 연동을 위해 WAS에 처리를 요청 17 | - ex) Apache 18 | - **WAS** 19 | - 요청된 URL에 맵핑된 페이지를 실행해서 결과를 웹서버에 반환 20 | - 페이지의 로직이나 데이터베이스와의 연동을 처리하는 역할 21 | - 동적인 페이지 처리 담당 22 | - 요청이 로드된 적이 있으면 새로운 쓰레드를 깨우고(Invoke Thread) Service()실행 23 | - 요청이 로드된 적이 없으면 새로운 인스턴스를 Init() -> Invoke Thread -> Service() -> Timeout되면 Destroy() 24 | - ex) Tomcat 25 | 5. 메세지를 받은 서버는 클라이언트의 요청을 승인하고 "200 OK" 메세지를 클라이언트에 전송한다. 26 | 6. 이후에 서버는 웹사이트의 데이터들을 데이터 패킷이라는 작은 덩어리로 뭉쳐서 브라우져에 전송한다. 27 | 7. 브라우져는 이 데이터패킷들을 조립해서 완전한 웹사이트를 클라이언트에게 보여준다. 28 | 29 | ## *Reference 30 | - Kathy Sierra, 『Head First Servlet & JSP』, O'REILLY, p44 31 | - https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/How_the_Web_works 32 | - https://d2.naver.com/helloworld/59361 33 | - https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/ 34 | - http://hoonmaro.tistory.com/26 35 | -------------------------------------------------------------------------------- /ETC/OAuth&JWT.md: -------------------------------------------------------------------------------- 1 | # OAuth2 와 JWT 2 | >실무에서 OAuth2와 JWT을 쓰게 되어 학습 내용을 정리한다. 3 | 4 | 5 | ## 한마디로 ? 6 | Json Web Token의 7 | 8 | ## OAuth2 구현 과정 9 | 1. `build.gradle`에 `spring-boot-stater-security` 와 `spring-security-oauth2`를 추가한다. 10 | 2. `@EnableAuthorizaionServer` 어노테이션을 붙일 클래스를 만들고, `AuthorizationServerConfigurerAdapter`를 상속받는다. 11 | 3. 2번의 클래스 안에 configure(ClientDetailsServiceConfigurer clients) 메소드를 만들어서 API의 요청 클라이언트 정보를 설정한다. 12 | ~~~java 13 | @Override 14 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 15 | clients.inMemory() 16 | .withClient("some_client_id") 17 | .secret("some_client_secret") 18 | .scopes("read:current_user", "read:users") 19 | .authorizedGrantTypes("client_credentials"); 20 | } 21 | ~~~ 22 | - `.inmemory()`는 클라이언트 정보를 메모리에 저장하므로 개발환경에 적합하다. (jdbc()는 데이터베이스에 저장하므로 운영환경에 적합) 23 | - `.withClient()`은 client id값 설정 24 | - `.secret()`은 client secret값 설정 25 | - `.authorizedGrantTypes()`는 Access Token을 획득하기 위한 4가지 인증 방법(grant types) 중 하나를 설정 26 | - Access Token을 획득하기 위한 4가지 인증 방법 (grant types) 27 | - Authorization Code Grant 28 | - Client Credentials Grant 29 | - Implicit Grant 30 | - Password Grant 31 | 4. 사용자 저장소 설정 32 | - 클라이언트와 토큰 관리는 Spring Security OAuth 모듈이 담당하지만, 사용자 관리는 Spring Security 담당 33 | ~~~java 34 | @Configuration 35 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 36 | 37 | @Override 38 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 39 | 40 | auth.inMemoryAuthentication() 41 | .withUser("user") 42 | .password("password") 43 | .roles("USER") 44 | .and() 45 | .withUser("admin") 46 | .password("password") 47 | .roles("USER", "ADMIN"); 48 | } 49 | } 50 | ~~~ 51 | 5. ClientDetailsService Bean 설정 52 | ## Reference 53 | - https://github.com/auth0/java-jwt 54 | - http://jsonobject.tistory.com/363 55 | - https://www.youtube.com/watch?v=CPbvxxslDTU&list=PL7ej4hCdlMAaA9uvDLANWqL0C0zeRgFbK 56 | -------------------------------------------------------------------------------- /ETC/PathVariable_QueryParameter.md: -------------------------------------------------------------------------------- 1 | # Path Variable과 Query Parameter는 언제 사용해야 할까? [번역] 2 | 3 | >원작자의 허락을 받고 번역한 글입니다. 4 | >원문: [When Should You Use Path Variable and Query Parameter?](https://medium.com/@fullsour/when-should-you-use-path-variable-and-query-parameter-a346790e8a6d) 5 | 6 | >역자 주: 7 | Spring boot와 Vue.js로 파일럿 프로젝트를 개발하던 중, 8 | 카테고리로 게시물 목록을 필터링할 때 @PathVariable로 카테고리 이름을 전달했더니, '/'가 포함된 카테고리 이름이 문제를 일으켰다. 9 | 알고 보니, 이 글에서 설명하는 것 처럼 Resource를 가져오는 Get 메소드는 PathVariable을 사용하고, 10 | 정렬(sort)이나 필터링을 하는 경우 QueryParam을 사용하는 것이 옳은 방법이었다. 11 | 12 | 이 글을 통해 PathVariable 과 Query Parameter 가 무엇이고, 어떻게 사용해야 하는지 이야기하고자 한다. 13 | 14 | ## 1. Query Parameter 15 | 당신이 웹 개발자라면, 가장 간단한 방법인 GET 메소드를 사용해서 데이터를 전송하는 방법을 배웠을 것이다. 16 | 소셜 서비스를 만든다고 가정해보자. 사용자 목록을 관리해야 하고, 모든 사용자는 사용자 페이지가 있어야 할 것이다. 17 | 18 | 그리고 각각의 사용자를 위한 페이지를 만들려면 페이지 마다 식별된 파라미터 경로가 필요한데, 19 | 다음과 같은 get 파라미터를 사용할 수 있을 것이다. 20 | 21 | ~~~yml 22 | /users?id=123 # 아이디가 123인 사용자를 가져온다. 23 | ~~~ 24 | 25 | 그럼 서버로 부터 id 변수를 얻을 수 있다. 이것이 Query String이 동작하는 방식이다. 26 | (이 글에서는 서버단에서의 동작까지는 설명하지 않을 것이다.) 27 | 28 | 29 | ## 2. Path Variable 30 | 하지만 데이터를 넘기는 방법 중의 하나로 Path Variable도 사용할 수 있다. 31 | Path Variable은 다음과 같이 사용한다. 32 | 33 | ~~~yml 34 | /users/123 # 아이디가 123인 사용자를 가져온다. 35 | ~~~ 36 | 37 | 이 경우에, 123 을 서버단에 전달한다. 경로를 변수로서 사용하는 것이다. 38 | 39 | 40 | ## 3. 그럼 Path Variable과 Query Parameter를 각각 언제 사용해야 하는가? 41 | 42 | 만약 어떤 **resource를 식별**하고 싶으면 **Path Variable**을 사용하고, 43 | **정렬이나 필터링**을 한다면 **Query Parameter**를 사용하는 것이 Best Practice이다. 44 | 45 | ~~~yml 46 | /users # 사용자 목록을 가져온다. 47 | /users?occupation=programer # 프로그래머인 사용자 목록을 가져온다. 48 | /users/123 # 아이디가 123인 사용자를 가져온다. 49 | ~~~ 50 | 51 | 또한, 기본적인 CRUD 기능을 위해서 또 다른 URL이나 query parameter를 정의할 필요는 없다. 52 | 대신 원하는 기능에 맞게 HTTP 메소드를 바꾸어야 한다. 53 | 54 | ~~~yml 55 | /users [GET] # 사용자 목록을 가져온다. 56 | /users [POST] # 새로운 사용자를 생성한다. 57 | /users/123 [PUT] # 사용자를 갱신한다. 58 | /users/123 [DELETE] # 사용자를 삭제한다. 59 | ~~~ 60 | 61 | 그렇다! 거의 모든 CRUD 프로세스를 62 | 추가적인 endpoint(예를 들어 users/create) 또는 63 | query parameter(예를 들어 users?action=create) 없이 수행할 수 있다. 게다가 단순하고 예측 가능하다. 64 | 65 | 66 | ## 4. 정리 67 | 68 | 앞서 말한 방법대로 구현하지 않아도 동작하는 API를 만들 수는 있다. 69 | 하지만 훨씬 복잡해질 것이고 개발속도를 늦출 것이다. 70 | 개발 효율을 최대한 끌어 올리고 다른 개발자들과의 협업을 고려하면, 표준이 되는 방법과 best practice를 따르는 것이 좋다. 71 | 72 | 마지막으로, References의 링크들을 통해 RESTful API를 설계하는 또 다른 best practice들을 확인할 수 있다. 73 | 74 | ## References 75 | - [Best Practices for Designing a Pragmatic RESTful API](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api) 76 | - [RESTful API Designing guidelines — The best practices](https://hackernoon.com/restful-api-designing-guidelines-the-best-practices-60e1d954e7c9) 77 | - [RESTful API Design. Best Practices in a Nutshell](https://phauer.com/2015/restful-api-design-best-practices/) 78 | -------------------------------------------------------------------------------- /ETC/RegEx.md: -------------------------------------------------------------------------------- 1 | # Regular Expression 정리 2 | 3 | ## 1. 정규식 메타 문자 4 | >메타 문자는 특정한 문자 혹은 문자 계열을 대신하여 표시하는 문자. 5 | 6 | 메타 문자 | 의미 | 예시 7 | ---- | ---- | ---- 8 | ^ | 문자열의 시작 | `^ryan`은 문자열의 첫 부분에 ryan이 온 경우에 매치 9 | $ | 문자열의 끝 | `ryan$`는 문자열이 ryan으로 끝난 경우에 ryan에 매치 10 | \b | 단어의 경계, 공백, 탭, 콤마, 대시 등 | `\bRyan\b`는 ryan의 양 끝에 단어 경계가 오는 경우에만 Ryan에 매치. 따라서 RyanHan의 경우 Ryan은 매치되지 않는다. 11 | \B | \b가 아닌 것 | \bRyan\B는 Ryan에 매치하지 않지만, RyanHan에 매치 12 | \s | 공백 문자 | 공백, 탭에 매치 13 | \S | 공백 문자가 아닌 것 | 공백 문자가 아닌 모든 문자에 매치 14 | \d | 숫자 | [0-9] 와 같다 15 | \D | 숫자가 아닌 것 | [^0-9] 와 같다 16 | \w | 알파벳 로마자 | 17 | \W | 알파벳 로마자가 아닌 것 | 18 | \n, \r | 개행 문자 및 캐리지 리턴에 매치 | 19 | \ | Escape | 20 | . | 문자 하나에 대응 | 21 | 22 | ## 2. 선택 패턴 23 | 선택 패턴 | 의미 | 예시 24 | ---- | ---- | ---- 25 | \| | 또는 | `Ryan\|Emily` 라고 쓰면 Ryan과 Emily 모두에게 매칭 26 | [...] | 대괄호 속 문자 중에 하나에 매칭 | `[cfh]all` 패턴은 call, fall, hall 모두에 매치 27 | [0-9] | 숫자 | 28 | [a-z] | 알파벳 소문자 | 29 | [A-Z] | 알파벳 대문자 | 30 | [ㄱ-힣] | 한글 | 유니코드를 지원하는 정규식에서만 31 | \^ | Not의 의미 | 선택 패턴 내에서 ^ 쓰일 때 32 | 33 | ## 3. 그룹 34 | >괄호()는 그룹을 의미한다. 35 | 36 | 예시 | 의미 37 | -- | -- 38 | (tom\|pot)ato | tomato, potato에 모두 매치되는 패턴 39 | (r\|y){3}an | r 또는 y가 3개 온 후에 an이 오는 패턴 40 | (r\|y){3}an\1 | r 또는 y 중 세 글자를 그룹으로 캡쳐하고, an 뒤에 캡쳐한 글자가 반복되는 패턴. 41 | (?: ) | 그룹으로 묶어주지만 캡쳐는 하지 않는 그룹 42 | 43 | 44 | ## 4. 수량 한정자 45 | >동일한 개체가 n 개 나오는 경우에 수량 한정자를 뒤에 붙일 수 있다. 46 | 47 | 표현 | 의미 | 예시 48 | ---- | ---- | ---- 49 | \? | 앞의 개체가 없을 수 있다. | `ryans?`는 ryan과 ryans에 매치 50 | \* | 앞의 표현이 0개 이상 | `n\d*` n, n1, n100, n9999 등에 매치 51 | \+ | 앞의 표현이 1개 이상 | `n\d+` 위의 예시에서 n은 매치되지 않는다. 52 | {n} | 앞의 표현이 n개 | `n\d{3}`은 n 뒤에 숫자가 3개 온다는 의미. 53 | {n,} | 앞의 표현이 n개 이상 | 54 | {n,m} | 앞의 표현이 n개 이상 m개 이하 | 수량이 n~m 사이에 있는 조건 55 | 56 | > `*`, `+`는 최대한 매치한다 57 | >> `There are apples and peaches` 라는 문장에서 58 | >>`^.*s`는 `There are apples and peaches` 전체를 매치하고, 59 | >>>`^.*?s`는 `There are apples`까지만 매치한다. 60 | 61 | 62 | ## *Reference 63 | - https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/%EC%A0%95%EA%B7%9C%EC%8B%9D 64 | - https://soooprmx.com/archives/7718 65 | -------------------------------------------------------------------------------- /ETC/StringUtils.md: -------------------------------------------------------------------------------- 1 | # StringUtils 2 | >Apache에서 제공하는 라이브러리 3 | >String 문자열에 대해 NullpointerException의 발생 없이 사용할 수 있다. 4 | 5 | ## 종류 6 | - `StringUtils.isEmpty(member.getMemName())` 7 | - Empty 8 | - StringUtils.isEmpty() 9 | - StringUtils.isNotEmpty() 10 | - StringUtils.isAnyEmpty() 11 | - StringUtils.isNoneEmpty() 12 | - StringUtils.isAllEmpty() 13 | - Blank 14 | - StringUtils.isBlank() 15 | - StringUtils.isNotBlank() 16 | - StringUtils.isAnyBlank() 17 | - StringUtils.isNoneBlank() 18 | 19 | # *Reference 20 | - http://hahaha2016.tistory.com/4 21 | -------------------------------------------------------------------------------- /ETC/TemplateEngines.md: -------------------------------------------------------------------------------- 1 | # 텍스트 템플릿 엔진 비교 (작성중) 2 | 3 | 4 | Template Engine? 5 | 템플릿 엔진은 "프로그램 로직" <-> "프리젠테이션" 계층을 분리하기 위한 수단 6 | 예를 들어 Controller -> View로 데이터를 던지면 어떻게 계층을 분리하여 쉽게 표현할지를 도와주는 "도구" 7 | 프리젠테이션 계층에서 로직을 쉽게 표현하고 개발의 유연성을 향상 시킴 & 유지보수 효율 향상 (과연?) 8 | 9 | ## Mustache 10 | 11 | ## Handlebars 12 | 13 | - Mustache의 파생인 handlebars.js의 자바 구현체인 handlebars.java 사용 14 | - handlebars.js는 Javascript 라이브러리로 렌더링이 끝난 뒤(즉, HTML Dom이 다 그려진 뒤)에 서버 통신 없이 화면 변경이 필요한 경우를 위한 것(출처 : https://jojoldu.tistory.com/23) 15 | - 컴파일된 템플릿에 모델을 반영하여 뷰를 구성하는 방식이죠. 모델을 한번 뷰에 반영해주고 끝이기 때문에 초기 랜더링 속도면에서 더 유리하지만, 양방향 구조가 아니기 때문에 이미 랜더링 된 뷰의 내용을 바꾸고 해당 내용을 다시 모델에 반영하려면 별도의 작업이 필요합니다. 16 | (출처 : https://tmondev.blog.me/220398995882 ) 17 | - 가장 큰 차이는 Mustache가 codeless를 지향하고 있어 코드의 중간 가공에 제약이 많은 반면 Handlebars.js는 사용자 정의 함수라고 볼 수 있는 헬퍼(Helper) 개념을 도입하여 이 제약을 상당히 덜어냈다는 점을 들 수 있겠습니다. 서버에서 받아온 json 데이터를 필요에 따라 간편하게 가공하여 사용할수 있다는 점이 Handlebars.js의 가장 큰 매력이지만, 템플릿 자체에 선언하는 로직은 최소화 함으로써 Mustache가 애초에 표방한 logic-less의 원칙을 크게 훼손하지 않았다는 점도 Handlebars의 매력이라고 할 수 있겠습니다. 18 | (출처 : https://tmondev.blog.me/220398995882 ) 19 | 20 | - 현재까지도 꾸준하게 업데이트 되고 있는 템플릿 엔진은 Thymeleaf, Handlebars 이며 이 중 하나를 선택하시면 됩니다. 21 | 개인적으로는 Handlebars를 추천합니다. 22 | (Spring 진영에선 Thymeleaf를 밀고 있습니다.) 23 | (1) 문법이 다른 템플릿엔진보다 간단하고 24 | (2) 로직 코드를 사용할 수 없어 View의 역할과 서버의 역할을 명확하게 제한할 수 있으며 25 | (3) Handlebars.js와 Handlebars.java 2가지가 다 있어, 하나의 문법으로 클라이언트 템플릿/서버 템플릿을 모두 사용할 수 있습니다. 26 | 개인적으로 View 템플릿엔진은 View의 역할에만 충실하면 된다고 생각합니다. 27 | 너무 많은 기능을 제공하면 API와 View템플릿엔진, JS가 서로 로직을 나눠갖게 되어 유지보수하기가 굉장히 어렵습니다. 28 | (출처 : https://jojoldu.tistory.com/23) 29 | 30 | ## Thymeleaf 31 | -------------------------------------------------------------------------------- /ETC/http.md: -------------------------------------------------------------------------------- 1 | # 를 읽고. 2 | >웹개발자의 필독서인 를 읽고 중요한 내용을 내 언어로 작성. 3 | 4 | 1. 사용자가 URL을 입력하면, 웹브라우져가 URL에서 호스트명을 추출하여 DNS를 통해 IP로 변환다. 5 | 또한 URL에서 포트번호를 추출하여, IP와 포트번호를 사용하여 웹서버와 TCP/IP 커넥션을 맺는다. 6 | 이제 웹브라우저는 웹서버에 HTTP 요청을 보내고, 웹서버는 HTTP 응답을 반환한다. 7 | 커넥션이 닫히면 웹브라우저는 사용자가 요청한 문서를 보여준다. 8 | -------------------------------------------------------------------------------- /ETC/images/Connectingthedots.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/Connectingthedots.jpg -------------------------------------------------------------------------------- /ETC/images/JAXB_architecture.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/JAXB_architecture.gif -------------------------------------------------------------------------------- /ETC/images/K-009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/K-009.png -------------------------------------------------------------------------------- /ETC/images/README.md: -------------------------------------------------------------------------------- 1 | # Images for TIL/ETC 2 | -------------------------------------------------------------------------------- /ETC/images/StockInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/StockInfo.png -------------------------------------------------------------------------------- /ETC/images/VirtualTopics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/VirtualTopics.png -------------------------------------------------------------------------------- /ETC/images/activemq/README.md: -------------------------------------------------------------------------------- 1 | ## Amazon MQ(Active MQ) 관련 이미지 2 | -------------------------------------------------------------------------------- /ETC/images/activemq/VirtualTopics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/VirtualTopics.png -------------------------------------------------------------------------------- /ETC/images/activemq/activemq_xml_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/activemq_xml_1.png -------------------------------------------------------------------------------- /ETC/images/activemq/activemq_xml_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/activemq_xml_2.png -------------------------------------------------------------------------------- /ETC/images/activemq/aws_sqs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/aws_sqs.png -------------------------------------------------------------------------------- /ETC/images/activemq/aws_sqs_tv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/aws_sqs_tv.png -------------------------------------------------------------------------------- /ETC/images/activemq/news_hub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/news_hub.png -------------------------------------------------------------------------------- /ETC/images/activemq/pubsub_activemq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/pubsub_activemq.png -------------------------------------------------------------------------------- /ETC/images/activemq/pubsub_amazonmq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/pubsub_amazonmq.png -------------------------------------------------------------------------------- /ETC/images/activemq/queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/queue.png -------------------------------------------------------------------------------- /ETC/images/activemq/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/thumbnail.png -------------------------------------------------------------------------------- /ETC/images/activemq/topics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/topics.png -------------------------------------------------------------------------------- /ETC/images/activemq/virtual_topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/activemq/virtual_topic.png -------------------------------------------------------------------------------- /ETC/images/apply2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/apply2.png -------------------------------------------------------------------------------- /ETC/images/books.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/books.jpg -------------------------------------------------------------------------------- /ETC/images/by20182.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/by20182.png -------------------------------------------------------------------------------- /ETC/images/cmts1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/cmts1.png -------------------------------------------------------------------------------- /ETC/images/cmts2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/cmts2.png -------------------------------------------------------------------------------- /ETC/images/cmts3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/cmts3.png -------------------------------------------------------------------------------- /ETC/images/exampleGist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/exampleGist.png -------------------------------------------------------------------------------- /ETC/images/fb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/fb.jpg -------------------------------------------------------------------------------- /ETC/images/fbf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/fbf.png -------------------------------------------------------------------------------- /ETC/images/goqual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/goqual.png -------------------------------------------------------------------------------- /ETC/images/jpa_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/jpa_table.png -------------------------------------------------------------------------------- /ETC/images/jpa_table2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/jpa_table2.png -------------------------------------------------------------------------------- /ETC/images/kakao.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/kakao.jpg -------------------------------------------------------------------------------- /ETC/images/lee.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/lee.gif -------------------------------------------------------------------------------- /ETC/images/mydesk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/mydesk.jpg -------------------------------------------------------------------------------- /ETC/images/myfirstPR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/myfirstPR.png -------------------------------------------------------------------------------- /ETC/images/myfirstPR2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/myfirstPR2.png -------------------------------------------------------------------------------- /ETC/images/myfirstPR3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/myfirstPR3.png -------------------------------------------------------------------------------- /ETC/images/myfirstPR4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/myfirstPR4.png -------------------------------------------------------------------------------- /ETC/images/nadal1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/nadal1.jpg -------------------------------------------------------------------------------- /ETC/images/okky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/okky.png -------------------------------------------------------------------------------- /ETC/images/oracleExpert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/oracleExpert.png -------------------------------------------------------------------------------- /ETC/images/planner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/planner.png -------------------------------------------------------------------------------- /ETC/images/planner2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/planner2.png -------------------------------------------------------------------------------- /ETC/images/queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/queue.png -------------------------------------------------------------------------------- /ETC/images/ryanjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/ryanjs.png -------------------------------------------------------------------------------- /ETC/images/sist.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/sist.jpg -------------------------------------------------------------------------------- /ETC/images/topics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Integerous/TIL/a00f1797d5b9fc09d145bd1cf43c193aad37e482/ETC/images/topics.png -------------------------------------------------------------------------------- /ETC/resumeKOR.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # 한정수 5 | 사람들이 필요로 하는 것을 만들 때 가장 행복한 주니어 백엔드 개발자입니다. 6 | 인생 첫 "Hello World"를 찍어본지 아직 1년이 안되었지만, 7 | 믿고 함께할 수 있는 동료 개발자가 되기 위해 열심히 성장하고 있습니다. 8 | 9 | >Github - https://github.com/Integerous 10 | >Blog - https://ryan-han.com 11 | >Email - rhep0820@gmail.com 12 | >Tel - 010 9189 1441 13 | 14 | ## :briefcase: WORK EXPERIENCE 15 | 16 | - ### **클라우드 캐시 (CLOUD CASH)** 17 | >- **주니어 백엔드 개발자** 18 | >- **Jun 2018 - Jan 2019** 19 | >- Back Office 관리자 페이지 개발 20 | >- 카카오톡 챗봇 프로토타입 개발 21 | >- Git-flow를 활용한 코드 리뷰 환경 구성 22 | 23 | - ### **현대 글로비스 (HYUNDAI GLOVIS)** 24 | >- **Bulk Carrier Operator** 25 | >- Jan 2017 - Jul 2017 26 | - ### **데상트 코리아 (DESCENTE KOREA)** 27 | >- **Sports Marketer (Intern)** 28 | >- Jul 2015 - Aug 2015 29 | - ### **EMPORIO ARMANI (San Francisco)** 30 | >- **Assistant (Intern)** 31 | >- Mar 2013 - Jul 2013 32 | 33 | ## :mortar_board: EDUCATION 34 | - ### **쌍용교육센터 (Ssangyong Institute of System Technology)** 35 | >- Dec 2017 - Jun 2018 36 | >- Java 웹 개발자 양성 과정 37 | 38 | - ### **서울대학교 (Seoul National University)** 39 | >- Mar 2009 - Feb 2017 40 | >- 사범대학 체육교육 전공 41 | >- Bachelor of Sports Science 42 | 43 | ## :books: PROJECTS 44 | - ### **고퀄리티 개발 컨텐츠 모음 (goQuality Dev Contents)** 45 | >- 고퀄리티의 개발 관련 컨텐츠(글, 영상, 슬라이드)를 아카이빙하는 오픈소스 프로젝트 46 | >- 이메일 구독 서비스와 웹사이트로 확장 개발하기 위해 기획중 47 | >- https://github.com/Integerous/goQuality-dev-contents 48 | - ### **개인블로그 (Integerous Devlog)** 49 | >- Static website generator인 Hugo와 Github page를 사용하여 만든 개인 블로그 50 | >- https://ryan-han.com 51 | - ### **카카오톡 챗봇 (공식 API 사용)** 52 | >- 카카오톡 플러스친구 API를 사용하여 만든 고객 응대용 챗봇 53 | >- Chat bot - http://pf.kakao.com/_xoEBQC 54 | >- Code - https://github.com/Integerous/Kakao-ChatBot-Java 55 | - ### **카카오톡 챗봇 (비공식 어플 사용)** 56 | >- 비공식 카카오톡 챗봇 어플을 사용하여 만든 개인용 챗봇 57 | >- 지인들과의 단톡방에서 유용하게 사용중입니다. 58 | >- Code - https://github.com/Integerous/Kakao-ChatBot-Javascript 59 | - ### **하루스케치 (Haru Sketch)** (미완성) 60 | >- 수공예품 디자이너(와이프)를 위한 포트폴리오 겸 쇼핑몰 프로젝트 61 | >- Code (Spring boot version) - https://github.com/Integerous/haru-sketch 62 | >- Code (Spring framework version) - https://github.com/Integerous/HaruSketch-ver.1 63 | 64 | ## :zap: SKILLS 65 | - Java 66 | - Spring Framework / Spring Boot 67 | - Gradle / Maven 68 | - JPA / MyBatis 69 | - MySQL / PostgreSQL 70 | - AWS (EC2, S3, CodeDeploy, EBS, VPC) 71 | - JSP / Mustache / Thymeleaf 72 | - Linux 73 | - Shell Script 74 | - Nginx 75 | - Travis CI 76 | - Git / Github / Git-flow 77 | - Trello / Slack / Telegram 78 | -------------------------------------------------------------------------------- /Early-Bird/2018-09/2018-09-23.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #1 2 | >자바의 정석(남궁성 저) 학습 3 | >이 책을 한참 공부하다가 정보처리기사 필기 시험기간을 맞이해서 멈추었던 것 같다. 4 | 5 | ## 1. 다형성 (Polymorphism) 6 | - Java에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 하는 것. 7 | - 부모클래스 타입의 참조변수로 자식클래스의 인스턴스를 참조할 수 있도록 하는 것. 8 | - 참조변수의 타입이 참조변수가 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 개수를 결정한다. 9 | - 모든 참조변수는 null 또는 4 byte의 주소값이 저장된다. 10 | 11 | ## 2. 참조변수의 형변환 12 | - 부모타입의 참조변수를 자식타입의 참조변수로 변환하는 것 = down-casting (형변환 생략 불가) 13 | - 형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니기 때문에, 참조변수의 형변환은 인스턴스에 아무 영향 없다. 14 | - 컴파일 시, 참조변수 간의 타입만 체크하기 때문에 실행 시 생성될 인스턴스의 타입에 대해서는 알지 못하여 컴파일은 성공하더라도 실행 시 에러(ClassCastException)가 발생할 수 있다. 15 | 16 | ## 3. instanceof 연산자 17 | - 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 `instanceof` 연산자를 사용한다.(주로 조건문에 사용) 18 | - `instanceof`를 이용한 연산 결과로 `true`를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 뜻이다. 19 | ~~~java 20 | void doWork(Car c) { 21 | if (c instanceof FireEngine){ 22 | FireEngine fe = (FireEngine)c; 23 | fe.water(); 24 | ... 25 | }else if ... 26 | } 27 | ~~~ 28 | 29 | ## 4. 참조변수와 인스턴스의 연결 30 | - static 메소드는 static 변수처럼 참조변수의 타입에 영향을 받는다. 참조변수의 타입에 영향을 받지 않는 것은 인스턴스 메소드 뿐이다. 31 | - 따라서 static 메소드는 반드시 참조변수가 아닌 `클래스이름.메소드()`로 호출해야 한다. 32 | 33 | ## 5. 여러 종류의 객체를 배열로 다루기 34 | - 부모타입의 참조변수 배열을 사용하면, 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 수 있다. 35 | - `Vector`클래스는 내부적으로 `Object`타입의 배열을 가지고 있어서, 이 배열에 객체를 추가하거나 제거할 수 있다. 36 | ~~~java 37 | public class Vector extends AbstractList 38 | implements List, Cloneable, java.io.Serializable { 39 | protected Object elementData[]; 40 | ... 41 | } 42 | ~~~ 43 | - `Vector`클래스는 배열의 크기를 알아서 관리해주기 때문에 저장할 인스턴스의 개수에 신경 쓰지 않아도 된다. 44 | - `Vector`클래스는 단지 동적으로 크기가 관리되는 객체배열일 뿐이다. 45 | - `Vector item = new Vector();` 46 | -------------------------------------------------------------------------------- /Early-Bird/2018-09/2018-09-24.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #2 2 | >자바의 정석(남궁성 저) 학습 3 | >추석 전날이라 그런지 집중력이 조금 떨어졌다. 4 | 5 | ## 1. 추상 클래스 (Abstract class) 6 | - 미완성 메소드(추상메소드)를 포함하고 있다는 것을 제외하고는 일반클래스와 같다. 7 | - 추상메소드가 없어도 `abstract`를 붙여서 추상클래스로 지정할 수 있다. 8 | - 추상클래스는 인스턴스를 생성할 수 없다. 9 | - 추상클래스는 상속을 통해서 자손클래스에 의해서만 완성된다. 10 | ~~~java 11 | abstract class 클래스이름{ 12 | ... 13 | } 14 | ~~~ 15 | 16 | ## 2. 추상 메소드 (Abstract method) 17 | - 선언부만 작성하고 구현부는 작성하지 않은 것이 추상메소드. 18 | ~~~java 19 | /* 주석을 통해 기능 설명 */ 20 | abstract 리턴타입 메소드이름(); 21 | ~~~ 22 | - 추상클래스로부터 상속받는 자손클래스는 오버라이딩을 통해 조상인 추상클래스의 추상메소드를 모두 구현해야 한다. 23 | - 만약 부모로 부터 상속받은 추상메소드 중 하나라도 구현하지 않으면 자식클래스 역시 추상클래스로 지정해야 한다. 24 | 25 | ## 3. 인터페이스 26 | - 인터페이스는 일종의 추상클래스다. 27 | - 인터페이스는 추상클래스처럼 추상메소드를 갖지만, 추상클래스와 달리 몸통을 갖춘 일반 메소드 또는 멤버변수를 가질 수 없다. 28 | - 인터페이스는 오직 추상메소드와 상수만을 멤버로 가질 수 있다. 29 | 30 | ## 4. 인터페이스의 작성 31 | ~~~java 32 | interface PlayingCard { 33 | public static final int SPADE = 4; 34 | final int DIAMOND = 3; //public static final int DIAMOND = 3; 35 | static int HEART = 2; //public static final int HEART = 2; 36 | int CLOVER = 1; //public static final int CLOVER = 1; 37 | 38 | public abstract String getCardNumber(); 39 | String getCardKind(); //public abstract String getCardKind(); 40 | } 41 | ~~~ 42 | - 모든 멤버변수는 public static final 이어야하며, 이를 생략할 수 있다. 43 | - 모든 메서드는 public abstract 이어야하며, 이를 생략할 수 있다. 44 | - 단, jdk 1.8부터 static 메서드와 디폴트 메서트는 예외 45 | 46 | ## 5. 인터페이스의 상속과 구현 47 | - 인터페이스는 인터페이스로부터만 상속받을 수 있다. 48 | - 클래스와 달리 다중 상속이 가능하다. 49 | - 인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없다. 50 | - 클래스는 `extends`(확장하다) 사용, 인터페이스는 `implements`(구현하다) 사용. 51 | - 상속과 구현을 동시에 할 수 있다. 52 | ~~~java 53 | class Fighter extends Unit implements Fightable { 54 | public void move(int x, int y) { /* 내용 생략 */ } 55 | public void attack(Unit u) { /* 내용 생략 */ } 56 | } 57 | ~~~ 58 | -------------------------------------------------------------------------------- /Early-Bird/2018-09/2018-09-25.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #3 2 | >자바의 정석(남궁성 저) 학습 3 | >날씨가 많이 추워졌다. 아침 찬바람 맞고 코찔찔이 상태. 4 | 5 | ## 1. 인터페이스를 이용한 다형성 6 | - 리턴 타입이 인터페이스라는 것은 메소드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다. 7 | - ~~~java 8 | Fightable method() { 9 | ... 10 | Fighter f = new Fighter(); 11 | return f; 12 | ~~~ 13 | 14 | - repair 메소드의 매개변수의 타입을 Repairable로 선언하면, 이 메소드의 매개변수로 Repairable 인터페이스를 구현한 클래스의 인스턴스만 받아들여진다. 15 | - ~~~java 16 | interface Repairable() {} 17 | class SCV extends GroundUnit implements Repairable { 18 | ... 19 | } 20 | class Tank extends GroundUnit implements Repairable { 21 | ... 22 | } 23 | class Drop extends AirUnit implements Repairable { 24 | ... 25 | } 26 | ~~~ 27 | - ~~~java 28 | void repair(Repairable r) { 29 | // 매개변수로 넘겨받은 유닛을 수리한다. 30 | } 31 | ~~~ 32 | - 앞으로 새로운 클래스가 추가될 때, SCV의 repair 메소드에 의해 수리가 가능하도록 하려면 Repairable 인터페이스를 구현하면 된다. 33 | - 인터페이스 타입의 매개변수가 갖는 의미는 메소드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야 한다는 것이다. 34 | 35 | ## 2. default 메소드와 static 메소드 36 | - 인터페이스에 원래 추상메소드만 선언할 수 있었는데, JDK1.8부터 default 메소드와 static 메소드도 추가할 수 있게 되었다. 37 | - 인터페이스의 default메소드와 static메소드는 접근 제어자가 항상 public이며, 생략할 수 있다. 38 | - default 메소드는 추상메소드의 기본적인 구현을 제공하는 메소드이다. 39 | - default 메소드는 추상메소드가 아니기 때문에 default 메소드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다. 40 | - default 메소드는 추상메소드와 달리 일반 메소드처럼 몸통{}이 있어야 한다. 41 | 42 | ## 3. 내부클래스 43 | - 내부 클래스는 클래스 내에 선언된 클래스다. 44 | - 내부 클래스는 주로 AWT나 Swing과 같은 GUI어플리케이션의 이벤트처리 외에는 잘 사용하지 않는다. 45 | - 내부 클래스의 종류와 특징 46 | - instance class 47 | - 외부 클래스의 멤버변수 선언위치에 선언. 48 | - 외부 클래스의 인스턴스 멤버처럼 다루어진다. 49 | - 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언된다. 50 | - static class 51 | - 외부 클래스의 멤버변수 선언위치에 선언. 52 | - 외부 클래스의 static 멤버처럼 다루어진다. 53 | - 특히 static 메소드에서 사용될 목적으로 선언된다. 54 | - local class 55 | - 외부 클래스의 메소드나 초기화블럭 안에 선언. 56 | - 선언된 영역 내부에서만 사용될 수 있다. 57 | - anonymous class 58 | - 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용) 59 | -------------------------------------------------------------------------------- /Early-Bird/2018-09/2018-09-26.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #4 2 | >자바의 정석(남궁성 저) 학습 3 | >연휴 마지막 날. 날씨가 너무 좋아서 강아지 운동장에 가게되어 공부를 많이 못했다. 4 | 5 | ## 1. 예외 처리 (Exception handling) 6 | - 에러는 메모리 부족(OutOfMemoryError)이나 스택오버플로우(StackOverFlowError)처럼 일단 발생하면 복구할 수 없는 심각한 오류 7 | - 예외는 발생하더라도 수습될 수 있는 오류 8 | 9 | ## 2. 예외 클래스 계층 구조 10 | - Object 11 | - Throwable 12 | - ***Exception*** 13 | - ***RuntimeException*** 14 | - ArithmeticException 15 | - ClassCastException 16 | - NullPointerException 17 | - IndexOutOfBoundException 18 | - IOException 19 | - Error 20 | - 예외 클래스는 ***Exception*** 클래스와 자식들과 ***RuntimeException*** 클래스와 자식들로 나뉜다. 21 | - ***Exception*** 클래스들 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외 22 | - ***RuntimeException*** 클래스들 : 개발자의 실수로 발생하는 예외 23 | - 모든 예외 클래스는 Exception 클래스의 자손이므로, catch블럭의 괄호()에 Exception클래스 타입의 참조변수를 선언하면, 어떤 종류의 예외가 발생하더라도 이 catch블럭()에 의해서 처리된다. 24 | 25 | ## 3. printStackTrace()와 getMessage() 26 | - 예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨져 있으며, getMessage()와 printStackTrace()를 사용해서 이 정보를 얻을 수 있다. 27 | - `printStackTrace()` : 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메세지를 화면에 출력한다. 28 | - `getMessage()` : 발생한 예외클래스의 인스턴스에 저장된 메세지를 얻을 수 있다. 29 | 30 | ## 4. 멀티 catch 블럭 31 | - JDK1.7부터 여러 catch블럭을 `|`기호를 이용해서 하나의 catch 블럭으로 합칠 수 있다. 32 | ~~~java 33 | try { 34 | ... 35 | } catch (ExceptionA e) { 36 | e.printStackTrace(); 37 | } catch (ExceptionB e2) { 38 | e2.printStacktrace(); 39 | } 40 | ~~~ 41 | - 이 try-catch 문을 아래와 같이 바꿀 수 있다. 42 | ~~~java 43 | try { 44 | ... 45 | } catch (ExceptionA | ExceptionB e) { 46 | e.printStackTrace(); 47 | } 48 | ~~~ 49 | - 단, 예외클래스들이 조상-자손 관계에 있으면 컴파일 에러가 발생한다.(불필요한 코드는 제거하라는 의미의 에러) 50 | 51 | ## 5. 메소드에 예외 선언 52 | - 메소드에 예외를 선언하는 방법 53 | ~~~java 54 | void method() throws Exception1, Exception2, ... ExceptionN { 55 | ... 56 | } 57 | ~~~ 58 | - 메소드의 선언부에 예외를 선언함으로써 메소드를 사용하려는 사람이 메소드의 선언부를 보았을 때, 이 메소드를 사용하기 위해서는 어떠한 예외들이 처리되어져야 하는지 쉽게 알 수 있다. 59 | 60 | ## 6. finally 블럭 61 | - finally 블럭은 try-catch문과 함께 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킬 목적으로 사용된다. 62 | - finally 블럭은 try-catch문의 맨 마지막에 위치해야 한다. 63 | - try 블럭에서 return문이 실행되는 경우에도 finally블럭의 문장들이 먼저 실행된 후에, 현재 실행 중인 메소드를 종료한다. 64 | -------------------------------------------------------------------------------- /Early-Bird/2018-09/2018-09-27.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #5 2 | >자바의 정석(남궁성 저) 학습 3 | >5일 간의 연휴 이후 목요일에 찾아온 월요병.. 4 | 5 | ## 1. java.lang 패키지 6 | - java.lang 패키지의 클래스들은 import문 없이도 사용 가능하다. 7 | 8 | ## 2. Object 클래스 9 | - Object 클래스는 모든 클래스의 최고 조상 10 | - Object 클래스의 멤버들은 모든 클래스에서 바로 사용 가능 11 | - Object 클래스는 멤버변수는 없고 11개의 메소드만 있다. 12 | >- protected Object **clone()** : 객체 자신의 복사본 반환 13 | >- public boolean **equals(Object obj)** : 객체 자신과 객체 obj가 같은 객체인지 판단 14 | >- protected void **finalize()** : 객체가 소멸될 때 가비지콜렉터에 의해 자동으로 호출(거의 사용안함) 15 | >- public Class **getClasss()** : 객체 자신의 클래스 정보를 담고 있는 Class 인스턴스를 반환 16 | >- public int **hashCode()** : 객체 자신의 해시코드를 반환 17 | >- public String **toString()** : 객체 자신의 정보를 문자열로 반환 18 | >- public void **notify()** : 객체 자신을 사용하려고 기다리는 쓰레드를 하나만 깨운다. 19 | >- public void **notifyAll()** : 객체 자신을 사용하려고 기다리는 모든 쓰레드를 깨운다. 20 | >- public void **wait(long timeout, int nanos)** : 다른 쓰레드가 notify()나 notifyAll()을 호출할 때 까지 현재 쓰레드를 무한히 또는 지정된 시간동안 기다리게 한다. 21 | 22 | ## 3. equals(Object obj) 23 | - Object 클래스로부터 상속받은 equals 메소드는 두 개의 참조변수가 같은 객체를 참조하는지(두 참조변수에 저장된 주소값이 같은지) 판단 24 | - equals 메소드로 Value 인스턴스가 가지고 있는 value값을 비교하려면, 25 | Value 클래스에서 equals 메소드를 오버라이딩하여 주소가 아닌 객체에 저장된 내용을 비교하도록 변경해야 한다. 26 | 27 | ## 4. hashCode() 28 | - 해시함수는 찾는 값을 입력하면, 그 값이 저장된 위치를 알려주는 해시코드(hash code)를 반환한다. 29 | - 일반적으로 해시코드가 같은 두 객체가 존재하는 것이 가능하지만, 30 | Object 클래스에 정의된 hashCode 메소드는 객체의 주소값을 이용해서 해시코드를 만들어 반환하기 때문에 31 | 서로 다른 두 객체는 같은 해시코드를 가질 수 없다. 32 | - String 클래스는 문자열의 내용이 같으면 같은 해시코드를 반환하도록 hashCode메소드가 오버라이딩 되어 있기 때문에 33 | 문자열의 내용이 같은 str1과 str2에 대해 hashCode()를 호출하면 항상 동일한 해시코드 값을 얻는다. 34 | 35 | ## 5. toString() 36 | - Object 클래스에 정의된 toString() 37 | ~~~java 38 | public String toString() { 39 | return getClass().getName()+"@"+Integer.toHexString(hashCode()); 40 | } 41 | ~~~ 42 | - 클래스를 작성할 때 toString()을 오버라이딩 하지 않고, toString()을 호출하면 클래스이름+16진수의 해시코드를 반환한다. 43 | - String 클래스의 toString()은 String 인스턴스가 갖고 있는 문자열을 반환하도록 오버라이딩 되어 있다. 44 | - Date 클래스의 경우, Date 인스턴스가 갖고 있는 날짜와 시간을 문자열로 반환하도록 오버라이딩 되어 있다. 45 | -------------------------------------------------------------------------------- /Early-Bird/2018-09/2018-09-28.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #6 2 | >자바의 정석(남궁성 저) 학습 3 | ><우리는 이렇게 왔다> 읽기 4 | >하루가 30시간 이면 얼마나 좋을까. 5 | 6 | ## 1. clone() 7 | - 자신을 복제하여 새로운 인스턴스를 생성한다. 8 | - Object 클래스에 정의된 clone()은 단순히 인스턴스 변수의 값만 복사하기 때문에 9 | 참조타입의 인스턴스 변수가 있는 클래스는 완전한 인스턴스 복제가 이루어지지 않는다. 10 | - clone()은 반드시 예외처리를 해줘야 한다. 11 | 12 | ## 2. 공변 반환타입 (covariant return type) 13 | - JDK1.5부터 오버라이딩할 때 부모 메소드의 반환타입을 자식 클래스의 타입으로 변경 가능하다. 14 | - ~~~java 15 | public Point clone() { // 반환타입을 Object에서 Point로 변경 16 | Object obj = null; 17 | try { 18 | obj = super.clone(); 19 | } catch(CloneNotSupportedException e) {} 20 | return (Point)obj; //Point 타입으로 형변환 21 | ~~~ 22 | - 공변 반환타입을 사용하면 조상의 타입이 아닌, 실제로 반환되는 자손 객체의 타입으로 반환할 수 있어 번거로운 형변환이 줄었다. 23 | - `Point copy = (Point)original.clone();` -> `Point copy = original.clone();` 24 | 25 | ## 3. 배열 복사 26 | - 배열도 객체이기 때문에 Object 클래스를 상속받으며, 동시에 Cloneable 인터페이스와 Serializable 인터페이스가 구현되어 있다. 27 | - 일반적으로 배열을 복사할 때는 같은 길이의 새로운 배열을 생성한 다음 `System.arraycopy()`를 이용해서 내용을 복사하지만 `clone()`을 이용해서 간단하게 복사할 수 있다. 28 | - ~~~java 29 | int[] arr = {1,2,3,4,5}; 30 | int[] arrClone = arr.clone(); 31 | ~~~ 32 | - ~~~java 33 | int[] arr = {1,2,3,4,5}; 34 | int[] arrClone = new int[arr.length]; 35 | System.arraycopy(arr,0,arrClone,0,arr.length); 36 | ~~~ 37 | - 배열 뿐만 아니라 `java.util` 패키지의 38 | >Vector 39 | >ArrayList 40 | >LinkedList 41 | >HashSet 42 | >TreeSet 43 | >HashMap 44 | >TreeMap 45 | >Calendar 46 | >Date와 같은 클래스들도 복제가 가능하다. 47 | 48 | ## 4. 얕은 복사와 깊은 복사 (shallow copy & deep copy) 49 | - clone()은 객체에 저장된 값을 그대로 복제할 뿐, 객체가 참조하고 있는 객체까지 복제하지 않음 50 | - 원본과 복제본이 같은 객체를 참조 51 | - 이것이 얕은 복사(shallow copy) 52 | - 얕은 복사에서는 원본을 변경하면 복사본도 영향을 받는다. 53 | - 원본이 참조하고 있는 객체까지 복제하는 것이 깊은 복사(deep copy) 54 | - 원본과 복사본이 서로 다른 객체를 참조하기 때문에 원본의 변경이 복사본에 영향 없음 55 | 56 | ## 5. getClass() 57 | - 자신이 속한 클래스의 Class 객체를 반환하는 메소드 58 | - Class 객체는 이름이 'Class'인 클래스의 객체이다. 59 | ~~~java 60 | public final class Class implements ... { 61 | ... 62 | } 63 | ~~~ 64 | - Class 객체는 클래스의 모든 정보를 담고 있으며, 클래스 당 1개만 존재한다. 65 | - 클래스 파일이 'ClassLoader'에 의해 메모리에 올라갈 때 자동으로 생성 66 | - 파일 형태로 저장되어 있는 클래스를 읽어서 Class클래스에 정의된 형식으로 변환하는 것 67 | - 즉, 클래스 파일을 읽어서 사용하기 편한 형태로 저장한 것이 클래스 객체 68 | - Class 객체 얻는 방법 69 | - `Class cObj = new Card().getClass(); // 생성된 객체로 부터 얻기` 70 | - `Class cObj = Card.class; // 클래스 리터럴(*.class)로 부터 얻기` 71 | - `Class cObj = Class.forName("Card"); //클래스 이름으로 부터 얻기` 72 | - 객체 생성 73 | - `Card c = new Card(); // new연산자로 객체 생성` 74 | - `Card c = Card.class.newInstance(); // Class객체로 객체 생성` 75 | -------------------------------------------------------------------------------- /Early-Bird/2018-09/2018-09-29.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #7 2 | >자바의 정석(남궁성 저) 학습 3 | 4 | ## 1. String 클래스 5 | - String 클래스는 문자열을 저장하기 위해 문자형 배열 변수(char[]) value를 인스턴스 변수로 정의되어있다. 6 | - ~~~java 7 | public final class String implements java.io.Serializable, Comparable { 8 | private char[] value; 9 | ... 10 | } 11 | ~~~ 12 | - 인스턴스 생성 시 생성자의 매개변수로 입력받는 문자열은 인스턴스 변수 `value`에 문자형 배열 `char[]`로 저장되는 것이다. 13 | - String 클래스는 앞에 final이 붙어 있으므로 다른 클래스의 부모가 될 수 없다. 14 | - 변경 불가능한(Immutable) 클래스다. 15 | - 예를 들어 '+' 연산자를 이용해서 문자열을 결합하는 경우, 인스턴스 내의 문자열이 바뀌는 것이 아니라 새로운 문자열이 담긴 String 인스턴스가 생성되는 것이다. 16 | - 즉, 매 연산 마다 새로운 문자열을 가진 String 인스턴스가 생성되어 메모리 공간을 차지한다. 17 | ### 1.1. 문자열을 만드는 방법 2가지 18 | - `String str1 = "abc";` // 문자열 리터럴 "abc"의 주소를 str1에 저장 19 | - `String str2 = new String("abc");` // 새로운 String 인스턴스 생성 20 | - 문자열 리터럴은 이미 존재하는 것을 재사용 하는 것이다. (문자열 리터럴은 클래스가 메모리에 로드될 때 자동으로 미리 생성된다.) 21 | - ~~~java 22 | String str1 = "abc"; 23 | String str2 = "abc"; 24 | str1 == str2 ? true 25 | str1.equals(str2) ? true 26 | 27 | String str3 = new String("abc"); 28 | String str4 = new String("abc"); 29 | str3 == str4 ? false 30 | str3.equals(str4) ? true 31 | ~~~ 32 | ### 1.2. 문자열 리터럴 33 | - 클래스 파일에는 소스파일에 포함된 모든 리터럴의 목록이 있다. 34 | - 해당 클래스 파일이 클래스 로더에 의해 메모리에 올라갈 때, 리터럴 목록에 있는 리터럴들이 JVM내에 있는 상수 저장소(constant pool)에 저장된다. 35 | ### 1.3. 빈 문자열 36 | - 길이가 0인 배열은 존재한다.(C언어는 불가능) 37 | - char형 배열도 길이가 0인 배열 생성할 수 있고, 이 배열을 내부적으로 가지고 있는 문자열이 빈 문자열이다. 38 | - `String s = "";` 에서 참조변수 `s`가 참조하고 있는 String 인스턴스는 내부에 `new char[0]` 같이 길이가 0인 char형 배열을 저장하고 있는 것이다. 39 | - `char[] chArr = new char[0];` 40 | - `int[] iArr = {};` 41 | ### 1.4. `join()`과 `StringJoiner` (jdk1.8부터 추가) 42 | - `join()`은 문자열 사이에 구분자를 넣어서 결합 43 | - ~~~java 44 | String[] arr = { "dog", "cat", "bear"}; 45 | String str = String.join("-", arr); 46 | ~~~ 47 | - `java.util.StringJoiner`클래스 사용하여 문자열 결합 48 | - ~~~java 49 | StringJoiner sj = new StringJoiner("," , "[" , "]"); 50 | String[] strArr = { "aaa", "bbb", "ccc" }; 51 | for(String s : strArr) 52 | sj.add(s.toUpperCase()); 53 | 54 | System.out.println(sj.toString()); // [AAA,BBB,CCC] 55 | ~~~ 56 | ### 1.5. 기본형-String 변환 57 | - 숫자에 빈문자열("") 더하기 58 | - `valueOf()` 사용 59 | - ~~~java 60 | String str1 = 100 + ""; // 100 > "100" 61 | String str2 = String.valueOf(100); // 100 > "100" 62 | int i = Integer.parseInt("100") // "100" > 100 63 | int i2 = Integer.valueOf("100") // "100" > 100 64 | ~~~ 65 | - valueOf()의 반환타입은 int가 아니라 Integer지만 오토박싱에 의해 자동변환 66 | - `valueOf(String s)` 는 메소드 내부에 `parseInt(String s)`를 호출할 뿐이므로, 두 메소드는 반환 타입만 다르고 같은 메소드다. 67 | -------------------------------------------------------------------------------- /Early-Bird/2018-09/README.md: -------------------------------------------------------------------------------- 1 | # 2018년 9월의 아침공부 후기 2 | 3 | 1. 아침공부 시작 (9월 23일) 4 | 2. 출석률 100% (8일/8일) 5 | 3. 아침엔 공부하고, 퇴근 후에 복습하면서 정리하는 방식 채택 6 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-01.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #9 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >월요병은 난치병인가보다.. 다소 늦잠! 4 | 5 | ## 1. Calendar 와 Date 6 | - `Date`는 JDK1.0, `Calendar`는 JDK1.1 부터 제공되었다. 7 | - JDK1.8부터 `java.time 패키지`로 Calendar와 Date의 단점을 개선한 클래스들이 추가되었다. 8 | - `Calendar`는 추상클래스라서 객체를 직접 생성할 수 없고, 메소드를 통해서 완전히 구현된 클래스의 인스턴스를 얻어야 한다. 9 | ```java 10 | Calendar cal = new Calendar(); // 에러. 추상클래스는 인스턴스를 생성할 수 없다. 11 | Calendar cal = Calendar.getInstance(); 12 | // 굿. getInstance() 메소드는 Calendar 클래스를 구현한 클래스의 인스턴스를 반환한다. 13 | ``` 14 | - `getInstance()`가 `static`인 이유 15 | - 메소드 내의 코드에서 인스턴스 변수를 사용하거나 인스턴스 메소드를 호출하지 않기 때문 16 | - `static`이 아니라면 객체를 생성한 다음에 호출해야 하는데 Calendar는 추상클래스라 객체를 생성할 수 없기 때문 17 | 18 | ## 2. Calendar 와 Date 간 변환 19 | - Calendar가 추가되면서 Date는 대부분의 메소드가 `deprecated` 되었다. 20 | - Java API 문서에서 더 이상 사용을 권장하지 않는 대상에 `deprecated`를 붙였다. 21 | ```java 22 | //1. Calendar를 Date로 변환 23 | Calendar cal = Calendar.getInstance(); 24 | ... 25 | Date d = new Date(cal.getTimeInMillis()); 26 | 27 | //2. Date를 Calendar로 변환 28 | Date d = new Date(); 29 | ... 30 | Calendar cal = Calendar.getInstance(); 31 | cal.setTime(d); 32 | ``` 33 | - get(Calendar.MONTH)로 얻어오는 값은 1\~12가 아니라 0\~11이다. 그래서 0이 1월 11이 12월을 의미한다. 34 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-02.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #10 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >와이프가 아파서 내 마음도 아팠다. 4 | 5 | ## 1. Calendar 와 Date (이어서) 6 | ### 1.1. 두 날짜간의 차이 구하기 7 | - 두 날짜를 최소단위인 초단위로 변경한 다음 그 차이를 구한다. 8 | ### 1.2. 시간상의 전후 알기 9 | - 두 날짜간의 차이가 양수인지 음수인지 판단 10 | - `boolean after(Object when)` 또는 `boolean before(Object when)` 사용 11 | ### 1.3. 특정 날짜/시간 기준 일정 기간 전후의 날짜/시간 알기 12 | - `add(int field, int amount)` 13 | - `roll(int field, int amount)` 14 | - `add()`와의 차이점은 다른 필드에 영향 미치지 않음 15 | - 단, Calendar.DATE가 말일일 때, `roll`로 Calendar.MONTH를 변경하면 Calendar.DATE 필드에 영향을 미친다. 16 | ### 1.4. 해당 월의 마지막날 알기 17 | - 다음 달의 1일에서 하루 빼기 18 | - `getActualMaximum(Calendar.DATE)` 사용 19 | ### 1.5. 일 수 계산 20 | - Calendar는 1970년 1월 1일을 기준으로 계산 21 | - 1970년 1월 1일 이전에 날짜에 대해 `getTimeInMillis()`를 호출하면 음수 반환 22 | 23 | ## 2. 형식화 클래스 24 | 25 | ### 2.1. DecimalFormat 26 | - DecimalFormat을 이용하면 숫자 데이터를 정수, 부동소수점, 금액 등의 다양한 형식으로 표현할 수 있다. 27 | - 반대로 일정한 형식의 텍스트 데이터를 숫자로 쉽게 변환 28 | - 형식화 클래스는 패턴을 정의하는 것이 전부다. 29 | - DecimalFormat 사용법 30 | - ```java 31 | double number = 1234567.89; 32 | DecimalFormat df = new DecimalFormat("#.#E0"); // 1.원하는 출력형식의 패턴을 작성하여 DecimalFormat 인스턴스를 생성 33 | String result = df.format(number); // 2.출력하고자 하는 문자열로 format 메소드를 호출 34 | ``` 35 | ### 2.2. SimpleDateFormat 36 | - 날짜 데이터를 원하는 형태로 다양하게 출력 37 | - 사용방법 38 | - 원하는 출력 형식의 패턴을 작성하여 SimpleDateFormat 인스턴스를 생성 39 | - 출력하고자 하는 Date 인스턴스를 가지고 format(Date d)를 호출 40 | - ```java 41 | Date today = new Date(); 42 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); 43 | String result = df.format(today); //오늘 날짜를 yyyy-MM-dd 형태로 반환 44 | ``` 45 | - `parse(String source)`를 사용하여 날짜 데이터의 출력형식 변환 가능 46 | - SimpleDateFormat의 `parse(String source)`는 문자열 source를 날짜 Date 인스턴스로 변환해줌 47 | - ```java 48 | DateFormat df = new SimpleDateFormat("yyyy년 MM월 dd일"); 49 | DateFormat df2 = new SimpleDateFormat("yyyy/MM/dd"); 50 | Date d = df.parse("2018년 10월 3일"); 51 | 52 | System.out.println(df2.format(d)); // 2018/10/03 53 | ``` 54 | 55 | ### 2.3. ChoiceFormat 56 | - ChoiceFormat은 특정 범위에 속하는 값을 문자열로 변환 57 | - 연속적/불연속적인 범위의 값 처리에 유용(예를 들어 90점까지 A, 80점까지 B, ..) 58 | - 패턴을 사용할 경우 `limit#value` 형태로 사용 59 | - 구분자로 `#`는 경계값 포함, `<`는 미포함 60 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-03.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #11 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >개천절은 수요일이 제맛! 4 | 5 | ## 1. java.time 패키지 6 | Java의 탄생과 함께한 Date와 Calendar의 단점을 해소하기 위해 7 | JDK 1.8부터 `java.time 패키지`가 추가되었다. 8 | 이 패키지는 4개의 하위 패키지가 있다. 9 | 10 | `java.time` - 날짜와 시간을 다루는데 필요한 핵심 클래스들 제공 11 | - `java.time.chrono` - 표준(ISO)이 아닌 달력 시스템을 위한 클래스들 제공 12 | - `java.time.format` - 날짜와 시간을 파싱, 형식화하기 위한 클래스들 제공 13 | - `java.time.temporal` - 날짜와 시간의 필드와 단위(unit)을 위한 클래스들 제공 14 | - `java.time.zone` - 시간대(time-zone)와 관련된 클래스들 제공 15 | 16 | ### 1.1 Immutable & Thread-safe 17 | 위 패키지의 클래스들은 String 클래스처럼 `Immutable`이다. 18 | 즉, 날짜나 시간을 변경하면 기존의 객체가 변경되는 것이 아니라, 새로운 객체를 반환한다. 19 | 기존의 Calendar 클래스는 변경가능 하므로 멀티쓰레드 환경에서 안전하지 않았다. 20 | 21 | 멀티쓰레드 환경에서는 여러 쓰레드가 동시에 같은 객체에 접근할 수 있어서 22 | 변경 가능한 객체의 데이터가 잘못 될 가능성이 있다. 23 | 이를 쓰레드 안전(Thread-safe)하지 못하다고 한다. 24 | 25 | ## 2. java.time 패키지의 핵심 클래스 26 | 시간을 표현할 때는 `LocalTime`, 27 | 날짜를 표현할 때는 `LocalDate`, 28 | 모두 표현할 때는 `LocalDateTime`, 29 | 시간대(time-zone)까지 표현하려면 `ZonedDateTime` 사용 30 | 31 | ### 2.2. 타임스탬프(time-stamp) 32 | 날짜와 시간을 초단위로 표현한 값. 33 | 이 값은 날짜와 시간을 하나의 정수로 표현할 수 있어서 34 | 날짜와 시간의 차이를 계산하거나 순서를 비교하는데 유리하다. (그래서 데이터베이스에서 많이 사용) 35 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-04.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #12 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >군입대한지 정확히 8년이 지남..(무의미) 4 | >꿈에서 어떤 코드를 리뷰하고 있었다. 5 | >모닝콜에 살짝 정신이 들었을 때, '꿈에서 코드 보고있으니까 더 자도 되겠지'라고 더 자버렸다. 6 | >정작 어떤 코드였는지 기억이 안난다... 앞으론 꿈에서 일어나는 일을 존중하지 말아야겠다. 7 | 8 | ## 1. java.time 패키지 (이어서) 9 | 10 | ### 1.1. 객체 생성하기 11 | java.time 패키지에 속한 클래스의 객체 생성은 `now()`와 `of()`로 한다. 12 | - now() 예시 13 | ~~~java 14 | LocalDate date = LocalDate.now(); 15 | LocalTime time = LocalTime.now(); 16 | ~~~ 17 | - of() 예시 18 | ~~~java 19 | LocalDate date = LocalDate.of(2010, 10, 04); // 2010년 10월 4일 (군입대날ㅋ) 20 | LocalTime time = LocalTime.of(23, 59, 59); // 23시 59분 59초 21 | ~~~ 22 | 23 | ### 1.2. 필드 값 변경하기 24 | 날짜와 시간에서 특정 필드 값을 변경하려면 `with`로 시작하는 메소드 사용 25 | - 종류 26 | ~~~java 27 | LocalDate withYear(int year) 28 | LocalDate withMonth(int month) 29 | LocalDate withDayOfMonth(int dayOfMonth) 30 | LocalDate withDayOfYear(int dayOfYear) 31 | 32 | LocalTime withHour(int hour) 33 | LocalTime withMinute(int minute) 34 | LocalTime withSecond(int second) 35 | LocalTime withNano(int nanoOfSecond) 36 | ~~~ 37 | - `with()` 사용시 원하는 필드를 직접 지정 가능 38 | ~~~java 39 | LocalDate with(TemporalField field, long newValue) 40 | ~~~ 41 | - 필드를 변경하는 메소드들은 항상 새로운 객체를 생성해서 반환하므로 대입연산자를 같이 사용해야 한다. 42 | ~~~java 43 | date = date.withYear(2018); // 년도를 2018년으로 변경 44 | time = time.withHour(12); // 시간을 12시로 변경 45 | ~~~ 46 | - LocalTime의 `truncatedTo()`는 지정된 것보다 작은 단위의 필드를 0으로 만든다. 47 | ~~~java 48 | LocalTime time = LocalTime.of(12, 34, 56); // 12시 34분 56초 49 | time = time.truncatedTo(ChronoUnit.HOURS); // 시(hour)보다 작은 단위를 0으로 50 | System.out.println(time); // 12:00 51 | ~~~ 52 | 53 | ### 1.3. 날짜와 시간 비교 54 | - `compareTo()` 55 | ~~~java 56 | int result = date1.compareTo(date2); // 같으면 0, date1이 이전이면 -1, 이후면 1 57 | ~~~ 58 | - boolean형 메소드들 59 | ~~~java 60 | boolean isAfter (ChronoLocalDate other) 61 | boolean isBefore (ChronoLocalDate other) 62 | boolean isEqual (ChronoLocalDate other) 63 | ~~~ 64 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-05.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #13 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >오픈소스 아이디어가 계속 떠올라 집중이 안되었다. 4 | 5 | ## 1. java.time 패키지 (이어서) 6 | 7 | ### 1.1. LocalDateTime 8 | - `LocalDate`와 `LocalTime`을 합쳐서 `LocalDateTime`을 만들 수 있다. 9 | 10 | ~~~java 11 | LocalDate date = LocalDate.of(2018, 10, 05); 12 | LocalTime time = LocalTime.of(12,34,56); 13 | 14 | LocalDateTime dt = LocalDateTime.of(date, time); 15 | LocalDateTime dt2 = date.atTime(time); 16 | LocalDateTime dt3 = time.atDate(date); 17 | LocalDateTime dt4 = date.atTime(12, 34 ,56); 18 | LocalDateTime dt5 = time.atDate(LocalDate.of(2018, 10, 05)); 19 | LocalDateTime dt6 = date.atStartOfDay(); // = date.atTime(0,0,0); 20 | 21 | LocalDateTime dateTime = LocalDateTime.of(2018, 10, 05, 12, 34, 56); 22 | LocalDateTime today = LocalDateTime.now(); 23 | ~~~ 24 | 25 | - 반대로 `LocalDateTime`을 `LocalDate` 또는 `LocalTime`으로 변환할 수 있다. 26 | 27 | ~~~java 28 | LocalDateTime dt = LocalDateTime.of(2018, 10, 05, 12, 34, 56); 29 | LocalDate date = dt.toLocalDate(); 30 | LocalTime time = dt.toLocalTime(); 31 | ~~~ 32 | 33 | ### 1.2. ZonedDateTime 34 | >LocalDateTime에 타임존(tiem-zone)을 추가하면 ZonedDateTime이 된다. 35 | ZoneId는 일광 절약시간(DST, Daylight Saving Time)을 자동으로 처리해준다. 36 | LocalDateTime에 atZone()으로 시간대 정보를 추가하면, ZonedDateTime을 얻을 수 있다. 37 | 38 | ~~~java 39 | ZoneId zid = ZoneId.of("Asia/Seoul"); 40 | ZonedDateTime zdt = dateTime.atZone(zid); 41 | ~~~ 42 | 43 | - 특정 타임존의 시간 알기 44 | ~~~java 45 | ZoneId nyId = ZoneId.of("America/New_York"); 46 | ZonedDateTime nyTime = ZonedDateTime.now().withZoneSameInstant(nyId); 47 | // now() 대신 of() 사용하여 날짜&시간 지정 가능 48 | ~~~ 49 | 50 | - ZoneOffset 51 | UTC로부터 얼마나 떨어져있는지를 ZoneOffSet으로 표현 52 | 53 | ### 1.3. OffsetDateTime 54 | >`ZonedDateTime`은 ZoneId로 구역을 표현하는데, 55 | ZoneOffset을 사용하는 것이 `OffsetDateTime` 이다. 56 | ZoneId는 일광절약시간 처럼 타임존과 관련된 규칙들을 포함하지만, 57 | ZoneOffset은 단지 시간대를 시간의 차이로만 구분 58 | 59 | ### 1.4. Period와 Duration 60 | - `between()` 61 | 두 날짜의 차이를 나타내는 Period는 `between()`으로 얻을 수 있다. 62 | 63 | ~~~java 64 | LocalDate date1 = LocalDate.of(2017, 1, 16); // 첫 직장 입사일ㅋㅋ 65 | LocalDate date2 = LocalDate.of(2018, 6, 4); // 두번째 직장 입사일 66 | 67 | Period pe = Period.between(date1, date2); 68 | // date1이 date2보다 이전이면 양수, 이후면 음수로 Period에 저장 69 | ~~~ 70 | - `until()` 71 | `between()`과 같은 역할이지만, 72 | `between()`은 static 메소드이고, `until()`은 인스턴스 메소드이다. 73 | D-day를 구하는 경우, 두 개의 매개변수를 받는 `until()`을 사용하는 것이 낫다. 74 | 75 | ~~~java 76 | long sec = LocalTime.now().until(endTime, ChronoUnit.SECONDS); 77 | ~~~ 78 | 79 | - 날짜 사이의 일 수 계산 80 | LocalDate의 `toEpochDay()` 는 Epoch Day인 `1970-01-01`부터 날짜를 세어서 반환한다. 81 | Period를 사용하지 않고 두 날짜 사이의 일 수를 편하게 계산할 수 있다. 82 | 83 | ~~~java 84 | LocalDate date1 = LocalDate.of(2010, 08, 20); // 사귀기 시작한 날 85 | LocalDate date2 = LocalDate.of(2017, 11, 25); // 결혼한 날ㅎ 86 | 87 | long 연애기간 = date2.toEpochDay() - date1.toEpochDay(); 88 | ~~~ 89 | 90 | ### 1.5. 출력형식 정의 91 | >DateTimeFormatter의 ofPattern()으로 원하는 출력형식을 작성할 수 있다. 92 | 93 | ~~~java 94 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); 95 | ~~~ 96 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-06.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #14 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >비 많이 오는 토요일 아침 7시. 4 | >깔깔이 입고 공부 시작! 5 | 6 | ## 1. 컬렉션 프레임웍 (Collections Framework) 7 | >'데이터 그룹을 다루고 표현하기 위한 단일화된 구조' - Java API문서 8 | JDK1.2 이전까지는 Vector, Hashtable, Properties와 같은 컬렉션 클래스들을 각자의 방식으로 처리 9 | 10 | ### 1.1. 핵심 인터페이스 11 | - List 12 | - 순서 있는 데이터 집합 13 | - 데이터 중복 허용 14 | - 예시) 대기자 명단 15 | - Set 16 | - 순서 없는 데이터 집합 17 | - 데이터 중복 불허 18 | - 예시) 양의 정수집합, 소수의 집합 19 | - Map 20 | - 키와 값의 쌍으로 이루어진 데이터 집합 21 | - 순서 없고, 키 중복 불허, 값 중복 허용 22 | - 어떤 두 값을 연결한다는 의미에서 Map이라 지어짐 23 | - 예시) 우편번호, 지역번호 24 | 25 | >Vector나 Hashtable과 같은 기존의 컬렉션 클래스들은 호환을 위해, 26 | 설계를 변경해서 남겨두었지만 사용안하는 것이 좋다. 27 | 대신 새로 추가된 ArrayList와 HashMap 사용 권장. 28 | 29 | ### 1.2. 인터페이스 상속계층도 30 | >List 상속계층도 31 | - `List` 32 | - `Vector` 33 | - `Stack` 34 | - `ArrayList` 35 | - `LinkedList` 36 | 37 | >Set 상속계층도 38 | - `List` 39 | - `HashSet` 40 | - `SortedSet` 41 | - `TreeSet` 42 | 43 | >Map 상속계층도 44 | - `Map` 45 | - `Hashtable` 46 | - `HashMap` 47 | - `LinkedHashMap` 48 | - `SortedMap` 49 | - `TreeMap` 50 | 51 | ### 1.3. Map.Entry 인터페이스 52 | >Map.Entry 인터페이스는 Map 인터페이스의 내부 인터페이스이다. 53 | >Map에 저장되는 key-value 쌍을 다루기 위해 내부에 Entry 인터페이스 정의. 54 | >내부 클래스와 같이 인터페이스 안에 인터페이스를 정의하는 내부 인터페이스가 가능하다. 55 | 56 | ~~~java 57 | public interface Map { 58 | ... 59 | interface Entry { 60 | Object getKey(); 61 | Object getValue(); 62 | Object setValue(Object value); 63 | boolean equals(Object o); 64 | int hashCode(); 65 | ... 66 | } 67 | } 68 | ~~~ 69 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-07.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #15 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >오늘은 어머니 생신! 4 | 5 | ## 1. ArrayList 6 | >ArrayList는 기존의 Vector를 개선한 것. 7 | ArrayList는 Object 배열을 이용해서 데이터를 순차적으로 저장한다. 8 | 배열에 더 이상 저장할 공간이 없으면, 9 | 보다 큰 새로운 배열을 생성해서 기존 배열에 저장된 내용을 새로운 배열로 복사하고 저장한다. 10 | 선언된 배열의 타입이 Object이기 때문에 모든 종류의 객체를 담을 수 있다. 11 | 12 | ~~~java 13 | public class ArrayList extends AbstractList 14 | implements List, RandomAccess, Cloneable, java.io.Serializable { 15 | ... 16 | transient Object[] elementData; // Object배열 17 | ... 18 | } 19 | ~~~ 20 | 21 | ### 1.1. list의 공통 요소 삭제하기 22 | ~~~java 23 | for(int 1 = list2.size()-1; i >= 0; i--) { 24 | if(list1.contains(list2.get(i))) 25 | list2.remove(i); 26 | } 27 | ~~~ 28 | 29 | 위의 코드에서 변수 i를 증가시키면서 삭제하면, 한 요소가 삭제될 때마다 30 | 빈 공간을 채우기 위해 나머지 요소들이 자리이동을 해야해서 올바른 결과를 얻을 수 없다. 31 | 그래서 i를 감소시키면서 삭제를 해야 자리이동이 발생해도 영향을 받지 않는다. 32 | 33 | ### 1.2. 문자열 데이터를 원하는 길이로 잘라서 ArrayList에 담기 34 | ~~~java 35 | import java.util.*; 36 | 37 | class ArrayListEx { 38 | public static void main(String[] args) { 39 | 40 | final int LIMIT = 10; //자르고자 하는 글자의 개수 지정 41 | String source = "0123456789abcdefghijklmnopqrstuvwxyz" 42 | int length = source.length(); 43 | 44 | List list = new ArrayList(length/LIMIT + 10); //크기를 여유있게 잡음 45 | 46 | for(int 1=0; i< length; i+=LIMIT) { 47 | if(i+LIMIT < length) 48 | list.add(source.substring(i, i+LIMIT)); 49 | else 50 | list.add(source.substring(i)); 51 | } 52 | 53 | for(int i=0; i < list.size(); i++) { 54 | System.out.println(list.get(i)); 55 | } 56 | } 57 | } 58 | ~~~ 59 | 단순히 문자열을 특정 크기로 잘라서 출력할 것이라면 60 | `charAt(int i)`와 for문을 이용하면 되지만, 61 | ArrayList에 담음으로서 더 다양한 작업을 간단하게 처리할 수 있다. 62 | 63 | >ArrayList나 Vector 같이 배열을 이용한 자료구조는 64 | 데이터를 읽어오고 저장하는 데는 효율이 좋지만, 65 | 용량을 변경해야할 때는 새로운 배열을 생성한 후 66 | 기존 배열로부터 새 배열로 데이터를 복사하기 때문에 효율이 떨어진다. 67 | 그러므로 인스턴스를 생성할 때부터 충분한 크기로 생성해야 한다. 68 | 69 | ### 1.3. remove() 메소드 70 | ~~~java 71 | Object[] data = null; // 객체를 담기위한 객체배열 선언 72 | int capacity = 0; // 용량 73 | int size = 0; // 크기 74 | 75 | public Object remove(int index) { 76 | Object oldObj = null; 77 | 78 | if(index < 0 || index >=size) 79 | throw new IndexOutOfBoundsException("범위를 벗어났습니다."); 80 | oldObj = data[index]; 81 | 82 | if(index != size-1) { 83 | System.arraycopy(data, index+1, data, index, size-index-1); 84 | } 85 | 86 | data[size-1] = null; 87 | size--; 88 | 89 | return oldObj; 90 | } 91 | ~~~ 92 | >배열의 중간에 위치한 객체를 추가하거나 삭제하는 경우 93 | System.arraycopy()를 호출해서 다른 데이터의 위치를 이동시켜야 하기 때문에 작업시간이 오래걸린다. 94 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-08.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #16 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >{출퇴근길 개발 읽기} 운영 첫날이라 공부를 별로 못했다. 4 | 5 | ## 1. LinkedList 6 | 배열은 데이터를 읽어오는데 걸리는 시간이 빠르다는 장점이 있지만, 7 | 크기를 변경할 수 없으므로, 새로운 배열을 생성해서 데이터를 복사해야 한다. 8 | 그리고 배열의 실행 속도를 향상시키기 위해서는 충분히 큰 크기로 배열을 생성해야하므로 메모리가 낭비된다. 9 | 10 | 또한, 배열은 차례대로 데이터를 추가하고 마지막에서부터 데이터를 삭제하는 것은 빠르다. 11 | 하지만 배열 중간에 데이터를 추가하려면, 빈자리를 만들기 위해 다른 데이터들을 복사해서 이동해야 한다. 12 | 13 | ### 1.1. 삭제 14 | 간단하다. 15 | 삭제하고자 하는 요소의 이전요소가 삭제하고자 하는 요소의 다음요소를 참조하도록 변경하면 끝. 16 | 배열처럼 데이터를 이동하기 위해 복사하는 과정이 없기 때문에 처리속도가 매우 빠르다. 17 | 18 | ### 1.2. 이중 연결리스트 (Doubly Linked List) 19 | 링크드 리스트는 이동방향이 단방향이기 때문에 이전 요소에 대한 접근은 어렵다. 20 | 이중 연결리스트는 연결리스트에 참조변수를 하나 더 추가하여, 이전 요소에 대한 참조가 가능 21 | 22 | ### 1.3. ArrayList와 LinkedList 비교 23 | - 순차적인 추가/삭제시 ArrayList가 더 빠르다. 24 | - 순차적으로 삭제한다는 것은 마지막 데이터부터 역순으로 삭제하는 것이고, ArrayList는 단지 마지막 요소의 값을 null로 바꾸면 된다. 25 | - 중간 데이터의 추가/삭제시 LinkList가 더 빠르다. 26 | - LinkedList는 각 요소간의 연결만 변경해주면 되기 때문 27 | - 반면 ArrayList는 각 요소들을 재배치하여 추가할 공간을 확보하거나 빈공간을 채워야 한다. 28 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-09.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #17 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >한글날! 어제 3시에 자버려서 아침 9시부터 공부시작! 4 | 5 | ## 1. Stack과 Queue 6 | Stack은 마지막에 저장한 데이터를 가장 먼저 꺼내게 되는 LIFO(Last In First Out)구조. 7 | Queue는 처음에 저장한 데이터를 가장 먼저 꺼내게 되는 FIFO(First In First Out)구조. 8 | 9 | ## 2. Stack과 Queue 구현 10 | - Stack 11 | - 순차적으로 데이터를 추가하고 삭제하는 스택에는 ArrayList와 같은 배열 기반의 컬렉션 클래스가 적합 12 | - Queue 13 | - 큐는 데이터를 꺼낼 때 항상 첫번째 저장된 데이터를 삭제한다. 14 | - 그러므로 ArrayList와 같은 배열 기반의 컬렉션 클래스를 사용한다면, 데이터를 꺼낼 때마다 빈공간을 채우기 위해 데이터 복사가 발생해서 비효율적. 15 | - 큐는 ArrayList보다 데이터의 추가/삭제가 쉬운 LinkedList가 더 적합하다. 16 | 17 | ## 3. Stack 메소드 18 | - `boolean empty()` : Stack이 비어있는지 알려준다. 19 | - `Object peek()` : Stack의 맨 위에 저장된 객체를 반환. `pop()`과 달리 Stack에서 객체를 꺼내지는 않음 20 | - `Object pop()` : Stack의 맨 위에 저장된 객체를 꺼낸다. 21 | - `Object push(Object item)` : Stack에 객체(item)를 저장한다. 22 | - `int search(Object o)` : Stack에서 주어진 객체(o)를 찾아서 그 위치를 반환. 못찾으면 -1 반환. (배열과 달리 위치는 0이 아닌 1부터 시작) 23 | 24 | ## 4. Queue 메소드 25 | - `boolean add(Object o)` : 지정된 객체를 Queue에 추가한다. 성공하면 `true` 반환. 저장공간 부족하면 `IlligalStateException` 발생 26 | - `boolean offer(Object o) : Queue에 객체를 저장. 성공하면 `true` 실패하면 `false` 반환 27 | - `Object remove()` : Queue에서 객체를 꺼내 반환. 비어있으면 `NoSuchElementException` 발생 28 | - `Object poll()` : Queue에서 객체를 꺼내서 반환. 비어있으면 `null` 반환 29 | - `Object element()` : 삭제없이 요소를 읽어온다. `peek()`과 달리 Queue가 비었을 때 `NoSuchElementException 발생` 30 | - `Object peek()` : 삭제없이 요소를 읽어 온다. Queue가 비어있으면 `null` 반환 31 | 32 | 33 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-11.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #18 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >10월 10일 아침공부 첫 실패! 4 | '하루도 빠짐 없이' 라는 못쓰게 되었으므로..완벽하기보다 꾸준히 해야겠다. 5 | 6 | ## 1. Stack과 Queue (이어서) 7 | Java에서는 스택을 Stack 클래스로 구현하여 제공하고 있지만 8 | 큐는 Queue 인터페이스로 정의해놓고 클래스는 제공하지 않는다. 9 | 대신 Queue 인터페이스를 구현한 클래스들 중 하나를 선택해서 사용하면 된다. 10 | 11 | ## 2. Stack 직접 구현하기 12 | 13 | ~~~java 14 | import java.util.*; 15 | 16 | class MyStack extends Vector { 17 | public Object push(Object item) { 18 | addElement(item); 19 | return item; 20 | } 21 | 22 | public Object pop() { 23 | Object obj = peek(); // Stack에 저장된 마지막 요소를 읽어온다. 24 | removeElementAt(size()-1); // 마지막 요소를 삭제한다. 배열의 인덱스가 0부터 시작하므로 1을 빼준다. 25 | return obj; 26 | } 27 | 28 | public Object peek() { 29 | int len = size(); 30 | if (len == 0) 31 | throw new EmptyStackException(); 32 | return elementAt(len -1); 33 | } 34 | 35 | public boolean empty() { 36 | return size() == 0; 37 | } 38 | 39 | public int search(Object 0) { 40 | int i = lastIndexOf(o); // 끝에서부터 객체를 찾는다. 41 | if (i >= 0) { 42 | return size() - i; 43 | } 44 | return -1; // 해당 객체를 찾지 못하면 -1 반환 45 | } 46 | } 47 | ~~~ 48 | 49 | 50 | ## 3. Deque(Double-Ended Queue) 51 | >Deque는 양쪽 끝에 추가/삭제 가능 52 | Deque는 스택과 큐를 하나로 합쳐놓은 것과 같으며 스택으로 사용할 수도, 큐로 사용할 수도 있다. 53 | 54 | | Deque | Queue | Stack | 55 | | --- | --- | --- | 56 | | offerLast() | offer() | push() | 57 | | pollLast() | - | pop() | 58 | | pollFirst() | poll() | - | 59 | | peekFirst() | peek() | - | 60 | | peekLast() | - | peek() | 61 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-12.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #19 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >아침에는 공부하지만 저녁에 복습하며 정리를 못하고 있다.. 4 | 5 | ## 1. Iterator 6 | - 컬렉션 프레임웍에서는 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화하였다. 7 | - 컬렉션에 저장된 각 요소에 접근하는 Iterator인터페이스를 정의하고, 8 | - Collection 인터페이스에는 Iterator(Iterator를 구현한 클래스의 인스턴스)를 반환하는 iterator()를 정의하고 있다. 9 | 10 | ~~~java 11 | public interface Iterator { 12 | boolean hasnext(); 13 | Object next(); 14 | void remove(); 15 | } 16 | 17 | public interface Collection { 18 | ... 19 | public Iterator iterator(); 20 | ... 21 | } 22 | ~~~ 23 | 24 | - 컬렉션 클래스에 대해 iterator()를 호출하여 Iterator를 얻은 다음 반복문(주로 while문)을 사용해서 컬렉션 클래스의 요소들을 읽어 온다. 25 | - `boolean hasNext()` - 읽어올 요소가 남아있는지 확인. 있으면 true 없으면 false 26 | - `Object next()` - 다음 요소를 읽어 온다. next()를 호출하기 전에 hasNext()를 호출해서 읽어 올 요소가 있는지 확인하는 것이 안전. 27 | - `void remove()` - next()로 읽어 온 요소를 삭제한다. next()를 호출한 다음에 remove()를 호출해야 한다. 28 | 29 | - Map 인터페이스를 구현한 컬렉션 클래스는 Key와 Value를 쌍으로 저장하기 때문에 iterator()를 직접 호출할 수 없다. 대신 keySet()이나 entrySet()을 통해 Key와 Value를 각각 따로 Set의 형태로 얻어 온 후에 다시 iterator()를 호출해야 Iterator를 얻을 수 있다. 30 | ~~~java 31 | Map map = new HashMap(); 32 | ... 33 | Iterator it = map.keySet().iterator(); 34 | ~~~ 35 | - List클래스들은 저장순서를 유지하기 때문에 Iterator를 이용해서 읽어 온 결과 역시 저장 순서와 동일하지만 Set클래스들은 각 요소간의 순서가 유지되지 않기 때문에 Iterator를 이용해서 저장된 요소들을 읽어 와도 처음에 저장된 순서와 같지 않다. 36 | 37 | ## 2. ListIterator 38 | ListIterator는 Iterator를 상속받아서 기능을 추가한 것으로, 컬렉션의 요소에 접근할 때 Iterator는 단방향으로만 이동할 수 있지만, ListIterator는 양방향으로의 이동이 가능. 단, List인터페이스를 구현한 컬렉션에서만 사용 가능 39 | 40 | - `void add(Object o)` - 컬렉션에 새로운 객체(o)를 추가 41 | - `hasPrevious()` - 읽어 올 이전 요소가 남아있는지 확인. 있으면 true, 없으면 false 42 | - `Object previous()` - 이전 요소를 읽어 온다. previous()를 호출하기 전에 hasPrevious()를 호출해서 읽어 올 요소가 있는지 확인하는 것이 안전. 43 | - `int nextIndex()` - 다음 요소의 index를 반환 44 | - `int previousIndex()` - 이전 요소의 index를 반환 45 | - `void set(Object o)` - next() 또는 previous()로 읽어 온 요소를 지정된 객체(o)로 변경. 반드시 next()나 previous()를 먼저 호출한 다음에 이 메서드를 호출해야한다. 46 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-16.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #20 2 | >자바의 정석(남궁성 저) 2권 학습 3 | >13일(토) 성주에서 참외 농사를 지으시는 작은외삼촌댁 방문 4 | >14일(일) 거창에서 사과 농사를 지으시는 큰외삼촌댁 방문 5 | >15일(월) 기절 6 | >오늘은 예비군 훈련으로 출근하지 않은 날! 7 | 8 | ## 1. Arrays 9 | >Arrays 클래스에는 배열을 다루는데 유용한 메소드가 정의되어 있다. 10 | Arrays에 정의된 메소드는 모두 static 메소드다. 11 | 12 | ### 1.1. 배열 복사 - copyOf(), copyOfRange() 13 | >copyOf()는 배열 전체 복사, copyOfRange()는 배열의 일부를 복사해서 새로운 배열을 만들어 반환. 14 | copyOfRange()에 지정된 범위의 끝은 포함되지 않는다. 15 | 16 | ~~~java 17 | int[] arr = {0,1,2,3,4,}; 18 | int[] arr2 = Arrays.copyOf(arr, 3); // arr2 = [0,1,2] 19 | int[] arr3 = Arrays.copyOfRange(arr, 2, 4); // arr3 = [2,3] 20 | ~~~ 21 | 22 | ### 1.2. 배열 채우기 - fill(), setAll() 23 | >fill()은 배열의 모든 요소를 지정된 값으로 채운다. 24 | setAll()은 배열을 채우는데 사용할 함수형 인터페이스를 매개변수로 받는다. 25 | 26 | ~~~java 27 | int[] arr = new int[5]; 28 | Arrays.fill(arr, 9); // arr = [9,9,9,9,9] 29 | Arrays.setAll(arr, () -> (int)(Math.random()*5)+1); // arr = [1,5,2,1,1] 30 | ~~~ 31 | 32 | ### 1.3. 배열 정렬, 검색 - sort(), binarySearch() 33 | >sort()는 배열 정렬, binarySearch()는 배열에 저장된 요소를 검색 34 | binarySearch()는 배열에서 지정된 값이 저장된 위치(index)를 찾아서 반환. 반드시 배열이 정렬된 상태여야 올바른 결과를 얻는다. 35 | 36 | ~~~java 37 | int[] arr = { 3, 2, 0, 1, 4,}; 38 | Arrays.sort(arr); // arr = [0,1,2,3,4] 39 | int idx = Arrays.binarySearch(arr, 2); // idx = 2 40 | ~~~ 41 | 42 | ### 1.4. 문자열의 비교, 출력 - equals(), toString() 43 | >equals(), toString()은 일차원 배열에만 사용 가능. 44 | 다차원 배열에는 deepEquals(), deepToString() 사용. 45 | deepToString()은 배열의 모든 요소를 재귀적으로 접근해서 문자열을 구성하므로 3차원 이상의 배열에도 동작 46 | 47 | - 다차원 배열은 '배열의 배열'의 형태로 구성하기 때문에 equals()로 비교하면, 문자열을 비교하는 것이 아니라 '배열에 저장된 배열의 주소'를 비교하게 된다. 48 | 49 | ### 1.5. 배열을 List로 반환 - asList(Object...a) 50 | >asList()는 배열을 List에 담아서 반환. 51 | 매개변수의 타입이 가변인수라서 배열 생성 없이 저장할 요소들만 나열하는 것도 가능 52 | asList()가 반환한 List의 크기를 변경할 수 없다. 53 | 크기 변경가능한 List는 `List list = new ArrayList(Arrays.asList(1,2,3,4,5));` 54 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-17.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #21 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | ## 1. Comparator와 Comparable 5 | >Arrays.sort()를 호출하면 알아서 배열을 정렬하는 것처럼 보이지만, 6 | 사실은 Chractor클래스의 Comparable의 구현에 의해 정렬되었던 것. 7 | Comparble을 구현한 클래스는 정렬이 가능하다는 것을 의미. 8 | 9 | ~~~java 10 | public interface Comparator { 11 | int compare(Object o1, Object o2); 12 | boolean equals(Object obj); 13 | } 14 | 15 | public interface Comparable { 16 | public int compareTo(Object o); 17 | } 18 | ~~~ 19 | 20 | >Comparable은 java.lang 패키지에 있고, Comparator는 java.util 패키지에 있다. 21 | 22 | - Comparable : 기본 정렬기준을 구현하는데 사용. 23 | - Comparator : 기본 정렬기준 외에 다른 기준으로 정렬하고자할 때 사용 24 | 25 | ## 2. HashSet 26 | >HashSet은 Set인터페이스를 구현한 가장 대표적인 컬렉션. 27 | HashSet은 저장순서를 유지하지 않으므로 저장순서를 유지하고자 한다면 LinkedHashSet 사용. 28 | 29 | - 로또번호 예제 30 | ~~~java 31 | import java.util.*; 32 | 33 | class HashSetLotto { 34 | public static void main(String[] args) { 35 | Set set = new HashSet(); 36 | 37 | for (int i = 0; set.size() < 6; i++) { 38 | int num = (int)(Math.random()*45) + 1; 39 | set.add(new Integer(num)); 40 | } 41 | 42 | List list = new LinkedList(set); 43 | Collections.sort(list); 44 | System.out.println(list); 45 | } 46 | } 47 | ~~~ 48 | >번호를 크기 순으로 정렬하기 위해 Collections클래스의 sort(List list)를 사용했다. 49 | 이 메서드는 인자로 List인터페이스 타입을 필요로 하기 때문에 50 | LinkedList클래스의 생성자 LinkedList(Collection c)를 이용해서 HashSet에 저장된 객체들을 LinkedList에 담아서 처리했다. 51 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-18.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #22 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. TreeSet 6 | >TreeSet은 이진검색트리(binary search tree) 형태로 데이터를 저장하는 컬렉션 클래스다. 7 | TreeSet은 이진검색트리의 성능을 향상시킨 Red-Black tree로 구현되어 있다. 8 | 중복된 데이터의 저장을 허용하지 않으며, 정렬된 위치에 저장하므로 저장순서를 유지하지도 않는다. 9 | TreeSet은 정렬된 상태를 유지하기 때문에 단일 값 검색과 범위검색, 예를 들면 3과 7사이의 범위에 있는 값을 검색하는 것이 매우 빠르다. 10 | 11 | - Binary Search Tree 12 | - 모든 노드는 최대 두 개의 자식노드를 가질 수 있다. 13 | - 왼쪽 자식노드의 값은 부모노드의 값보다 작고, 오른쪽 자식노드의 값은 부모노드의 값보다 커야한다. 14 | - 노드의 추가 삭제에 시간이 걸린다.(순차적으로 저장하지 않으므로) 15 | - 검색(범위검색)과 정렬에 유리하다. 16 | - 중복된 값을 저장하지 못한다. 17 | 18 | - TreeSet으로 만든 로또번호 생성 프로그램 (HashSet으로 만든 것과 달리 정렬하는 코드가 필요없다. TreeSet은 저장할 때 이미 정렬하기 때문에.) 19 | ~~~java 20 | import java.util.*; 21 | 22 | class TreeSetLotto { 23 | public static void main(String[]args) { 24 | Set set = new TreeSet(); 25 | 26 | for (int i =0; set.size() < 6; i++) { 27 | int num = (int)(Math.random()*45) + 1; 28 | set.add(num); // set.add(new Integer(num)); 29 | } 30 | 31 | System.out.println(set); 32 | } 33 | } 34 | ~~~ 35 | 36 | - headSet()과 tailSet()을 사용하면, TreeSet에 저장된 객체 중 지정된 기준 값보다 큰 값의 객체들과 작은 값의 객체들을 얻을 수 있다. 37 | ~~~java 38 | import java.util.*; 39 | 40 | class TreeSetEx2 { 41 | public static void main(String[] args) { 42 | TreeSet set = new TreeSet(); 43 | int[] score = {80, 95, 50, 35, 45, 65, 10, 100}; 44 | 45 | for (int i=0; i < score.length; i++) 46 | set.add(new Integer(score[i])); 47 | 48 | System.out.println("50보다 작은 값 :" + set.headSet(new Integer(50))); 49 | System.out.println("50보다 큰 값 :" + set.tailSet(new Integer(50))); 50 | } 51 | } 52 | ~~~ 53 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-19.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #23 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. HashMap 6 | >Hashtable과 HashMap의 관계는 Vector와 ArrayList의 관계와 같아서 Hashtable보다는 새로운 버전인 HashMap을 사용할 것을 권한다. 7 | HashMap은 Map을 구현했으므로 키와 값을 묶어서 하나의 데이터로 저장한다. 8 | 그리고 hashing을 사용하기 때문에 많은 양의 데이터를 검색하는데 뛰어난 성능을 보인다. 9 | 10 | ~~~java 11 | public class HashMap extends AbstractMap implements Map, Cloneable, Serializable { 12 | 13 | transient Entry[] table; 14 | ... 15 | 16 | static class Entry implements Map.Entry { 17 | final Object key; 18 | Object value; 19 | ... 20 | } 21 | } 22 | ~~~ 23 | 24 | >HashMap은 Entry라는 내부 클래스를 정의하고, 다시 Entry타입의 배열을 선언한다. 25 | 키와 값은 별개의 값이 아니라 서로 관련된 값이기 때문에 26 | 각각의 배열로 선언하기 보다는 하나의 클래스로 정의해서 하나의 배열로 다루는 것이 데이터의 무결성(integrity)적인 측면에서 더 바람직하기 때문. 27 | 28 | - HashMap은 키와 값을 각각 Object 타입으로 저장한다. 29 | - (Object, Object)의 형태로 저장하기 때문에 어떠한 객체도 저장할 수 있지만 key는 주로 String을 대문자 또는 소문자로 통일해서 사용한다. 30 | 31 | ## 2. 해싱과 해시함수 32 | >해싱이란 해시함수(hash function)를 이용해서 데이터를 해시테이블(hash table)에 저장하고 검색하는 기법 33 | 해시함수는 데이터가 저장된 곳을 알려주기 때문에 다량의 데이터 중에서도 원하는 데이터를 빠르게 찾을 수 있다. 34 | 35 | - 해싱을 구현한 함수 - HashSet, HashMap, Hashtable 36 | - Hashtable은 Collection Framework가 도입되면서 HashMap으로 대체되었으나 이전소스와의 호환성 문제로 남겨두고 있다. 37 | 38 | ### 2.1. hashCode() 39 | 40 | - HashMap과 같이 해싱을 구현한 컬렉션 클래스에서는 Object클래스에 정의된 hashCode()를 해시함수로 사용한다. 41 | - Object클래스에 정의된 hashCode()는 객체의 주소를 이용하는 알고리즘으로 해시코드를 만들기 때문에 모든 객체에 대해 hashCode()를 호출한 결과가 서로 유일한 훌륭한 방법이다. 42 | - String클래스의 경우 Object로 부터 상속받은 hashCode()를 오버라이딩해서 문자열의 내용으로 해시코드를 만들어낸다. 그래서 서로 다른 String인스턴스일지라도 같은 내용의 문자열을 가졌다면 hashCode()를 호출하면 같은 해시코드를 얻는다. 43 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-20.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #24 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. TreeMap 6 | >TreeMap은 이름에서 알 수 있듯이 이진검색트리의 형태로 키와 값의 쌍으로 이루어진 데이터를 저장한다. 7 | 그래서 검색과 정렬에 적합한 클래스이다. 8 | 검색의 경우 대부분의 경우에서 HashMap이 TreeMap보다 더 뛰어나다. 9 | 다만 범위검색이나 정렬이 필요한 경우 TreeMap이 낫다. 10 | 11 | ## 2. Properties 12 | >Properties는 HashMap의 구버전인 Hashtable을 상속받아 구현한 것이다. 13 | Hashtable은 키와 값을 (Object, Object)의 형태로 저장하는데 비해 14 | Properties는 (String, String)의 형태로 저장하는 보다 단순화된 컬렉션클래스이다. 15 | 16 | - 주로 애플리케이션의 환경설정과 관련된 속성(property)을 저장하는데 사용된다. 17 | - 데이터를 파일로부터 읽고 쓰는 편리한 기능을 제공한다. 18 | - Properties는 컬렉션프레임웍 이전의 구버전이므로 Iterator가 아닌 Enumeration을 사용한다. 19 | - list메소드로 Properties에 저장된 모든 데이터를 화면 또는 파일에 편하게 출력할 수 있다. 20 | ~~~java 21 | void list(PrintStream out) 22 | void list(PrintWriter out) 23 | ~~~ 24 | 25 | ## 3. Collections 26 | >Arrays가 배열과 관련된 메소드를 제공하는 것처럼, Collections는 컬렉션과 관련된 메소드를 제공한다. 27 | fill(), copy(), sort(), binarySearch() 등의 메소드는 두 클래스 모두에 포함되어 있으며 같은 기능을 한다. 28 | 29 | ### 3.1. 컬렉션의 동기화 30 | - 멀티 쓰레드(multi-thread) 프로그래밍에서는 하나의 객체를 여러 쓰레드가 동시에 접근할 수 있기 때문에 데이터의 일관성(consistency)을 유지하기 위해서는 공유되는 객체에 동기화(synchronization)가 필요하다. 31 | - 새로 추가된 ArrayList와 HashMap과 같은 컬렉션은 동기화를 자체적으로 처리하지 않는다. 32 | - 필요한 경우에만 java.util.Collections 클래스의 동기화 메소드를 이용해서 동기화처리가 가능하도록 변경하였다. 33 | 34 | ## 4. 컬렉션 클래스 요약 35 | |컬렉션|특징| 36 | |---|---| 37 | |ArrayList|배열기반. 데이터의 추가와 삭제에 불리. 순차적인 추가삭제는 제일 빠름. 임의의 요소에 대한 접근성이 뛰어남.| 38 | |LinkedList|연결기반. 데이터의 추가와 삭제에 유리. 임의의 요소에 대한 접근성이 좋지 않다.| 39 | |HashMap|배열과 연결이 결합된 상태. 추가,삭제,검색,접근성이 모두 뛰어남. 검색에는 최고의 성능.| 40 | |TreeMap|연결기반. 정렬과 검색(특히 범위검색)에 적합. 검색성능은 HashMap보다 떨어짐.| 41 | |Stack|Vector를 상속받아 구현| 42 | |Queue|LinkedList가 Queue인터페이스를 구현| 43 | |Properties|Hashtable을 상속받아 구현| 44 | |HashSet|HashMap을 이용해서 구현| 45 | |TreeSet|TreeMap을 이용해서 구현| 46 | |LinkedHashMap|HashMap과 HashSet에 저장순서유지기능 추가| 47 | |LinkedHashSet|HashMap과 HashSet에 저장순서유지기능 추가| 48 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-25.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #26 - 열거형(Enums) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 열거형(Enums) 6 | >Java의 열거형은 C언어의 열거형과 다르게 열거형이 갖는 값 뿐만 아니라 타입까지 관리한다. 7 | >기존의 상수의 값이 바뀌면, 해당 상수를 참조하는 모든 소스를 다시 컴파일 해야한다. 하지만 열거형 상수를 사용하면 기존의 소스를 다시 컴파일하지 않아도 된다. 8 | 9 | ### 1.1. 사용방법 10 | 11 | ~~~java 12 | enum 열거형이름 { 상수명1, 상수명2, ...} 13 | ~~~ 14 | 15 | - 열거형 상수 간의 비교에는 `==`을 사용할 수 있다. `equals()`가 아닌 `==`으로 비교가능한 것은 그만큼 빠르다는 것이다. 16 | - 하지만 비교연산자(<, >)는 사용할 수 없고 `compareTo()`는 사용 가능하다. 17 | - switch문의 조건식에 열거형 사용하기 18 | ~~~java 19 | void move() { 20 | switch(dir) { 21 | case EAST: x++; //Direction.EAST라고 쓰면 안된다.(열거형 이름 없이 상수 이름만 적어야 한다.) 22 | break; 23 | case WEST: x--; 24 | break; 25 | case SOUTH: y++; 26 | break; 27 | case NORTH: y--; 28 | break; 29 | } 30 | } 31 | ~~~ 32 | 33 | ### 1.2. 열거형의 이해 34 | 35 | ~~~java 36 | enum Direction { EAST, WEST, SOUTH, NORTH } 37 | ~~~ 38 | - 열거형 상수 하나하나가 Direction 객체이다. 39 | 40 | 위의 문장을 클래스로 정의하면, 41 | ~~~java 42 | class Direction { 43 | static final Direction EAST = new Direction("EAST"); 44 | static final Direction WEST = new Direction("WEST"); 45 | static final Direction SOUTH = new Direction("SOUTH"); 46 | static final Direction NORTH = new Direction("NORTH"); 47 | 48 | private String name; 49 | 50 | private Direction(String name) { 51 | this.name = name; 52 | } 53 | } 54 | ~~~ 55 | 56 | - Direction클래스의 static상수 EAST, WEST, SOUTH, NORTH의 값은 객체의 주소이고, 이 값은 바뀌지 않는 값이므로 `==`로 비교가 가능한 것이다. 57 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-27.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #27 - 쓰레드(Thread) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 프로세스와 쓰레드 6 | - 프로세스란 실행중인 프로그램이다. 7 | - 프로그램을 실행하면 OS로부터 실행에 필요한 자원(메모리)를 할당받아 프로세스가 된다. 8 | - 프로세스의 자원을 이용해서 실제로 작업을 수행하는 것이 쓰레드다. 9 | - 모든 프로세스에는 최소한 하나 이상의 쓰레드가 존재한다. 10 | - 쓰레드가 작업을 수행하려면 개별적인 메모리 공간(호출스택)이 필요하다. 11 | - CPU의 코어(core)가 한 번에 단 하나의 작업만 수행할 수 있으므로, 동시에 처리되는 작업의 수는 코어의 개수와 일치한다. 12 | 13 | ## 2. 쓰레드의 구현과 실행 14 | - 쓰레드를 구현하는 방법은 Thread 클래스를 상속받는 방법과 Runnable 인터페이스를 구현하는 방법이 있다. 15 | - Thread 클래스를 상속받으면 다른 클래스를 상속받을 수 없기 때문에, Runnable 인터페이스를 구현하는 방법이 일반적이다. 16 | 17 | ### 2.1. Thread 클래스 상속 18 | 19 | ~~~java 20 | class MyThread extends Thread { 21 | public void run() { // Thread 클래스의 run()을 오버라이딩 22 | 작업 내용 23 | } 24 | } 25 | ~~~ 26 | 27 | ### 2.2. Runnable 인터페이스 구현 28 | >Runnable 인터페이스는 오로지 run()만 정의되어 있는 간단한 인터페이스이다. 29 | >Runnable 인터페이스를 구현하기 위해서 해야 할 일은 추상메서드인 run()의 몸통 {}을 만들어 주는 것 뿐이다. 30 | 31 | ~~~java 32 | public interface Runnable { 33 | public abstract void run(); 34 | } 35 | ~~~ 36 | 37 | >쓰레드를 구현한다는 것은 두 가지 방법 모두, 그저 쓰레드를 통해 작업하고자 하는 내용으로 run()의 몸통{}을 채우는 것 뿐이다. 38 | 39 | 40 | ### 2.3. 인스턴스 생성 방법 41 | - Thread 클래스 상속 42 | 43 | ~~~java 44 | ThreadA t1 = new ThreadA(); 45 | ~~~ 46 | 47 | - Runnable 인터페이스 구현 48 | 49 | ~~~java 50 | Runnable r = new ThreadB(); 51 | Thread t2 = new Thread(r); 52 | ~~~ 53 | 54 | >Thread클래스를 상속받으면, 자손 클래스에서 조상인 Thread클래스의 메서드를 직접 호출할 수 있지만, 55 | Runnable을 구현하면 Thread클래스의 static메서드인 currentThread()를 호출하여 쓰레드에 대한 참조를 얻어 와야만 호출이 가능하다. 56 | 57 | ~~~java 58 | class ThreadA extends Thread { 59 | public void run() { 60 | System.out.println(getName()); // 조상인 Thread의 getName() 호출 61 | } 62 | } 63 | ~~~ 64 | 65 | ~~~java 66 | class ThreadB implements Runnable { 67 | public void run() { 68 | System.out.println(Thread.currentThread().getName()); 69 | // Thread.currentThread() - 현재 실행중인 Thread 반환 70 | } 71 | } 72 | ~~~ 73 | 74 | ### 2.4. 쓰레드의 실행 75 | - 쓰레드를 생성했다고 자동을 실행되지 않는다. start()를 호출해야만 쓰레드가 실행된다. 76 | - start()가 호출되어도 바로 실행되는 것이 아니라, 실행대기 상태에 있다가 자신의 차례가 되어야 실행된다. 77 | - 쓰레드의 실행 순서는 OS의 스케쥴러가 작성한 스케쥴에 의해 결정된다. 78 | - 한 번 실행이 종료된 쓰레드는 다시 실행할 수 없다. (하나의 쓰레드에 start()가 한 번만 호출될 수 있다.) 79 | 80 | ## 3. Start() 와 run() 81 | - main메서드에서 run()을 호출하는 것은 생성된 쓰레드를 실행시키는 것이 아니라, 단순히 클래스에 선언된 메서드를 호출하는 것일 뿐이다. 82 | - start()는 새로운 쓰레드를 위해 호출스택(call stack)을 생성한 후에 run()을 호출해서, 생성된 호출스택에 run()이 첫 번째로 올라가게 한다. 83 | 1. main메서드에서 쓰레드의 start()를 호출한다. 84 | 2. start()는 새로운 쓰레드를 생성하고, 쓰레드가 작업하는데 사용될 호출스택을 생성한다. 85 | 3. 새로 생성된 호출스택에 run()이 호출되어, 쓰레드가 독립된 공간에서 작업을 수행한다. 86 | 4. 호출스택이 2개가 되었으므로 스케쥴러가 정한 순서에 의해 번갈아 가면서 실행된다. 87 | - 주어진 시간동안 작업을 마치지 못한 쓰레드는 다시 자신의 차례가 돌아올 때까지 대기 상태로 있는다. 88 | - 작업을 마친 쓰레드, 즉 run()의 수행이 종료된 쓰레드는 사용하던 호출스택이 모두 비워지고 사라진다. 89 | - 이는 자바프로그램을 실행하면 호출스택이 생성되고 main메서드가 처음으로 호출되고, 90 | main메서드가 종료되면 호출스택이 비워지면서 프로그램도 종료되는 것과 같다. 91 | - 한 쓰레드가 예외가 발생해서 종료되어도 다른 쓰레드의 실행에는 영향을 미치지 않는다. 92 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/2018-10-30.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #28 - 쓰레드(Thread) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 쓰레드의 실행제어 6 | 7 | ### 1.1. sleep(long millis) 8 | >일정 시간동안 쓰레드를 멈추게 한다. 9 | 10 | ~~~java 11 | static void sleep(long millis) 12 | static void sleep(long millis, int nanos) 13 | ~~~ 14 | 15 | - sleep()에 의해 일시정지 상태가 된 쓰레드는 지정된 시간이 지나거나, 16 | interrupt()가 호출되면, InterruptedException이 발생되어 잠에서 깨어나 실행대기 상태가 된다. 17 | - 그래서 sleep()을 호출할 때는 항상 try-catch문으로 예외를 처리해줘야 한다. 18 | 19 | ~~~java 20 | void delay(long millis) { 21 | try { 22 | Thread.sleep(millis); 23 | } catch(InterruptedException e) {} 24 | } 25 | ~~~ 26 | - sleep()은 항상 실행중인 쓰레드에 대해 작동한다. 27 | - 그래서 sleep()은 static으로 선언되어 있으며, 28 | `th1.sleep(2000)` 처럼 참조변수를 이용해서 호출하기 보다는 `Thread.sleep(2000)`과 같이 해야한다. 29 | 30 | ### 1.2. interrupt()와 interrupted() 31 | >쓰레드의 작업을 취소한다. 32 | 33 | ~~~java 34 | void interrupt() // 쓰레드의 interrupted 상태를 false에서 true로 변경 35 | boolean isInterrupted() // 쓰레드의 interrupted상태를 반환 36 | static boolean interrupted() // 현재 쓰레드의 interrupted상태를 반환 후, false로 변경 37 | ~~~ 38 | 39 | - interrupt()는 쓰레드에게 작업을 멈추라고 요청한다. (강제 종료는 아니다.) 40 | - interrupted()는 쓰레드에 대해 interrupt()가 호출되었는지 알려준다. (않았다면 false, 호출 되었다면 true 반환) 41 | - 쓰레드가 sleep(), wait(), join()에 의해 일시정지(waiting) 상태에 있을 때, 해당 쓰레드에 대해 interrupt()를 호출하면 42 | sleep(), wait(), join()에서 `Interrupted Exception`이 발생하고 쓰레드는 실행대기(Runnable) 상태로 바뀐다. 43 | 즉, 멈춰있던 쓰레드를 깨워서 실행가능한 상태로 만드는 것이다. 44 | 45 | ### 1.3. suspend(), resume(), stop() 46 | >모두 deprecated 된 메서드 들이다. 47 | - suspend()는 sleep()처럼 쓰레드를 멈추게 한다. suspend()에 의해 정지된 쓰레드는 resume()을 호출해야 다시 실행대기 상태가 된다. 48 | - stop()은 호출되는 즉시 쓰레드가 종료된다. 49 | - suspend()와 stop()은 교착상태(Deadlock)를 일으키기 쉬우므로 권장되지 않는다. 50 | 51 | ### 1.4. yield() 52 | >쓰레드 자신에게 주어진 실행시간을 다음 차례의 쓰레드에게 양보한다. 53 | 54 | ### 1.5. join() 55 | >쓰레드 자신이 하던 작업을 잠시 멈추고 다른 쓰레드가 지정된 시간 동안 작업을 수행하도록 할 때 join()을 사용한다. 56 | 57 | ~~~java 58 | void join() 59 | void join(long millis) 60 | void join(long millis, int nanos) 61 | ~~~ 62 | 63 | - 시간을 지정하지 않으면, 해당 쓰레드가 작업을 모두 마칠 때 까지 기다리게 된다. 64 | - 작업 중에 다른 쓰레드의 작업이 먼저 수행되어야 할 필요가 있을 때 join()을 사용한다. 65 | - join()이 호출되는 부분을 try-catch로 감싸야한다. 66 | - sleep()과 다른 점은 join()은 현재 쓰레드가 아닌 특정 쓰레드에 대해 동작하므로 static메서드가 아니라는 것이다. 67 | 68 | ~~~java 69 | try { 70 | th1.join(); // 현재 실행중인 쓰레드가 쓰레드 th1의 작업이 끝날때 까지 기다린다. 71 | } catch(InterruptedException e) {} 72 | ~~~ 73 | -------------------------------------------------------------------------------- /Early-Bird/2018-10/README.md: -------------------------------------------------------------------------------- 1 | # 2018년 10월의 아침공부 후기 2 | 3 | 1. 출석률 67 % (21일/31일) 4 | 2. 6시간 수면에 익숙해졌다. 5 | 3. 11월에는 12시에 잠자리에 드는 연습을 해야겠다. 6 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-03.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #30 - 람다식(Lambda expression) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 람다식 6 | >메서드를 하나의 식(expression)으로 표현한 것. 7 | >메서드를 람다식으로 표현하면 메서드의 이름과 반환값이 없어지므로 람다식을 익명함수(anonymous function)라고도 한다. 8 | 9 | 람다식은 메서드의 매개변수로 전달될 수 있고, 10 | 메서드의 결과로 반환될 수 있다. 11 | 즉, 메서드를 변수처럼 다루는 것이 가능하다. 12 | 13 | ## 1.1. 람다식 작성하기 14 | - 메서드에서 이름과 반환타입 제거 15 | - 매개변수 선언부와 몸통{} 사이에 -> 추가 16 | 17 | ~~~java 18 | //기존 19 | 반환타입 메서드이름 (매개변수 선언) { 20 | ... 21 | } 22 | 23 | //람다식 24 | (매개변수 선언) -> { 25 | ... 26 | } 27 | ~~~ 28 | 29 | - 반환값이 있는 메서드는 return 대신 식(expression)으로 대신할 수 있다.(연산 결과가 자동으로 반환값이 되고 ; 생략) 30 | - 매개변수의 타입은 추론가능하면 생략 가능 (대부분 생략 가능) 31 | - 두 매개변수 중 하나의 타입만 생략하는 것은 불가능 32 | - 매개변수가 하나뿐이면 괄호() 생략 가능 33 | - 중괄호{} 안의 문장이 하나일 때는 중괄호{} 생략 가능 (문장 끝에 ; 생략) 34 | - 중괄호{} 안의 문장이 return문일경우 중괄호{} 생략 불가능 35 | ~~~java 36 | //기존 37 | int max(int a, int b) { 38 | return a > b ? a : b; 39 | } 40 | 41 | //람다식 42 | (int a, int b) -> { 43 | return a > b ? a : b; 44 | } 45 | 46 | //return문 대신 expression 사용 47 | (int a, int b) -> a > b ? a: b 48 | 49 | //매개변수 타입 생략 50 | (a, b) -> a > b ? a : b 51 | 52 | //매개변수 1개일 경우 괄호 생략 53 | a -> a*a //OK 54 | int a -> a*a //에러 55 | 56 | //본문 문장 1개일 경우 중괄호 생략 57 | (String name, int i) -> System.out.println(name+"="+i) 58 | ~~~ 59 | 60 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-05.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #31 - 람다식(Lambda expression) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 람다식 6 | 7 | ## 1.1. 함수형 인터페이스(Functional Interface) 8 | >람다식을 다루기 위한 인터페이스 9 | 10 | 람다식은 메서드와 동등한 것이 아니라 익명클래스의 객체와 동등하다. 11 | 12 | ~~~java 13 | // 람다식 14 | (int a, int b) -> a > b ? a : b 15 | 16 | // 익명클래스의 객체 17 | new Object() { 18 | int max(int a, int b) { 19 | return a > b ? a : b ; 20 | } 21 | } 22 | ~~~ 23 | 24 | 람다식으로 정의된 익명 객체의 메서드를 호출하려면 참조변수가 필요하다. 25 | 이 때, 참조변수의 타입은 클래스 또는 인터페이스가 가능한데, 람다식과 동등한 메서드가 정의되어 있는 것이어야 한다. 26 | 27 | ~~~java 28 | // 예를 들어 max() 메서드가 정의된 Myfunction 인터페이스 정의 29 | interface MyFunction { 30 | public abstract int max(int a, int b); 31 | 32 | // MyFunction 인터페이스를 구현한 익명클래스 객체 생성 33 | MyFunction f = new MyFunction() { 34 | public int max (int a, int b); 35 | return a > b ? a : b; 36 | } 37 | } 38 | int big = f.max(5, 3); //익명 객체의 메서드 호출 39 | 40 | // 위의 익명 객체를 람다식으로 대체 41 | MyFunction f = (int a, int b) -> a > b ? a : b; 42 | int big = f.max(5, 3); 43 | ~~~ 44 | 45 | 위 처럼 MyFunction 인터페이스를 구현한 익명 객체를 람다식으로 대체 가능한 이유는 람다식도 실제로는 익명 객체이고, 46 | MyFunction 인터페이스를 구현한 익명 객체의 메서드 max()와 람다식의 매개변수의 타입과 개수, 반환값이 일치하기 때문이다. 47 | 48 | 단, 함수형 인터페이스에는 오직 하나의 추상 메서드만 정의되어 있어야 한다. 그래야 람다식과 인터페이스가 1:1로 연결되기 때문이다. 49 | 반면 static 메서드와 default 메서드의 개수에는 제약이 없다. 50 | 51 | @FunctionalInterface를 붙이면 컴파일러가 함수형 인터페이스를 올바르게 정의하였는지 확인해준다. 52 | 53 | ~~~java 54 | // 기존 인터페이스의 메서드 구현 55 | List list = Arrays.asList("abc", "aaa", "bbb", "ccc"); 56 | Collections.sort(list, new Comparator() { 57 | public int compare(String s1, String s2) { 58 | return s2.compareTo(s1); 59 | } 60 | }); 61 | 62 | // 람다식으로 구현 63 | List list = Arrays.asList("abc", "aaa", "bbb", "ccc"); 64 | Collections.sort(list, (s1, s2) -> s2.compareTo(s1)); 65 | ~~~ 66 | 67 | 함수형 인터페이스로 람다식을 참조할 수 있지만, 람다식의 타입이 함수형 인터페이스의 타입과 일치하는 것은 아니다. 68 | 람다식은 익명 객체이고 익명 객체는 타입이 없다. (정확히는 타입이 있지만 컴파일러가 임의로 이름을 정하기 때문에 알 수 없다.) 69 | 그러므로 아래와 같이 형변환이 필요하다. 70 | 71 | ~~~java 72 | MyFunction f = (MyFunction) (()->{}); // 73 | ~~~ 74 | 75 | 람다식은 MyFunction인터페이스를 직접 구현하지 않았지만, 이 인터페이스를 구현한 클래스의 객체와 완전히 동일하기 때문에 위와 같은 형변환을 허용한다. 76 | 그리고 이 형변환은 생략 가능하다. 77 | 78 | 람다식은 이름이 없을 뿐 분명히 객체인데도, Object 타입으로 형변환 할 수 없다. 람다식은 오직 함수형 인터페이스로만 형변환이 가능하다. 79 | 굳이 Object 타입으로 형변환하려면 아래와 같이 먼저 함수형 인터페이스로 변환해야 한다. 80 | 81 | ~~~java 82 | Object obj = (Object)(MyFunction)(()->{}); 83 | String str = (Object)(MyFunction)(()->{})).toString(); 84 | ~~~ 85 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-06.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #32 - 람다식(Lambda expression) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 람다식 6 | 7 | ## 1.1. java.util.function 패키지 8 | >이 패키지에 자주 쓰이는 형식의 메서드를 함수형 인터페이스로 정의해놓았다. 9 | 10 | |함수형 인터페이스|메서드|설명| 11 | |---|---|---| 12 | |java.lang.Runnable|void run()|매개변수도 없고, 반환값도 없음| 13 | |Supplier|T get()|매개변수는 없고, 반환값만 있음| 14 | |Consumer|void accept(T t)|Supplier와 반대로 매개변수만 있고, 반환값이 없음| 15 | |Function|R apply(T t)|일반적인 함수. 하나의 매개변수를 받아서 결과를 반환| 16 | |Predicate|boolean test(T t)|조건식을 표현하는데 사용. 매개변수는 하나, 반환 타입은 boolean| 17 | |BiConsumer|void accept(T t, U u)|두개의 매개변수만 있고, 반환값이 없음| 18 | |BiPredicate|boolean test(T t, U u)|조건식을 표현하는데 사용됨. 매개변수는 둘, 반환값은 boolean| 19 | |BiFunction|R apply(T t, U u)|두개의 매개변수를 받아서 하나의 결과를 반환| 20 | 21 | - 수학에서 결과로 true 또는 false를 반환하는 함수를 Predicate 라고 한다. 22 | - 매개변수가 2개인 함수형 인터페이스는 이름 앞에 'Bi'가 붙는다. 23 | - Supplier는 매개변수는 없고 반환값만 존재하는데 메서드는 두 개의 값을 반환할 수 없으므로 BiSupplier가 없다. 24 | - 매개변수의 타입과 반환타입이 일치할 때는 Function 대신 UnaryOperator를 사용한다. (매개 변수 2개면 BinaryOperator) 25 | 26 | ~~~java 27 | // 조건식 표현에 사용되는 Predicate 28 | 29 | Predicate isEmptyStr = s -> s.length() == 0; 30 | String s = ""; 31 | 32 | if(isEmptyStr.test(s)) 33 | System.out.println("This is an empty String."); 34 | ~~~ 35 | 36 | 37 | ## 1.2. Function의 합성과 Predicate의 결합 38 | 39 | ### 1.2.1. Function의 합성 40 | >두 람다식을 합성해서 새로운 람다식을 만들 수 있다. 41 | 42 | 함수 f, g가 있을 때 43 | f.andThen(g)는 함수 f를 먼저 적용하고 g 적용. 44 | f.compose(g)는 함수 g를 먼저 적용하고 f 적용. 45 | 46 | ### 1.2.2. Predicate의 결합 47 | >여러 Predicate를 and(), or(), negate()로 연결해서 하나의 새로운 Predicate로 결합할 수 있다. 48 | >Predicate의 끝에 negate()를 붙이면 조건식 전체가 부정이 된다. 49 | 50 | ~~~java 51 | Predicate p = i -> i < 100; 52 | Predicate q = i -> i < 200; 53 | Predicate r = i -> i%2 == 0; 54 | Predicate notP = p.negate(); 55 | 56 | // 100 <= i && (i < 200 || i%2==0) 57 | Predicate all = notP.and(q.or(r)); 58 | System.out.println(all.test(150)); // true 59 | ~~~ 60 | 61 | static 메서드인 isEqual()은 두 대상을 비교하는 Predicate를 만들 때 사용한다. 62 | isEqual()의 매개변수로 비교대상을 하나 지정하고, 또 다른 비교대상은 test()의 매개변수로 지정한다. 63 | 64 | ~~~java 65 | Predicate p = Predicate.isEqual(str1); 66 | boolean result = p.test(str2); //str1과 str2가 같은지 비교하여 결과를 반환 67 | 68 | // 위의 두 문장을 하나로 합치면 69 | boolean result = Predicate.isEqual(str1).test(str2); 70 | ~~~ 71 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-12.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #33 - 람다식(Lambda expression) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 람다식 6 | 7 | ## 1.1. 메서드 참조(Method reference) 8 | >람다식이 하나의 메서드만 호출하는 경우, 메서드 참조를 통해 람다식을 간략히 할 수 있다. 9 | >클래스명::메서드명 또는 참조변수::메서드명 10 | ~~~java 11 | // 기존 12 | Function f = (String s) -> Integer.parseInt(s); 13 | 14 | // 메서드 참조 15 | Funcation f = Integer::parseInt; 16 | ~~~ 17 | 18 | 생성자를 호출하는 람다식도 메서드 참조로 변환 가능 19 | 20 | ~~~java 21 | Supplier s = () -> new MyClass(); // 람다식 22 | Supplier s = MyClass::new; // 메서드 참조 23 | ~~~ 24 | 25 | 배열 생성할 경우 26 | 27 | ~~~java 28 | Function f = x -> new int[x]; // 람다식 29 | Function f2 = int[]::new; // 메서드 참조 30 | ~~~ 31 | 32 | ## 2. 스트림(Stream) 33 | 34 | ## 2.1. 스트림이란? 35 | >스트림은 데이터 소스를 추상화하고, 데이터를 다루는데 자주 사용되는 메서드들을 정의해 놓았다. 36 | 37 | Collection이나 Iterator 같은 인터페이스를 이용해서 컬렉션을 다루는 방식을 표준화 했지만, 각 컬렉션 클래스에는 같은 기능의 메서드들이 중복해서 정의되어 있다. List를 정렬할 때는 Collection.sort()를 사용해야하고, 배열을 정렬할 때는 Arrays.sort()를 사용해야 한다. 이렇게 데이터 소스마다 다른 방식으로 다루어야하는 문제점을 해결해주는 것이 Stream 이다. 38 | 39 | ~~~java 40 | // 기존 41 | String[] strArr = {"aaa", "bbb", "ccc"}; 42 | List strList = Arrays.asList(strArr); 43 | 44 | // 스트림 생성 45 | Stream strStream1 = strList.stream(); 46 | Stream strStream2 = Arrays.stream(strArr); 47 | 48 | // 스트림 출력 49 | strStream1.sorted().forEach(System.out::println); 50 | strStream2.sorted().forEach(System.out::println); 51 | ~~~ 52 | 53 | - 스트림은 데이터 소스로 부터 데이터를 읽기만 할 뿐, 변경하지 않는다. 54 | - 스트림은 한번 사용하면 닫혀서 다시 사용할 수 없다. 55 | - 스트림은 작업을 내부 반복으로 처리한다. 56 | 57 | ~~~java 58 | void forEach(Consumer action) { 59 | Objects.requireNonNull(action); // 매개변수의 널 체크 60 | 61 | for(T t : src) { 62 | action.accept(T); 63 | } 64 | } 65 | ~~~ 66 | 67 | - 스트림은 최종 연산이 수행되기 전까지 중간 연산이 수행되지 않는다. 중간 연산을 호출하는 것은 단지 어떤 작업이 수행되어야하는지를 지정해주는 것일 뿐이다. 68 | - 요소의 타입이 T인 스트림은 Stream이지만, 오토박싱/언박싱의 비효율을 줄이기 위해 69 | 데이터 소스의 요소를 기본형으로 다루는 InsStream, LongStream, DoubleStream이 제공된다. 70 | - 병렬스트림은 내부적으로 fork&join 프레임웍을 이용해서 자동적으로 연산을 병렬로 수행한다. 스트림에 parallel() 메서드를 호출하면 병렬로 연산하고, parallel()을 취소하려면 sequential()을 호출한다. 71 | - parallel()과 sequential()은 새로운 스트림을 생성하는 것이 아니라, 그저 스트림의 속성을 변경할 뿐이다. 72 | 73 | ~~~java 74 | int sum = strStream.parallelStream() 75 | .mapToInt(s -> s.length()) 76 | .sum(); 77 | ~~~ 78 | 79 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-18.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #35 - 스트림(Stream) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 스트림(Stream) 6 | 7 | ## 1.1. 스트림의 중간연산 8 | 9 | ### 스트림 자르기 10 | >Stream skip(long n) // 처음 n개의 요소 건너뛰기 11 | >Strema limit(long maxSize) // 스트림의 요소를 maxSize개로 제한 12 | 13 | ~~~java 14 | IntStream exampleStream = IntStream.rangeClosed(1, 10); // 1~10의 요소를 가진 스트림 15 | exampleStream.skip(3).limit(5).forEach(System.out::print); // 45678 16 | ~~~ 17 | 18 | ### 스트림 요소 걸러내기 19 | >distinct()는 스트림에서 중복된 요소들 제거 20 | >filter()는 주어진 조건(Predicate)에 맞지 않는 요소를 걸러낸다. 21 | 22 | ~~~java 23 | // distinct() 24 | IntStream exampleStream = IntStream.of(1,2,2,3,3,3,4,5,5,6); 25 | exampleStream.distinct().forEach(System.out::print); // 123456 26 | 27 | // filter() 28 | IntStream example2Stream = IntStream.rangeClosed(1, 10); 29 | example2Stream.filter(i -> i%2 ==0).forEach(System.out::print); // 246810 30 | 31 | // filter()를 다른 조건으로 여러 번 사용. 두 문장의 결과는 같다. 32 | example2Stream.filter(i -> i%2!=0 && i%3!=0).forEach(System.out::print); //157 33 | example2Stream.filter(i -> i%2!=0).filter(i -> i%3!=0).forEach(System.out::print); 34 | ~~~ 35 | 36 | ### 스트림 정렬 37 | >Stream sorted() 38 | >Stream sorted(Comparator comparator) 39 | 40 | ~~~java 41 | Stream strStream = Stream.of("dd","aaa","CC","cc","b"); 42 | strStream.sorted().forEach(System.out::print); // CCaaabccdd 43 | 44 | // 기본정렬 역순 45 | strStream.sorted(Comparator.reverseOrder()); 46 | 47 | // 대소문자 구분 없이 48 | strStream.sorted(String.CASE_INSESITIVE_ORDER) 49 | 50 | // 길이 순 정렬 51 | strStream.sorted(Comparator.comparing(String::length)) 52 | 53 | //정렬 조건을 추가할 때는 thenComparing() 사용 54 | studentStream.sorted(Comparator.comparing(Student::getBan) 55 | .thenComparing(Student::getTotalScore) 56 | .thenComparing(Student::getName) 57 | .forEach(System.out::println); 58 | ~~~ 59 | 60 | ### 스트림 변환 61 | >스트림의 요소에 저장된 값 중에서 원하는 필드만 뽑아내거나, 특정 형태로 변환해야 할 때 62 | >map() 사용 63 | 64 | ~~~java 65 | // map()으로 Stream을 Stream으로 변환하기 66 | 67 | Stream fileStream = Stream.of(new File("Ex1.java"), new File("Ex2.java")); 68 | Stream filenameStream = fileStream.map(File::getName); 69 | filenameStream.forEach(System.out::println); 70 | 71 | // map() 여러 번 사용 72 | 73 | fileStream.map(File::getName) // Stream -> Stream 74 | .filter(s -> s.indexOf('.')!= -1) // 확장자 없는 것 제외 75 | .map(s -> s.substring(s.indexOf('.')+1)) // Stream -> Stream 76 | .map(String::toUpperCase) // 모두 대문자로 변환 77 | .distinct() 78 | .forEach(System.out::print); 79 | ~~~ 80 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-21.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #37 - 스트림(Stream) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 스트림(Stream) 6 | 7 | ## 1.1. Optional 8 | >Optional은 지네릭 클래스로 'T타입의 객체'를 감싸는 래퍼 클래스다. 9 | >그래서 Optional타입의 객체에는 모든 타입의 참조변수를 담을 수 있다. 10 | 11 | 최종 연산의 결과를 그냥 반환하는 것이 아니라 Optional 객체에 담아서 반환하면, 12 | 반환된 결과가 null인지 매번 if문으로 체크하는 대신 Optional에 정의된 메서드를 통해 간단히 처리할 수 있다. 13 | 14 | ### Optional 객체 생성하기 15 | >of() 또는 ofNullable() 사용 16 | 17 | ~~~java 18 | //참조변수의 값이 null일 가능성이 있으면 of()대신 ofNullable() 사용 19 | Optional optVal = Optional.of(null); //NullPointerException 발생 20 | Optional optVal = Optional.ofNullable(null); // OK 21 | 22 | //Optional 타입의 참조변수를 기본값으로 초기화할 때 empty() 사용 23 | //null로 초기화할 수 있지만 empty()로 초기화하는 것이 바람직 24 | Optional optVal = null; 25 | Optional optVal = Optional.empty(); // 빈 객체로 초기화 26 | ~~~ 27 | 28 | ### Optional 객체의 값 가져오기 29 | >get(), orElse() 30 | 31 | ~~~java 32 | Optional optVal = Optional.of("abc"); 33 | String str1 = optVal.get(); // optVal에 저장된 값을 반환. null이면 예외발생 34 | String str2 = optVal.orElse(""); // optVal에 저장된 값이 null이면 ""를 반환 35 | String str3 = optVal.orElseGet(String::new); // null을 대체할 값을 반환하는 람다식 지정 36 | String str4 = optVal.orElseThrow(NullPointerException::new); // null일 때 지정된 예외를 발생 37 | ~~~ 38 | 39 | >isPresent()는 Optional 객체의 값이 null이면 false를, 아니면 true 반환 40 | >ifPresent(Consumer block)는 값이 있으면 주어진 람다식 실행, 없으면 아무일 안함 41 | 42 | ~~~java 43 | //조건문 44 | if(str!=null) { 45 | System.out.println(str); 46 | } 47 | 48 | //위의 조건문을 isPresent()로 구현 49 | if(Optional.ofNullable(str).isPresent()) { 50 | System.out.println(str); 51 | } 52 | 53 | //위의 조건문을 ifPresent()로 구현 54 | Optional.ofNullable(str).ifPresent(System.out::println); 55 | ~~~ 56 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-22.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #38 - 스트림(Stream) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 스트림(Stream) 6 | 7 | ## 1.1. 스트림의 최종 연산 8 | >최종 연산은 스트림의 요소를 소모해서 결과를 만든다. 그래서 최종 연산후에는 스트림이 닫혀서 더이 상 사용할 수 없다. 9 | 10 | ### forEach() 11 | >반환 타입이 void이므로 스트림의 요소를 출력하는 용도로 많이 사용 12 | 13 | ### 조건검사 14 | >allMatch(), anyMatch(), noneMatch(), findFirst(), findAny() 15 | 16 | ~~~java 17 | boolean allMatch (Predicate predicate) 18 | boolean anyMatch (Predicate predicate) 19 | boolean noneMatch (Predicate predicate) 20 | 21 | // 학생성적 스트림에서 총점이 낙제점 이하인 학생 확인 22 | boolean noFailed = stuStream.anyMatch(s->s.getTotalScore()<=100); 23 | 24 | // 스트림 요소 중 조건에 일치하는 첫 번째 것 반환 25 | Optional stu = stuStream.filter(s->s.getTotalScore()<=100).findFirst(); 26 | 27 | // 병렬스트림의 경우 findFirst() 대신 findAny() 사용 28 | Optional stu = parallelStream.filter(s->s.getTotalScore()<=100).findAny(); 29 | ~~~ 30 | 31 | ### 통계 32 | >count(), sum(), average(), max(), min() 33 | 34 | ~~~java 35 | // 기본형 스트림이 아닌 경우 통계 관련 메서드는 아래 3개 뿐이다. 36 | // 기본형 스트림의 min(), max()와 달리 매개변수로 Comparator가 필요하다. 37 | long count() 38 | Optional max(Comparator comparator) 39 | Optional min(Comparator comparator) 40 | ~~~ 41 | 42 | ### reduce() 43 | >reduce()는 스트림의 요소를 줄여나가면서 연산을 수행하고 최종결과를 반환한다. 44 | >그래서 매개변수의 타입이 BinaryOperator 이다. 45 | >처음 두 요소를 가지고 연산한 결과로 그 다음 요소와 연산한다. 46 | >모든 스트림의 요소를 소모하게 되면 그 결과를 반환한다. 47 | 48 | ~~~java 49 | Optional reduce(BinaryOperator accumulator) 50 | ~~~ 51 | 52 | >reduce()의 사용방법은 초기값과 어떤 연산(BinaryOperator)으로 스트림의 요소를 줄여나갈 것인지만 결정하면 된다. 53 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-23.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #39 - 스트림(Stream) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 스트림(Stream) 6 | 7 | ## 1.1. collect() 8 | >스트림의 요소를 수집하는 최종 연산 9 | >collect()가 스트림의 요소를 수집하기 위한 수집 방법이 정의된 것이 collector. 10 | >collector는 Collector인터페이스를 구현한 것. 11 | 12 | ~~~ 13 | collect() 스트림의 최종 연산. 매개변수로 collector가 필요하다. 14 | Collector 인터페이스. collector는 이 인터페이스를 구현해야한다. 15 | Collectors 클래스. static 메서드로 미리 작성된 collector를 제공한다. 16 | ~~~ 17 | 18 | collect()의 매개변수 타입은 Collector인데. 매개변수가 Collector를 구현한 클래스의 객체이어야 한다는 뜻. 19 | 그리고 collect()는 이 객체에 구현된 방법대로 스트림의 요소를 수집한다. 20 | 21 | ### 스트림을 컬렉션과 배열로 변환 22 | >toList(), toSet(), toMap(), toCollection(), toArray() 23 | 24 | ~~~java 25 | // 스트림의 모든 요소를 컬렉션에 수집하려면, Collectors클래스의 toList()와 같은 메서드를 사용하면 된다. 26 | List names = stuStream.map(Student::getName) 27 | .collect(Collectors.toList()); 28 | 29 | // List나 Set이 아닌 특정 컬렉션을 지정하려면, 30 | // toCollection()에 해당 컬렉션의 생성자 참조를 매개변수로 넣어주면 된다. 31 | ArrayList list = names.stream() 32 | .collect(Collectors.toCollection(ArrayList::new)); 33 | 34 | // Map은 객체의 어떤 필드를 키와 값으로 사용하지 지정해야 한다. 35 | // 요소의 타입이 Person인 스트림에서 사람의 주민번호(regId)를 키로 하고, 값으로 Person 객체를 그대로 저장 36 | Map map = personStream.collect(Collectors.toMap(p->p.getRegId(), p->p) 37 | 38 | // 스트림에 저장된 요소들을 T[] 타입의 배열로 변환하려면 toArray() 사용 39 | // 단, 해당 타입의 생성자 참조를 매개변수로 지정해줘야 한다. 지정하지 않으면 반환되는 배열의 타입은 Object[] 40 | Student[] stuNames = studentStream.toArray(Student[]::new); // OK 41 | Student[] stuNames = studentStream.toArray(); // 에러 42 | Object[] stuNames = studentStream.toArray(); // OK 43 | ~~~ 44 | 45 | ### 통계 46 | >counting(), summingInt(), averagingInt(), maxBy(), minBy() 47 | 48 | ### 문자열 결합 49 | >joining() 50 | >스트림의 요소가 String이나 StringBuffer처럼 CharSequence의 자손인 경우에만 결합 가능하므로 51 | >스트림의 요소가 문자열이 아닌 경우에는 먼저 map()을 이용해서 스트림의 요소를 문자열로 변환해야 한다. 52 | 53 | ~~~java 54 | String studentNames = stuStream.map(Student::getName).collect(joining()); 55 | String studentNames = stuStream.map(Student::getName).collect(joining(",")); 56 | String studentNames = stuStream.map(Student::getName).collect(joining(",", "[", "]")); 57 | 58 | // 만약 map()없이 스트림에 바로 joining()하면, 스트림의 요소에 toString()을 호출한 결과를 결합한다. 59 | String studentInfo = stuStream.collect(joining(",")); 60 | ~~~ 61 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/2018-11-26.md: -------------------------------------------------------------------------------- 1 | # 아침공부 #41 - 스트림(Stream) 2 | >자바의 정석(남궁성 저) 2권 학습 3 | 4 | 5 | ## 1. 스트림(Stream) 6 | 7 | ## 1.1. 스트림의 변환 8 | 9 | |from|to|변환메서드| 10 | |---|---|---| 11 | |**1. 스트림 -> 기본형 스트림**| 12 | |Stream|IntStream|mapToInt (ToIntFunction mapper)| 13 | ||LongStream|mapToLong (ToLongFunction mapper)| 14 | ||DoubleStream|mapToDouble (ToDoubleFunction mapper)| 15 | |**2. 기본형 스트림 -> 스트림**| 16 | |IntStream|Stream| 17 | |LongStream|Stream|boxed() 18 | |DoubleStream|Stream| 19 | ||Stream|mapToObj (DoubleFunction mapper) 20 | |**3. 스트림의 스트림 -> 스트림**| 21 | |Stream>|Stream|flatMap (Function mapper)| 22 | |Stream|IntStream|flatMapToInt (Function mapper)| 23 | |Stream|LongStream|flatMapToLong (Function mapper)| 24 | |Stream|DoubleStream|flatMapToDouble (Function mapper)| 25 | |**4. 컬렉션 -> 스트림**| 26 | |Collection, List, Set|Stream|stream()| 27 | -------------------------------------------------------------------------------- /Early-Bird/2018-11/README.md: -------------------------------------------------------------------------------- 1 | ## 2018년 11월의 아침공부 후기 2 | 3 | - 출석률 43% (13일/30일) 4 | - 자바의정석을 끝냈다. 5 | - 12월의 아침에는 알고리즘, SQL, HTTP 책들을 볼 예정이다. 6 | -------------------------------------------------------------------------------- /Early-Bird/README.md: -------------------------------------------------------------------------------- 1 | ## 아침공부 기록소 2 | 3 | ## 폐쇄 4 | >아침에 학습한 내용도 해당 주제에 맞는 카테고리에 작성하기로 하였다. 5 | -------------------------------------------------------------------------------- /Git/Submodule.md: -------------------------------------------------------------------------------- 1 | # Git Submodule 2 | >Hugo와 Github page로 Static Blog를 만들었는데, Submodule을 사용하고있다. 사용하면서 Submodule이 눈에 거슬릴 때마다 조금씩 공부하고자 한다. 3 | 4 | - 서브모듈은 Git 저장소 안에 다른 Git 저장소를 둘 수 있게 해준다. 이렇게 해도 두 Git저장소 모두 여전히 독립적으로 관리된다. 5 | 6 | ## *Reference 7 | - https://git-scm.com/book/ko/v1/Git-%EB%8F%84%EA%B5%AC-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88 8 | -------------------------------------------------------------------------------- /Git/rm_cached.md: -------------------------------------------------------------------------------- 1 | # 원격저장소에 Commit한 파일 삭제하기 2 | >$ git rm --cached 3 | >>.gitignore 파일에 내용을 제대로 갖추지 않아서 bin 폴더가 함께 원격 저장소에 Push 되었다. 4 | >>저장소 자체를 삭제하고 다시 만들까 생각했지만, git rm -r --cached bin 명령으로 5 | >>간단하게 bin 폴더만 원격저장소에서 제거할 수 있었다. 6 | 7 | ### 옵션 8 | - `$ git rm [파일명]` : 원격저장소와 로컬저장소에 있는 파일 삭제 9 | - `$ git rm --cached [파일명]` : 원격저장소의 파일만 삭제 10 | - `$ git rm -r --cached [폴더명]` : 원격저장소의 폴더 내의 모든 파일 삭제 11 | 12 | ## Reference 13 | - [GitHub Help - Removing files from a repository's history](https://help.github.com/articles/removing-files-from-a-repository-s-history/) 14 | - http://mygumi.tistory.com/103 15 | -------------------------------------------------------------------------------- /Go/30minGo/Function_and_Variable.md: -------------------------------------------------------------------------------- 1 | # 함수와 변수 2 | 3 | ## 1. 함수와 매개변수 4 | ~~~go 5 | pacakage main 6 | 7 | import "fmt" 8 | 9 | // 1. 매개변수 타입, 리턴 타입은 이름 뒤에 지정한다. 10 | func add1(x int, y int) int { 11 | return x + y 12 | } 13 | 14 | // 2. 매개변수 x, y가 같은 타입일 때에는 타입을 한 번만 명시해 줄 수 있다. 15 | func add2(x, y int) int { 16 | return x + y 17 | } 18 | 19 | func main() { 20 | fmt.Println("add1(x int, y int)의 결과: ", add1(42, 13)) 21 | fmt.Println("add2(x, y int)의 결과: ", add2(42, 13)) 22 | } 23 | ~~~ 24 | - 타입은 매개변수 뒤에 표시한다. 25 | - 리턴 타입도 가장 뒤에 표시한다. 26 | - 같은 타입의 변수 여러 개를 선언할 때에는 타입을 한 번만 적어도 된다. 27 | 28 | ## 2. 함수와 여러가지 리턴 방법 29 | - 함수는 여러 값을 한 번에 return할 수 있다. 30 | - return 뒤에 리턴 타입을 적어주는 방법 31 | - return 뒤에 리턴 할 변수를 선언하는 방법 32 | -------------------------------------------------------------------------------- /Go/30minGo/README.md: -------------------------------------------------------------------------------- 1 | >Programmers 강의인 ['30분 Go'](https://programmers.co.kr/learn/courses/13)를 공부하고 기록! 2 | 3 | 4 | # Hello World! 5 | ~~~go 6 | package main 7 | 8 | import "fmt" 9 | 10 | func main() { 11 | fmt.Println("Hello world") 12 | } 13 | ~~~ 14 | -------------------------------------------------------------------------------- /Go/HelloWorld.md: -------------------------------------------------------------------------------- 1 | > Go를 학습해야 할 일이 생겼다. Go! 2 | 3 | - 프로그래머스 무료강의인 [30분 Go](https://programmers.co.kr/learn/courses/13)를 수강하며 기록한다. 4 | -------------------------------------------------------------------------------- /Java/CompleatableFuture.md: -------------------------------------------------------------------------------- 1 | ## CompletableFuture 사용 예시 2 | >급하게 사용하게 된 CompletableFuture 사용 기록 3 | 4 | ~~~java 5 | /** 6 | * 벤더 상세조회 (Async) 7 | * 8 | * @param utmCode 벤더 식별 아이디 9 | * @return 벤더 상세조회 응답 객체 10 | */ 11 | public DetailedVendorDTO getDetailedVendorAsync(String utmCode) { 12 | CompletableFuture> vendorHasServiceAsync = getVendorHasServiceAsync(utmCode); 13 | CompletableFuture> tokensByUtmCodeAsync = getTokensByUtmCodeAsync(utmCode); 14 | 15 | DetailedVendorDTO detailedVendorDTO = vendorHasServiceAsync 16 | .thenCombine(tokensByUtmCodeAsync, 17 | (services, tokens) -> DetailedVendorDTO.builder() 18 | .servicesByVendor(services) 19 | .tokenList(tokens) 20 | .build() 21 | ) 22 | .join(); 23 | 24 | return detailedVendorDTO; 25 | } 26 | 27 | private CompletableFuture> getVendorHasServiceAsync(String utmCode) { 28 | CompletableFuture future = new CompletableFuture<>(); 29 | new Thread(() -> { 30 | log.info("새로운 쓰레드로 벤더가 사용중인 서비스 목록 조회"); 31 | List vendorHasServiceByUtmCode = vendorHasServiceReadRepository.findVendorHasServiceByUtmCode(utmCode); 32 | List services = vendorHasServiceByUtmCode.stream() 33 | .map(DynamoTable::getSk) 34 | .collect(Collectors.toList()); 35 | future.complete(services); 36 | }).start(); 37 | 38 | return future; 39 | } 40 | 41 | private CompletableFuture> getTokensByUtmCodeAsync(String utmCode) { 42 | CompletableFuture future = new CompletableFuture<>(); 43 | new Thread(() -> { 44 | log.info("새로운 쓰레드로 벤더가 사용중인 토큰 목록 조회"); 45 | List tokensByUtmCode = tokenReadRepository.findTokensByUtmCode(utmCode); 46 | List tokens = tokensByUtmCode.stream() 47 | .map(TokenResponseDTO::from) 48 | .collect(Collectors.toList()); 49 | future.complete(tokens); 50 | }).start(); 51 | 52 | return future; 53 | } 54 | ~~~ 55 | 56 | ### Reference 57 | - https://brunch.co.kr/@springboot/267 58 | -------------------------------------------------------------------------------- /Java/DWR.md: -------------------------------------------------------------------------------- 1 | 2 | # DWR (Direct Web Remoting) 3 | > ajax를 기반으로 Client side의 javascript로 Server side의 Java Beans를 interative하게 조작할 수 있는 framework 4 | > 실제 사용해본 느낌은, Controller를 추가로 생성하지 않고 jsp파일의 script에서 바로 service.메소드()를 호출할 수 있어서 편리함. 5 | > 단점은 좀 더 알아보고 이 곳에 정리할 예정.. 6 | 7 | ### DWR 사용 흐름 8 | ![](http://skccdev.pbworks.com/f/20060905_dwr_architecture.jpg) 9 | 10 | # 사용 순서 11 | 1. DWR JAR file 설치 12 | - dwr.jar 파일을 [다운로드](http://directwebremoting.org/dwr/downloads/index.html)받아 WEB-INF/lib 디렉토리에 추가한다. 13 | 2. Commons Logging JAR file 설치 14 | - DWR은 Commons Logging에 의존하므로 commons-logging.jar를 [다운로드](http://commons.apache.org/proper/commons-logging/)받아서 WEB-INF/lib 디렉토리에 추가한다. 15 | 3. web.xml에 DWR servlet definition과 mapping 추가 16 | ~~~xml 17 | 18 | DWR Servlet 19 | dwr-invoker 20 | org.directwebremoting.servlet.DwrServlet 21 | 22 | debug 23 | true 24 | 25 | 26 | 27 | dwr-invoker 28 | /dwr/* 29 | 30 | ~~~ 31 | 4. DWR config file(dwr.xml) 만들기 32 | - web.xml 옆에 dwr.xml 파일을 아래와 같이 작성한다. 33 | ~~~xml 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | ~~~ 49 | 50 | 51 | # Reference 52 | - http://directwebremoting.org/dwr/index.html 53 | - http://rajalo.tistory.com/entry/%ED%8E%8C-DWR-%EC%84%A4%EB%AA%85%EA%B3%BC-%EC%82%AC%EC%9A%A9%EB%B2%95 54 | -------------------------------------------------------------------------------- /Java/IO.md: -------------------------------------------------------------------------------- 1 | > 입출력을 대충 공부하고 복붙으로만 쓰다가 제대로 실습! 2 | 3 | # 일반적인 I/O 4 | ~~~java 5 | InputStream is = null; 6 | OutputStream os = null; 7 | 8 | try { 9 | is = new FileInputStream("/Users/ryanhan/test.txt"); 10 | os = new FileOutputStream("/Users/ryanhan/test2.txt"); 11 | 12 | while(true) { 13 | int i = is.read(); 14 | if(i==-1) 15 | break; 16 | os.write(i); 17 | } 18 | } catch (Exception e) { 19 | e.printStackTrace(); 20 | } finally { 21 | if(is != null) { 22 | try { 23 | is.close(); 24 | } catch (Exception e2) { 25 | e2.printStackTrace(); 26 | } 27 | } 28 | if(os != null) { 29 | try { 30 | os.close(); 31 | } catch (Exception e2) { 32 | e2.printStackTrace(); 33 | } 34 | } 35 | ~~~ 36 | 37 | # byte[]를 활용하여 더 빠른 I/O 38 | ~~~java 39 | InputStream is = null; 40 | OutputStream os = null; 41 | 42 | try { 43 | is = new FileInputStream("/Users/ryanhan/test.txt"); 44 | os = new FileOutputStream("/Users/ryanhan/test2.txt"); 45 | 46 | byte[] bs = new byte[5]; 47 | 48 | while(true) { 49 | int count = is.read(bs); 50 | if(count == -1) { 51 | break; 52 | } 53 | os.write(bs, 0, count); 54 | } 55 | 56 | } catch (Exception e) { 57 | e.printStackTrace(); 58 | } finally { 59 | if(is != null) { 60 | try { 61 | is.close(); 62 | } catch (Exception e2) { 63 | e2.printStackTrace(); 64 | } 65 | } 66 | if(os != null) { 67 | try { 68 | os.close(); 69 | } catch (Exception e2) { 70 | e2.printStackTrace(); 71 | } 72 | } 73 | } 74 | ~~~ 75 | 76 | # Data I/O Stream을 이용한 문자열 읽고 쓰기 77 | ~~~java 78 | InputStream is = null; 79 | DataInputStream dis = null; 80 | 81 | OutputStream os = null; 82 | DataOutputStream dos = null; 83 | 84 | try { 85 | is = new FileInputStream("Users/ryanhan/test.txt"); 86 | dis = new DataInputStream(is); 87 | String str = dis.readUTF(); 88 | 89 | os = new FileOutputStream("Users/ryanhan/test2.txt"); 90 | dos = new DataOutputStream(os); 91 | dos.writeUTF(str); 92 | 93 | } catch (Exception e) { 94 | 95 | } finally { 96 | if( dos != null) { 97 | try { 98 | dos.close(); 99 | } catch (Exception e2) { 100 | e2.printStackTrace(); 101 | } 102 | } 103 | if(os != null) { 104 | try { 105 | os.close(); 106 | } catch (Exception e2) { 107 | e2.printStackTrace(); 108 | } 109 | } 110 | 111 | } 112 | ~~~ 113 | -------------------------------------------------------------------------------- /Java/Lombok.md: -------------------------------------------------------------------------------- 1 | 2 | # Lombok Project 3 | > 회사에서 Lombok을 사용중이라 공부 시작! 4 | > [Lombok Project](https://projectlombok.org/)에서 4분짜리 데모 영상을 보면 Lombok이 뭔지 간단하게 알 수 있다. 5 | >>2016년 여름 인도네시아 발리로 한달 동안 서핑여행을 갔을 때 Lombok이라는 지역의 파도가 좋았었다... 6 | 7 | # 주요 기능 8 | >Lombok Project에서 소개한 [Lombok의 주요 기능 리스트](https://projectlombok.org/features/all)가 가장 유용한 정보였다. 9 | ## @Data 10 | - ~사실 @Data 이것만 사용해도 무방한 것 같다.~ [손권남님이 작성한 Lombok 사용시 주의사항 읽어보기](https://projectlombok.org/features/all) 11 | - 실무에서는 가급적 @Getter @Setter @ToString 만 사용하는 것이 좋다. 12 | - @Data는 밑에 설명할 @Getter, @Setter, @RequiredArgsConstructor, @ToString, @EqualsAndHashCode을 한꺼번에 설정해준다. 13 | - 클래스 레벨에서 @Data 어노테이션을 붙여주면, 모든 필드를 대상으로 접근자와 설정자가 자동으로 생성되고, final 또는 @NonNull 필드 값을 파라미터로 받는 생성자가 만들어지며, toStirng, equals, hashCode 메소드가 자동으로 만들어진다. 14 | # 동작 원리 15 | - java source를 컴파일할 때 annotation processor로 등록된 lombok processor가 parsing 된 AST(Abstract Syntax Tree)를 annotation을 확인하고 그에 적합한 메쏘드를 생성해줘서 parsing된 AST에 적절한 위치에 넣어주어서 byte code로 변환하게 된다. [출처] PROJECT LOMBOK과 그 사용법|작성자 뜻깊은 태클 16 | 17 | # Reference 18 | - https://projectlombok.org/features/all 19 | - http://kwonnam.pe.kr/wiki/java/lombok/pitfall 20 | - http://www.daleseo.com/lombok-popular-annotations/ 21 | - http://wonwoo.ml/index.php/post/1607 22 | - http://blog.naver.com/PostView.nhn?blogId=rlagyska3319&logNo=220824619962&categoryNo=0&parentCategoryNo=0&viewDate=¤tPage=1&postListTopCurrentPage=1&from=postView 23 | -------------------------------------------------------------------------------- /Java/String_Concatenation.md: -------------------------------------------------------------------------------- 1 | # Java 문자열 연결 방법들 2 | >CodeWars에서 알고리즘 문제들을 풀다보면 문자열 연결할 일이 많았는데, 퍼포먼스 이슈가 많다보니 정리가 필요했다. 3 | 4 | 5 | 이 글에서는 `StringBuilder`, `StringBuffer`, `+ 연산자`, `Concat메서드`를 비교하는 것에 중점을 두었다. 6 | 문자열 연결과 구분에 대한 추가적인 내용은 [아침공부 #8](https://ryan-han.com/post/2018/early-bird/180930/)을 참고하면 좋다. 7 | 8 | 9 | ## 1. Concat 메서드 10 | String 클래스에는 문자열을 이어주는 concat 메서드가 있다. 11 | ~~~java 12 | String sample = "X".concat("Y").concat("Z"); // XYZ 13 | ~~~ 14 | 하지만 Java에서 String 객체는 Immutable(불변)이기 때문에, 새로운 문자열을 더할 때마다 새로운 인스턴스를 생성한다. 그래서 퍼포먼스가 좋지 않다. 15 | 16 | 예를 들어 수십번 String이 더해지는 경우, 각 String의 주소값이 stack에 쌓이고, 17 | 가비지콜렉터가 호출되기 전 까지 클래스들은 heap에 지속적으로 쌓이게 된다. 18 | 즉, 메모리 관리 측면에서 치명적이다. 19 | 20 | 21 | ## 2. StringBuilder 22 | ~~~java 23 | String sample = new StringBuilder().append("X").append("Y").append("Z").toString(); 24 | ~~~ 25 | StringBuilder는 내부적으로 문자열을 가지고 문자열을 변경하는 메서드를 제공한다. 26 | String 객체가 매 수정 시에 새로운 인스턴스를 만드는 것과 달리, 27 | StringBuilder는 문자열을 계속해서 앞뒤로 덧붙이거나 문자열을 삽입, 삭제하는 등 다양한 연산이 가능하다. 28 | 29 | ## 3. StringBuilder vs. StringBuffer 30 | - 두 클래스가 제공하는 메서드는 같다. 둘의 차이는 멀티쓰레드 환경에서 동기화 보장이 되는냐 안되느냐의 차이이다. 31 | - StringBuffer는 thread-safe 이므로 MultiThreaded 환경에서는 StringBuilder를 사용해야 한다. 32 | - StringBuffer는 멀티쓰레드 환경에서 다른 값을 변경하지 못하도록 하므로 33 | **Web이나 소켓환경과 같이 비동기로 동작하는 경우가 많을 때에는 StringBuffer를 사용**하는 것이 안전하다 . 34 | 35 | ## 3. + 연산자 36 | ~~~java 37 | String sample = "X" + "Y" + "Z"; // XYZ 38 | ~~~ 39 | 연산자로도 문자열을 붙일 수 있다. 40 | `+ 연산자`는 Java 1.5 이전에는 concat 메서드와 동일하게 새로운 String 인스턴스를 생성했지만, Java 1.5 부터는 컴파일 단계에서 StringBuilder로 컴파일 되도록 변경되었기 때문에 StringBuilder와 동일하다고 볼 수 있다. 41 | 42 | 간단한 경우에는 가독성이 좋은 + 연산자를 사용하는 것이 좋다. 43 | 하지만 + 연산자는 만들 때마다 StringBuilder 인스턴스를 생성하기 때문에, 44 | 반복문에서 문자열을 조합하는 것처럼 StringBuilder 인스턴스를 생성해서 여러 작업을 하는 경우에는 StringBuilder를 쓰는 것이 좋다. 45 | ~~~java 46 | List list = Array.asList("foo","bar","baz","qux"); 47 | 48 | StringBuilder sb = new StringBuilder(); 49 | for(String s : list){ 50 | sb.append(s); 51 | } 52 | System.out.println(sb); 53 | ~~~ 54 | 55 | ## 4. 성능 비교 56 | ![성능비교](https://docs.google.com/spreadsheets/d/1dV4Pbe2_ZCsc9TDBYsN9u69a2a3xSjCAzxKR7I6fxzg/pubchart?oid=1847999196&format=image) 57 | 출처 : http://www.pellegrino.link/2015/08/22/string-concatenation-with-java-8.html 58 | 59 | 60 | # Reference 61 | - http://javahungry.blogspot.com/2013/06/difference-between-string-stringbuilder.html 62 | - http://www.pellegrino.link/2015/08/22/string-concatenation-with-java-8.html 63 | - https://novemberde.github.io/2017/04/15/String_0.html 64 | - https://www.slipp.net/questions/271 65 | - http://futurecreator.github.io/2018/06/02/java-string-concatenation/ 66 | 67 | -------------------------------------------------------------------------------- /Java/slf4j.md: -------------------------------------------------------------------------------- 1 | https://inyl.github.io/programming/2017/05/05/slf4j.html 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ryan Jeongsu Han 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Linux/Maintaining_Process.md: -------------------------------------------------------------------------------- 1 | # 리눅스 ssh 로그아웃해도 프로세스 유지하기 2 | >챗봇을 만들어보면서 AWS EC2를 사용중인데도 ssh 접속이 끊기면 챗봇 서버도 내려지는 (초보다운)문제가 생겼다. 3 | `java -jar ChatBot~~~.jar &` 명령을 사용하여 백그라운드에서 동작하게끔 했는데도 로그아웃과 함께 프로세스가 종료되는 이유를 몰랐었다. 4 | 알아보니 `&` 명령은 백그라운드에서 동작하게만 할 뿐, ssh의 로그아웃 신호(HUP 신호)를 막지 않는 것을 알게 되어 이참에 정리하였다. 5 | ## 1. nohup 6 | nohup은 HUP(hangup)신호를 무시하도록 만드는 명령어이며, HUP 신호는 터미널이 의존 프로세스들에게 로그아웃을 알리는 방식이다. 7 | 즉, **로그아웃 신호를 무시하도록하여 프로세스를 유지시킨다.** 8 | ~~~ 9 | $ nohup 명령어 & 10 | ~~~ 11 | nohup으로 쉘파일을 실행하면 자동으로 `nohup.out` 파일이 생성되고 이 파일에는 Redirection을 사용하지 않은 출력문자열이 자동으로 저장된다. 12 | 13 | ### 주의사항 1 14 | 위의 명령으로 background에 프로그램을 시작하고, 로그아웃 하더라도 프로세스가 정지신호를 보내는 것을 막아서 이 프로그램의 프로세스를 중단하지 않는다. 하지만 표준 입출력 파일(stdin, stdout, stderr)에 대해 입출력을 수신하면 터미널에 행(hang)이 걸리게 된다. 15 | 16 | ### 주의사항 2 17 | 또 다른 문제는 ssh가 로그오프(행)을 거부하는 것인데, 백그라운드 작업들에 대한 데이터 손실을 거부하기 때문이다. 이 문제는 3개의 모든 입출력 스트림을 Redirection 처리함으로써 극복할 수 있다. 18 | ~~~ 19 | $ nohup ./myprogram > foo.out 2> foo.err < /dev/null & 20 | ~~~ 21 | 22 | ### 주의사항 3 23 | nohup으로 실행할 쉘스크립트 파일(*.sh)는 현재 퍼미션이 755이상이어야 한다. `chmod 755 deloy.sh` 24 | 25 | ## 2. foreground에서 프로세스를 실행중 ssh 로그아웃 할 때 26 | 27 | 1. `ctrl + z` 명령으로 foreground에서 실행중인 프로세스를 중단. 28 | 2. `bg` 명령으로 중단된 프로세스를 background에서 실행. 29 | 3. `disown -h` 명령으로 작업의 소유권을 shell session에서 해제. 30 | 4. `ssh 로그아웃` 31 | 32 | - `disown`은 bash 셀의 내부 명령어로 job table에서 지정된 프로세스를 삭제하여 SIGHUP 신호가 전송되지 않도록 한다. 33 | - `disown [-ar] [-h] [jobspec]` 34 | - 옵션 없이 사용되면 jobspec은 실행 중인 작업 테이블에서 삭제된다. 35 | - `-h` 옵션이 사용되면 jobspec은 테이블에서 삭제되지 않지만, 쉘이 SIGHUP을 수신해도 SIGHUP을 해당 작업에 보내지 않는다. 36 | - `-a``-r`옵션과 jobspec 모두 지정되지 않으면 현재의 작업이 사용된다. 37 | - jobspec이 지정되지 않으면, `-a` 옵션은 모든 작업을 테이블에서 삭제하라는 뜻이다. 38 | - jobspec이 지정되지 않으면, `-r` 옵션은 현재 실행중인 작업에 한정한다는 뜻이다. 39 | - jobspec이 유효한 작업이라면 리턴값은 0이다. 40 | 41 | ## *Reference 42 | - https://ko.wikipedia.org/wiki/Nohup 43 | - http://brownbears.tistory.com/174 44 | -------------------------------------------------------------------------------- /Linux/README.md: -------------------------------------------------------------------------------- 1 | # Linux 2 | 3 | ## [1. SysAdmin Basics](https://github.com/Integerous/TIL/blob/master/Linux/SysAdminBasics.md) 4 | >[tutoriaLinux](https://www.youtube.com/watch?v=bju_FdCo42w&list=PLtK75qxsQaMLZSo7KL-PmiRarU7hrpnwK) 리눅스 기본기를 유튜브 영상으로 학습하며, 익숙하지 않은 명령어들 정리 5 | 6 | ## [2. 프로세스를 유지하는 2가지 방법](https://github.com/Integerous/TIL/blob/master/Linux/Maintaining_Process.md) 7 | >리눅스 ssh를 로그아웃해도 프로세스를 유지시키는 두 가지 방법 정리 8 | 9 | ## [3. 실무에서 만난 쉘 스크립트](https://github.com/Integerous/TIL/blob/master/Linux/Shell_Script_Study.md) 10 | >실무에서 쓰는 쉘 스크립트를 분석하며 공부한 내용 정리 11 | -------------------------------------------------------------------------------- /Node.js/1_BasicConcepts.md: -------------------------------------------------------------------------------- 1 | 2 | # Node.js 기초 3 | 4 | ## 1. V8 엔진 5 | - 구글 개발자 모드에서 console에 가면 자바스크립트를 실행할 수 있었는데, 6 | - Node.js가 나오면서 브라우져 밖에서 자바 스크립트 코드를 실행할 수 있게 되었다. 7 | - Node.js는 크롬에서 사용하는 V8 엔진을 사용하고 있기 때문이다. 8 | - V8 엔진은 자바스크립트 코드를 해석해주는 해석기라고 볼 수 있다. 9 | 10 | ### Node.js만의 특징은 11 | - 이벤트 기반의 비동기 I/O 프레임워크이고, 12 | - CommonJS를 구현한 모듈 시스템이다. 13 | 14 | 15 | ## 2. 이벤트 기반의 비동기 I/O 프레임워크 16 | ### 2.1. 이벤트 기반 ? 17 | - Node.js로 만든 어플리케이션은 클라이언트에서 요청을 보내면, 18 | - 클라이언트의 요청을 Event로 만들어서 Event Queue에 차곡차곡 쌓는다. 19 | - Event Loop는 Event Queue에 있는 Event 하나 하나를 뽑아내서 실행한다. 20 | - Event loop는 싱글스레드이며 일을 처리하여 클라이언트에게 응답한다. 21 | - 즉, 'Node.js는 싱글스레드다' == 'Event loop가 싱글스레드다.' 22 | 23 | ### 2.2. 비동기 I/O ? 24 | - Event Loop가 바로 응답할 수 없고 더 많은 시간이 필요한 Event가 있다. 25 | - 예를 들어 디스크에 있는 파일을 읽거나 외부 네트워크 통신을 하는 경우 큰 자료이기 때문에, 26 | - Event Loop가 직접 실행하지 않고 다른 스레드에게 일을 위임한다. 27 | - Non-blocking Worker가 그 일을 해서 Event queue에 전달한다 28 | - Event Loop는 Event Queue에서 일을 받아 처리하여 클라이언트에 반환한다. 29 | 30 | 31 | ## 3. 모듈 시스템 32 | - 브라우저에서는 모듈을 사용하기 위해 window context를 사용하거나, 33 | - 브라우저에서 전역 객체인 this는 window 객체이다. 34 | - 자바스크립트 어느 곳에서나 window 객체는 전역으로 접근할 수 있다. 35 | - 모듈시스템을 구현할 때는 window.module1 = function() {return 'module1'}; 이렇게 구현하거나, 36 | - window를 생략해서 module1()으로 모듈을 구현했었다. 37 | - RequireJS 같은 의존성 로더를 사용해서 모듈을 구현했었다. 38 | - 하지만 Node.js에서는 새로운 형태의 모듈시스템을 구현했다. 39 | - 이 모듈시스템의 스펙이 되는 것은 CommonJS 이다. 40 | - CommonJS는 파일 형태로 모듈을 관리할 수 있게 한다. 41 | - 웹브라우저에서는 파일에 접근할 수 없었지만 Node.js 는 서버에서 돌아가기 때문에 파일을 읽을 수 있다. 42 | - 때문에 Node.js에서는 파일 하나하나를 모듈로 만들어서 관리할 수 있게 되었다. 43 | 44 | 45 | ## 4. 비동기 세계 46 | - 자바스크립트는 비동기 코드가 많은데, Node.js도 마찬가지로 비동기 코드가 많다. 47 | - 파일을 읽거나, 네트워크 통신을 할 때에도 다 비동기로 한다. 48 | - 때문에 자바나 php처럼 동기로 동작하는 언어들과 다르다. 49 | - Node.js에\ FileSystem 모듈중에 readFile 메서드는 비동기로 동작하고 readFileSync 메서드는 동기로 동작. 50 | - Node.js에서 비동기를 처리할 때는 함수를 파라미터로 넣는 콜백함수를 많이 쓴다. 51 | -------------------------------------------------------------------------------- /Node.js/2_HelloWorld.md: -------------------------------------------------------------------------------- 1 | # Hello Node 2 | - 노드의 헬로월드 코드 링크 https://nodejs.org/dist/latest-v6.x/docs/api/synopsis.html 3 | ~~~C 4 | const http = require('http'); 5 | 6 | const hostname = '127.0.0.1'; 7 | const port = 3000; 8 | 9 | const server = http.createServer((req, res) => { 10 | res.statusCode = 200; 11 | res.setHeader('Content-Type', 'text/plain'); 12 | res.end('Hello World!\n'); 13 | }); 14 | 15 | server.listen(port, hostname, () => { 16 | console.log(`Server running at http://${hostname}:${port}/`); 17 | }); 18 | ~~~ 19 | - 실행 명령 20 | - `$ node index.js` 21 | - 실행 확인 22 | - `curl -X GET 'localhost:3000'` 23 | 24 | ## Hello Node 코드 분석 25 | 1. `const http = require('http')` 26 | - 노드의 기본모듈 중 http라는 모듈을 가져와서 http 변수에 할당 27 | 2. 호스트 네임(내컴퓨터 주소)과 포트 번호(클라이언트와 통신할 포트) 할당 28 | 3. `const server = http.createServer(req, res) =>{}` 29 | - (req, res)=> 는 es6문법으로 function(req, res)와 같다. 30 | - http모듈의 메소드 중 createServer메소드를 실행하고 콜백함수를 넣어준다. 31 | - 콜백함수는 클라이언트가 접속했을 때 동작하는 코드 32 | 4. `res.statusCode = 200;` 33 | - 200은 성공을 의미 34 | 5. `res.end('Hello Node\n');` 35 | - end함수를 통해서 헬로노드라는 문자열을 클라이언트에 보낸다. 36 | 5. `server.listen(port, hostname, () => {}` 37 | - listen은 서버를 요청 대기상태로 만들어주는 함수. 38 | - 요청대기 상태는 서버가 클라이언트의 요청을 받기 위해서 종료하지 않고 대기하는 상태 39 | - listen함수는 파라미터를 3개 받는다. `listen(port, hostname, (콜백함수) =>{} );` 40 | 41 | 6. `{console.log(`Server running at http://${hostname}:${port}/`);` 42 | - 콜백함수는 listen이라는 메서드가 완료되면 호출되는 함수이다. 43 | - String을 정의할때 템플릿 문자열 ( ` )를 썼다. 44 | - ${hostname}은 값으로 인식되어 박힌다. 45 | 46 | ## 라우터 추가 47 | - 현재상태의 서버는 루트 경로로만 접속할 수 있는 서버이다. 48 | - 경로를 추가해도 계속 Hello Node만 응답해주는 상태이다. 49 | - 그러므로 다양한 요청에 응답하는 로직을 만들어야한다. 50 | - 서버가 접속했을 때 응답하는 코드가 CreateServer의 콜백함수이다. 51 | - 요청한 사용자의 경로를 확인해보면 : `console.log(req.url);` - request객체의 url로 요청이 들어온다. 52 | - `if (req.rul === '/')` 등으로 분기문을 만들어서 다양한 요청에 응답하는 api를 만들 수 있다. 53 | - 예시 54 | ~~~javascript 55 | const server = http.createServer((req,res) => { 56 | if (req.url ==='/'){ 57 | res.statusCode = 200; 58 | res.setHeader('Content-Type', 'text/plain'); 59 | res.end('Hello Node\n'); 60 | } else if (req.url === '/users') { 61 | res.statusCode = 200; 62 | res.setHeader('Content-Type', 'text/plain'); 63 | res.end('User list'); 64 | } else { 65 | res.statusCode = 404; 66 | res.end('Not Found'); 67 | } 68 | }); 69 | ~~~ 70 | 71 | - 이렇게 api를 추가해 나갈 수 있지만 분기문이 계속 길어지고 코드도 반복된다. 72 | - 그래서 http 모듈만 쓰지않고 Express.js라는 프레임워크를 사용한다. 73 | -------------------------------------------------------------------------------- /Node.js/3_Express.js.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /OS/OperatingSystemConcepts/Chapter1/1.1_WhatOperatingSystemsDo.md: -------------------------------------------------------------------------------- 1 | # 1.1 What Operating Systems Do 2 | # Reference 3 | - Abraham Silberschatz, Peter B. Galvin, Greg Gagne, *『OPERATING SYSTEM CONCEPTS 9th Edition』*, WILEY, ISBN: 978-11180-9375-7 4 | -------------------------------------------------------------------------------- /OS/OperatingSystemConcepts/Preface.md: -------------------------------------------------------------------------------- 1 | # 서문 2 | 3 | 운영체제는 모든 컴퓨터 시스템에서 필수적인 요소다. 마찬가지로, 운영체제 수업은 모든 컴퓨터공학 교육에서 필수적인 요소다. 4 | 이 분야는 자동차의 임베디드 장치에서부터 정부기관과 국제적인 기업들의 정교한 계획 도구들까지, 우리 일상의 모든 분야에 컴퓨터가 있다. 5 | 그리고 이 분야는 빠른 변화가 진행중이다. 하지만 운영체제의 기본적인 개념은 여전히 확실하게 남아있다. 그리고 그것들이 이 책의 근간이다. 6 | 7 | 우리는 이 책을 대학생에서 대학원 1학년생 수준의 운영체제 입문 수업의 교재로써 집필하였다. 8 | 또한 전문가들에게도 유익할 것으로 기대한다. 이 책은 운영체제의 개념에 대해 명확한 설명을 제공한다. 9 | 단, 우리는 독자들이 기본적인 자료구조와 컴퓨터구조, 그리고 C와 JAVA 같은 고급언어에 익숙하다는 전제 하에 집필하였다. 10 | 운영체제를 이해하기 위해 필요한 하드웨어 지식들은 챕터1에서 다루었다. 11 | 또한 챕터1에서는 대부분의 운영체제에서 일반적으로 사용되는 기본적인 자료구조들을 개략적으로 담고있다. 12 | 예제 코드는 주로 C를 사용하였고, Java도 일부 사용되었다. 하지만 이러한 언어에 능숙하지 않아도 독자는 예제들을 충분히 이해할 수 있을 것이다. 13 | 14 | 개념은 직관적인 서술 방법을 사용하여 제시되었다. 중요한 이론적인 결과들을 다루었지만, 공식적인 증명들은 대부분 생략하였다. 15 | 각 챕터 마지막 부분의 참고문헌 노트에서는 내용과 관련된 연구 결과를 처음 제시하고 증명한 논문들을 확인할 수 있다. 16 | 이 책의 내용들을 왜 사실로 받아들여야 하는지에 대해서는 증명들 대신에 수치와 예시가 사용되었다. 17 | 18 | 이 책에서 다루는 기본적인 개념과 알고리즘 중 일부는 상업적인 운영체제들과 오픈소스 운영체제들에 기초하였다. 19 | 우리의 목표는 특정 운영체제에 얽매이지 않는 일반적인 환경에서의 개념과 알고리즘을 제시하는 것이기 때문이다. 20 | 하지만 우리는 Linux, Microsoft Windows, Apple Mac OS X, 그리고 Solaris와 같은 가장 인기있고 혁신적인 운영체제들과 관련된 많은 예시들을 제시한다. 21 | 또한 두 가지의 우세한 모바일 운영체제인 Android과 iOS의 예시들도 다루었다. 22 | 23 | 책의 구성은 우리의 수년 간의 운영체제 강의 경험과 IEEE와 ACM가 제공하는 커리큘럼 가이드라인이 반영되었다. 24 | 또한, 이전 버전 책의 독자들과 학생들로 부터 받은 많은 의견과 제안들에 더불어, 검토자들에 의해 제공된 피드백들에 대한 답변 또한 제공하였다. 25 | 26 | # Reference 27 | - Abraham Silberschatz, Peter B. Galvin, Greg Gagne, *『OPERATING SYSTEM CONCEPTS 9th Edition』*, WILEY, ISBN: 978-11180-9375-7 28 | -------------------------------------------------------------------------------- /OS/OperatingSystemConcepts/README.md: -------------------------------------------------------------------------------- 1 | >흔히 말하는 '공룡책'은 수학의정석 처럼 운영체제의 바이블로 불리워지는 책이다. 2 | >>그래서 평생 읽을 생각(?)으로 **원서**를 구매했고, 조금씩 공부하고 기록할 계획이다. 3 | >>> 4 | 5 | # 목차 6 | 0. [서문](https://github.com/Integerous/TIL/blob/master/OS/OperatingSystemConcepts/Preface.md) 7 | 1. **소개** 8 | 2. **시스템 구조** 9 | 3. **프로세스 개념** 10 | 4. **멀티쓰레드 프로그래밍** 11 | 5. **프로세스 스케쥴링** 12 | 6. **동기화** 13 | 7. **데드락** 14 | 8. **메모리관리 전략** 15 | 9. **가상메모리 관리** 16 | 10. **파일 시스템** 17 | 11. **파일 시스템 구현** 18 | 12. **대용량 기억장치 구조** 19 | 13. **I/O 시스템** 20 | 14. **시스템 보호** 21 | 15. **시스템 보안** 22 | 16. **리눅스** 23 | 17. **윈도우7** 24 | 18. **영향력있는 운영체제들** 25 | 26 | # Reference 27 | - Abraham Silberschatz, Peter B. Galvin, Greg Gagne, *『OPERATING SYSTEM CONCEPTS 9th Edition』*, WILEY, ISBN: 978-11180-9375-7 28 | -------------------------------------------------------------------------------- /SQL/README.md: -------------------------------------------------------------------------------- 1 | # SQL 기록소 2 | >작성할 때 생소했던 SQL 기록! 3 | 4 | ## 1. SQL문 자가복사하여 더미 데이터 만들기 5 | ~~~sql 6 | insert into tbl_board (title, content, writer) (select title, content, writer from tbl_board); 7 | ~~~ 8 | - 현재 tbl_board 테이블에서 꺼낸 데이터를 다시 tbl_board 테이블에 넣는 방식 9 | - 여러 번 실행하면 현재 데이터의 배수만큼 들어가므로 100만건의 데이터도 금방 만들 수 있다. 10 | 11 | ## 2. 페이징을 위해서 데이터 일부만 출력하기 12 | ~~~sql 13 | select * from tbl_board whrer bno > 0 order by bno desc limit 0, 10' 14 | ~~~ 15 | - 10개씩 데이터를 출력하는 경우 16 | - 1 page = limit 0, 10 17 | - 2 page = limit 10, 10 18 | - 20개씩 데이터를 출력하는 경우 19 | - 1 page = limit 0, 20 20 | - 2 page = limit 20, 20 21 | 22 | ## 3. 테이블에 외래키(foreign key) 추가하기 23 | ~~~sql 24 | alter table tbl_reply add constraint fk_board foreign key (bno) references tbl_board (bno); 25 | ~~~ 26 | >형식 : alter table (테이블명) add constraint (외래키 별칭) foreign key (외래키 줄 컬럼명) references (부모 테이블명) (참조할 테이블명) (옵션) 27 | 28 | 29 | ### 3-1. 외래키 동작 옵션 30 | >옵션은 참조당하는 부모 테이블의 컬럼이 삭제되었을 때 외래키가 어떻게 동작할 것인지에 대한 옵션 31 | - on delete **restrict** - 참조하는 부모테이블의 컬럼이 갱신/삭제 시도 -> 갱신/삭제 불가 32 | - on delete **cascade** - 부모테이블 컬럼 삭제 -> 자식테이블 컬럼 모두 삭제 33 | - on delete **set null** - 부모테이블 컬럼 삭제 -> 자식테이블 컬럼이 모두 NULL 된다. 34 | - on delete **no action** - 부모테이블 컬럼 삭제 -> 무시 35 | - on delete **set default** - 부모테이블 컬럼 삭제 -> 지정된 값으로 대체 36 | 37 | ## 4. 38 | 39 | ~~~sql 40 | 57 | ~~~ 58 | -------------------------------------------------------------------------------- /Spring/@Controller.md: -------------------------------------------------------------------------------- 1 | ## @Controller 2 | >[이일민(토비)님의 Oracle Code Seoul 2017 강연](https://www.youtube.com/watch?v=BFjrmj4p3_Y)에서 짧게 설명된 @Controller의 역할에 대해 정리. 3 | 4 | ~~~java 5 | @Controller 6 | public class HelloWorldController { 7 | @ReqeustMapping("/helloWorld") 8 | public String helloWorld(Model model) { 9 | model.addAttribute("message", "Hello World!"); 10 | return "helloWorld"; 11 | } 12 | } 13 | ~~~ 14 | 15 | 위 코드에서 @Controller의 역할은 16 | 17 | 1. 스프링 빈 스캐너에 의해서 싱글톤 빈으로 등록 18 | 2. 빈 이름을 지정하지 않아도 클래스명의 제일 앞글자만 소문자로 바꿔서 helloWorldController으로 빈이름 지정 19 | 3. MVC 컨트롤러 기능 담당 20 | 4. @Controller가 붙은 클래스에 @RequestMapping가 있으면, 이것을 맵핑정보로 활용해서 웹컨트롤러 메소드로 사용하게 해준다. 21 | -------------------------------------------------------------------------------- /Spring/@ModelAttribute.md: -------------------------------------------------------------------------------- 1 | >Spring 게시판 CRUD 중 게시글 수정을 만들면서 공부하였다. 2 | 3 | # @ModelAttribute 4 | - 작성 예정 5 | ## Reference 6 | - http://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation 7 | -------------------------------------------------------------------------------- /Spring/@RequestBody.md: -------------------------------------------------------------------------------- 1 | # @RequestBody, @ResponseBody 2 | >카카오톡 플러스친구 챗봇을 개발하던 중 @RequestBody를 사용할 일이 생긴 김에 공부하여 정리 3 | 4 | ## 1. @RequestBody 5 | - @RequestMapping에 의해 POST 방식으로 전송된 HTTP 요청 데이터를 String 타입의 body 파라미터로 전달한다. 6 | - @RequestBody를 사용하지 않은 경우 : query parameter, form data를 object에 맵핑한다. 7 | - @RequestBody를 사용하는 경우 : body에 있는 data를 HttpMessageConverter를 이용해 선언한 object에 맵핑한다. 8 | 9 | ### 사용 예시 (카카오톡 플러스친구 챗봇 코드 중 일부) 10 | ~~~java 11 | @RequestMapping(value = "/message", method = RequestMethod.POST) 12 | public ResponseMessageVO message(@RequestBody RequestMessageVO vo) { 13 | 14 | ResponseMessageVO res_vo = new ResponseMessageVO(); 15 | MessageVO mes_vo = new MessageVO(); 16 | String command = vo.getContent(); 17 | 18 | if(command.equals("메뉴")) { 19 | 20 | } 21 | 22 | ~~~ 23 | 24 | res_vo.setMessage(mes_vo); 25 | return res_vo; 26 | } 27 | ~~~ 28 | - 위에서 `@RequestBody`를 사용하여 사용자가 보낸 json 형식의 메세지 데이터를 String 타입의 body 파라미터로 받아서 RequestMessageVO 객체에 담는다. 29 | - 그리고 객체에 담긴 String 데이터를 if문에서 비교하여 사용한다. 30 | 31 | ## 2. @ResponseBody 32 | - @ResponseBody 어노테이션이 @RequestMapping 메서드에서 적용되면 해당 메서드의 리턴 값을 HTTP 응답 데이터로 사용한다. 33 | 34 | ### 사용 예시 35 | - 임의의 Response 객체 생성 36 | ~~~java 37 | public class ResponseTransfer { 38 | private String text; 39 | 40 | // standard getters/setters 41 | } 42 | ~~~ 43 | - @Response 사용 44 | ~~~java 45 | @Controller 46 | @RequestMapping("/post") 47 | public class ExamplePostController { 48 | 49 | @Autowired 50 | ExampleService exampleService; 51 | 52 | @PostMapping("/response") 53 | @ResponseBody 54 | public ResponseTransfer postResponseController( 55 | @RequestBody LoginForm loginForm) { 56 | return new ResponseTransfer("Thanks For Posting!!!"); 57 | } 58 | } 59 | ~~~ 60 | - 결과 61 | ~~~java 62 | {"text":"Thanks For Posting!!!"} 63 | ~~~ 64 | 65 | ## * Reference 66 | - https://www.baeldung.com/spring-request-response-body 67 | - [장인개발자를 꿈꾸는 :: 기록하는 공간](http://devbox.tistory.com/entry/Spring-RequestBody-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98%EA%B3%BC-ReponseBody-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98%EC%9D%98-%EC%82%AC%EC%9A%A9) 68 | - [파란하늘 개발공부](http://bluesky-devstudy.blogspot.com/2016/07/spring-mvc-requestbody.html) 69 | -------------------------------------------------------------------------------- /Spring/@RequestParam.md: -------------------------------------------------------------------------------- 1 | > Spring+Mybatis로 게시판 CRUD 구현하면서 공부한 내용 2 | 3 | # @RequestParam 4 | - Http 요청 파라미터를 메서드의 파라미터로 전달받을 때 사용 5 | 6 | ## @RequestParam vs HttpServletRequest 7 | - @RequestParam("bno")는 request.getParameter("bno")처럼 동작한다. 8 | - @RequestParam이 Servlet의 HttpServletRequest와 다른 점은 문자열, 숫자, 날짜 등의 형 변환이 가능하다는 것. 9 | - 비교 예시 10 | ~~~java 11 | @RequestMapping("board/confirmId") 12 | public String confirmId (HttpServletRequest request, Model model) { 13 | String id = request.getParameter("id"); 14 | String pw = request.getParameter("pw"); 15 | model.addAttribute("identify", id); 16 | model.addAttribute("password", pw); 17 | 18 | return "board/confirmId"; 19 | } 20 | ~~~ 21 | ```java 22 | @RequestMapping("board/confirmId") 23 | public String confirmId (@RequestParam("id") String id, @RequestParam("pw") int pw, Model model) { 24 | model.addAttribute("identify", id); 25 | model.addAttribute("password", pw); 26 | 27 | return "board/confimrId"; 28 | } 29 | ``` 30 | 31 | ## 사용 방법 32 | ~~~java 33 | 메서드(@RequestParam(PARAM) Obj ) 34 | 메서드(@RequestParam Map ) 35 | ~~~ 36 | - PARAM : 전달되는 파라미터의 이름 지정. 이름 외에 기본값(defaultValue), 필수여부(required)를 설정할 수 있다. 37 | 값이 할당될 변수의 타입이 Map 혹은 MultiValueMap일 경우 명시하지 않는다. 38 | - Obj : PARAM으로 지정된 이름과 일치하는 파라미터의 값을 할당할 변수, 39 | 보통 String 타입을 선언하지만 넘어온 값이 반드시 숫자일 경우에 한해서 int등의 숫자 타입도 가능 40 | - @RequestParam 이 적용된 파라미터가 String이 아닐 경우 자동으로 타입 변환 41 | 42 | ## 내가 한 삽질 43 | ```java 44 | @RequestMapping("/delete") 45 | public String deleteByPrimaryKey(@RequestParam(value="artcSeq", defaultValue="1") ArticleKey artcSeq) 46 | ``` 47 | - 위의 코드에서 artcSeq의 값 정수 15가 String으로 들어가서 4시간동안 삽질함 48 | 49 | ## *Reference 50 | - https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestParam.html 51 | -------------------------------------------------------------------------------- /Spring/@RestController.md: -------------------------------------------------------------------------------- 1 | http://highcode.tistory.com/24 2 | -------------------------------------------------------------------------------- /Spring/@SessionAttributes.md: -------------------------------------------------------------------------------- 1 | > 개인적인 학습을 위해 작성한 내용입니다. 최대한 정확한 내용을 담기위해 노력하지만 틀린 내용이 있을 수 있습니다. 지적해주시면 감사하겠습니다. 2 | 3 | > Haru Sketch 프로젝트의 로그인 정보가 member/index 이외의 페이지에서는 유지가 안되어 찾아본 해결책 4 | 5 | # @SessionAttributes 6 | - HTTP 요청에 의해 동작하는 서블릿은 기본적으로 상태를 유지하지 않는다. 7 | - 따라서 매 요청이 독립적으로 처리된다. 8 | - 하나의 HTTP 요청을 처리한 후에는 사용했던 모든 리소스를 정리해 버린다. 9 | - 애플리케이션은 기본적으로 상태를 유지할 필요가 있으므로 @SessionAttributes를 추가하여 로그인 정보를 유지할 수 있다. 10 | 11 | 12 | ## *Reference 13 | - http://javafactory.tistory.com/350 14 | -------------------------------------------------------------------------------- /Spring/@Transient.md: -------------------------------------------------------------------------------- 1 | # @Transient 2 | - @Entity 애노테이션이 붙은 클래스의 모든 속성들은 기본으로 모두 테이블의 필드로 생성하게 된다. 3 | 만약 어떤 속성을 테이블의 필드로 만들고 싶지 않다면, @Transient을 해당 속성 또는 해당 속성의 getter위에 붙이면 된다. 4 | - @Transient 어노테이션을 사용한 필드나 메소드는 DB 테이블에 적용되지 않는다. 5 | 6 | ## 예를 들어 7 | - 회원가입 시 패스워드를 제대로 입력했는지 확인하기 위해서 한 번 더 입력을 하는데, 8 | 이러한 속성은 DB에 저장할 필요가 없기 때문에, @Transient로 설정해 줄 수 있다. 9 | ~~~C 10 | @Entity 11 | public class Member { 12 | private Long memberId; 13 | private String password; 14 | @Transient 15 | private String confirmPassword; 16 | ... 17 | } 18 | ~~~ 19 | # Reference 20 | - http://egloos.zum.com/LuckyChips/v/1692422 21 | - http://whiteship.tistory.com/1169 22 | -------------------------------------------------------------------------------- /Spring/AmazonMQ+SpringBoot.md: -------------------------------------------------------------------------------- 1 | # AmazonMQ + Spring Boot 2 | >AWS SQS를 사용하던 스프링부트 프로젝트를 AmazonMQ로 바꾸면서 작성한 코드 정리 3 | 4 | ## 0. History 5 | - 뉴스팀은 각종 뉴스 매체에서 뉴스 데이터를 받아 파싱하여 뉴스 서비스에 사용하고, 허브팀은 파싱된 뉴스 데이터를 뉴스팀으로부터 받아서 허브 서비스에 사용한다. 6 | - 이 과정에서 파싱된 뉴스 데이터를 전달받기 위해 기존에 AWS SQS의 Queue를 활용한 1:1 메세지 브로킹을 사용해왔다. 7 | - 그런데 TV팀도 뉴스 데이터가 필요해져서, 뉴스에서는 Publish하고, 허브팀과 TV팀이 Subscribe하는 1:N Pub-Sub 방식으로 바꿔야했다. 8 | - AmazonMQ의 Topic을 활용하여 1:N Pub-Sub 방식의 메세지 브로킹을 구현했고, 나(허브팀)는 Subscriber만 구현했다. 9 | 10 | 11 | ## 1. Broker 정보 설정 12 | >application.yml 13 | 14 | ~~~yml 15 | spring: 16 | activemq: 17 | broker-url: ssl://b-xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx-x.mq.ap-northeast-2.amazonaws.com:61617 18 | user: 사용자 19 | password: 비밀번호 20 | 21 | # 로컬 테스트용 MQ 22 | # broker-url: tcp://localhost:61616 23 | # user: admin 24 | # password: admin 25 | ~~~ 26 | - AWS 콘솔에서 생성한 broker 정보를 세팅한다. 27 | - pub-sub 설정을 application.yml 파일에서 할 수도 있다. 28 | ~~~yml 29 | spring: 30 | jms: 31 | pub-sub-domain: true 32 | ~~~ 33 | ## 2. Jms 설정 34 | ~~~java 35 | @EnableJms 36 | @SpringBootApplication 37 | public class SchedulerApplication { 38 | // 생략 39 | } 40 | ~~~ 41 | - 메인클래스에 `@EnableJms` 어노테이션 추가 42 | 43 | ## 3. Jms Listener 설정 44 | ~~~java 45 | @Configuration 46 | @EnableJms 47 | @RequiredArgsConstructor 48 | public class AwsMqListenerConfig { 49 | 50 | private final ConnectionFactory connectionFactory; 51 | private final DefaultJmsListenerContainerFactoryConfigurer configurer; 52 | 53 | @Bean 54 | public JmsListenerContainerFactory newsJmsListenerContainerFactory() { 55 | DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); 56 | 57 | configurer.configure(factory, connectionFactory); 58 | 59 | factory.setPubSubDomain(true); 60 | factory.setSessionTransacted(true); 61 | factory.setErrorHandler(jmsErrorHandler()); 62 | 63 | return factory; 64 | } 65 | 66 | @Bean 67 | public ErrorHandler jmsErrorHandler() { 68 | return e -> ZumServiceAnalysisLogger.log(e.getMessage()); 69 | } 70 | } 71 | ~~~ 72 | - `@EnableJms` 필수 73 | - 위와 같이 `JmsListenerContainerFactory`를 구현해서 각종 설정을 세팅할 수 있다. 74 | 75 | 76 | ## 4. Listener 구현 77 | ~~~java 78 | @Slf4j 79 | @Component 80 | public class AwsMqNewsListener { 81 | 82 | @Transactional(value = "hubTransactionManager") 83 | @JmsListener(destination = "news.topic", containerFactory = "newsJmsListenerContainerFactory") 84 | // @JmsListener(destination = "for.test", containerFactory = "newsJmsListenerContainerFactory") // 로컬 테스트용 MQ 85 | public void receiveMessage(@Payload String data) { 86 | 87 | // 동기화 및 재처리 로직 88 | } 89 | } 90 | ~~~ 91 | - Publisher에서 만든 topic명 (여기서는 `news.topic`)을 destination으로 설정하고, containerFactory를 지정한다. 92 | -------------------------------------------------------------------------------- /Spring/Model_ModelMap_ModelAndView.md: -------------------------------------------------------------------------------- 1 | # Model, Model Map, ModelAndView 차이 2 | - `Model`은 interface 3 | - `Model Map`은 Class 4 | - `ModelAndView`는 ModelMap과 View 객체를 위한 Container. 컨트롤러가 이 둘을 하나의 값으로 리턴할 수 있다. 5 | ## 예시 6 | ### 1. Model 7 | ~~~java 8 | @RequestMapping 9 | public String PrintHello(Model model) { 10 | model.addattribute("message", "Hello World!"); 11 | return "hello"; 12 | ~~~ 13 | ### 2. ModelMap 14 | ~~~java 15 | @RequestMapping("/helloworld") 16 | public String hello(ModelMap map) { 17 | String helloWorldMessage = "Hello world!"; 18 | String welcomeMessage = "Welcome!"; 19 | map.addAttribute("helloMessage", helloWorldMessage); 20 | map.addAttribute("welcomeMessage", welcomeMessage); 21 | return "hello"; 22 | ~~~ 23 | ### 3. ModelAndView 24 | ~~~java 25 | @RequestMapping("/board/reply") 26 | public ModelAndView reply() { // ModelAndView import해야됌 27 | 28 | ModelAndView mv = new ModelAndView(); // ModelAndView 객체 생성 29 | mv.addObject("id", 30); // model 객체에 데이터 담음 30 | mv.setViewName("board/reply") // View 이름 설정 31 | 32 | return mv; 33 | ~~~ 34 | ~~~java 35 | @RequestMapping("/welcome") 36 | public ModelAndView helloWorld() { 37 | String message = "Hello World!"; 38 | return new ModelAndView("welcome", "message", message); 39 | } 40 | ~~~ 41 | 42 | # *Reference 43 | - https://stackoverflow.com/questions/18486660/what-are-the-differences-between-model-modelmap-and-modelandview 44 | -------------------------------------------------------------------------------- /Spring/TilesPreparer.md: -------------------------------------------------------------------------------- 1 | # Tiles View Preparer 2 | >@SessionAttributes를 사용해도 Tiles로 나누어진 header.jsp나 aside.jsp에서는 세션유지가 안되는 문제 발생하여 시작! 3 | Tiles의 ViewPreparer를 사용하여 인증된 사용자의 Member 객체를 Model에 저장하여 4 | layout이 실행될 때 Preparer가 실행되도록 하여 모든 페이지에서 로그인정보 세션유지 가능 ! 5 | 6 | ## 1. Tiles Configurer 설정 7 | - Member 정보를 모든 페이지에서 유지하기 위해 8 | - `tilesConfigurer.setPreparerFactoryClass(SimpleSpringPreparerFactory.class);` 추가 9 | ~~~C 10 | @Configuration 11 | public class TilesConfig { 12 | 13 | @Bean 14 | public TilesConfigurer tilesConfigurer() { 15 | 16 | TilesConfigurer tilesConfigurer = new TilesConfigurer(); 17 | tilesConfigurer.setDefinitions(new String[] {"/WEB-INF/tiles.xml"}); 18 | tilesConfigurer.setCheckRefresh(true); 19 | //Preparer 추가 18/5/25 20 | tilesConfigurer.setPreparerFactoryClass(SimpleSpringPreparerFactory.class); 21 | return tilesConfigurer; 22 | } 23 | ~~~ 24 | ## 2. Tiles.xml에 `preparer="com.harusketch.util.MemberPreparer"` 추가 25 | ~~~C 26 | 27 | 28 | 29 | 30 | 31 | 32 | ~~~ 33 | 34 | ## 3. MemberPreparer 35 | ~~~C 36 | @Component 37 | public class MemberPreparer implements ViewPreparer { 38 | 39 | @Autowired 40 | private MemberDao memberDao; 41 | 42 | @Override 43 | public void execute(Request tilesRequest, AttributeContext attributeContext) 44 | throws PreparerException { 45 | 46 | // ********** 로그인 된 상태에서 만 실행되는 코드를 작성할 경우 ****************** 47 | // 현재 로그인 한 사용자의 인증객체를 얻는다. 48 | Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 49 | 50 | // 인증된 사용자의 Member 정보 얻는 방법 51 | if (!(auth instanceof AnonymousAuthenticationToken)) { 52 | 53 | // 인증객체를 통해서 인증에 사용된 id를 얻는다. 54 | final UserDetails userDetails = (UserDetails) auth.getPrincipal(); 55 | final String username = userDetails.getUsername(); 56 | 57 | // 이제 인증 id를 이용해서 Member 객체를 얻어온다. 58 | Member member = memberDao.get(username); 59 | 60 | // 위의 member 객체를 model 저장소에 담는다. 61 | Map model = tilesRequest.getContext("request"); 62 | model.put("member", member); 63 | } 64 | ~~~ 65 | 66 | ## 4. 해당하는 .jsp 페이지에 EL Member 정보 사용하기 67 | ` ${member.name} 님 안녕하세요 :)` 68 | 69 | # *Reference 70 | - https://tiles.apache.org/framework/tutorial/advanced/preparer.html 71 | - https://stackoverflow.com/questions/25358665/spring-4-tiles-3-2-2-2-any-way-to-access-beans-in-view-context 72 | - https://richardbarabe.wordpress.com/2009/02/19/apache-tiles-2-viewpreparer-example/ 73 | -------------------------------------------------------------------------------- /Tools/Eclipse.md: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | 3 | ## 1. git local 저장소에서 이클립스로 가져오기 4 | - Import - General - Projects from Folder or Archive 선택 5 | - 프로젝트 root 폴더를 지정. 6 | - egit을 사용하지 않을 것이면 import - git - existing local repository 로 가져오면 안됌 7 | 8 | 9 | ## 2. 이클립스 초기 설정 (for Cloud Cash Project) 10 | 11 | 1. 환경설정 - Server - runtime environments 에 Tomcat 8.5 추가 12 | 2. 프로젝트 properties - Java Build Path 에 Libraries 4개 필요 13 | - Apache Tomcat 8.5 14 | - JRE System Library [JavaSE- 1.8] 15 | - Maven Dependencies 16 | - Web App Libraries 17 | 3. Properties - Java Compiler 버전 1.8로 수정 18 | 4. Properties - Maven - Project Facets 버전 설정 19 | - Dynamic Web Module - 3.1 20 | - Java -1.8 21 | 5. Properties - Server - Tomcat 8.5 추가 22 | 6. Tomcat에 프로젝트 물리고, servers 탭에서 Tomcat - Modules의 Path를 23 | - Document base : cash cloud 24 | - Path : / 로 수정 25 | --------------------------------------------------------------------------------