StudyServer
web, server, java, spring 등.. 공부한 것을 기록하는 장소 입니다. 공부하면서 정리하였기 때문에 틀린 내용이 있을 수 있습니다. 이야기 해주시면 수정하겠습니다.

ArrayList, HashMap

2018-11-14 00:00:00 +0000

자료구조란?

데이터를 효율적으로 사용할 수 있도록 구조를 만들어서 저장해둔 것

자료구조 종류

  • 리스트 (ArrayList, LinkedList)
  • 스택 (LinkedList )
  • 큐 (LinkedList)
  • 해시 테이블 (HashMap)
  • 집합(HashSet, key와 value가 한 쌍)

ArrayList

  • 순서가 있는 자료구조
  • 배열의 길이가 제한이 없다
  • ArrayList list = new ArrayList();
  • ArrayList는 내부에 있는 배열에 데이터를 저장. 전체를 순회할 때 사용하면 좋다
  • ArrayList는 데이터 삭제하면 자동으로 정렬해준다. 하지만 수정, 삭제가 많으면 성능이 떨어진다
  • LinkedList는 인접한 데이터가 서로 메모리를 가르키는 식으로 저장. 수정, 삭제힐 떼 가르키는 주소만 바꾸면 되므로 성능이 좋다
  • 보통 web은 view에 list를 뿌려주는 일을 많이 한다=>ArrayList(수정,삭제는 db에서 많이 하므로)
import java.util.ArrayList;
public class ListEx {
     public static void main(String[] args) {
         ArrayList<String> list = new ArrayList<String>();
        list.add("one");                // 값 추가
        list.add("two");
        list.add(2,"three");            // 값 인덱스로 추가
        list.remove(2);                     // 값 삭제
        list.add(1,"four");
        
        int index = list.indexOf("one");               // 값으로  index 찾기
        System.out.println("index:"+index);
        
        int num = list.size();
        for(int cnt = 0; cnt < num; ++cnt){
             System.out.println(list.get(cnt));        // 값  index로 가져와서 출력하기
        }
     }
}

iterator

  • 자바의 컬렉션클래스 데이터를 읽어오는 방법 중 하나
  • 만약 iterator가 없다면 각 컬렉션 클래스의 값 얻어오는 함수를 알고 있어야 한다. 하지만 iterator를 사용하면 어떤 컬렉션 객체이든간에 iterator로 쉽게 값을 가져올 수 있다
public static void Show(ArrayList<Integer> list){
           Iterator<Integer> itr = list.iterator();
           while(itr.hasNext()){
                System.out.print(itr.next()+",");
           }
}

스택

  • 맨 마지막에 넣은 데이터를 먼저 꺼낸다
import java.util.LinkedList;
public class LinkedListEx {
     
     public static void main(String[] args) {
           LinkedList<Integer> stack = new LinkedList<Integer>();
           stack.addLast(1);
           stack.addLast(30);
           stack.addLast(33);
           
           while(!stack.isEmpty()){
                Integer num = stack.removeLast();
                System.out.print(num+","); // 출력결과는 33,30,1  최근 넣은 것 부터 출력
           }
     }
}

해쉬테이블

  • 데이터가 key, value로 쌍이 이루어진다
  • key를 연산을 거쳐 해시값으로 만든다. 예를들어 String 값 “111’을 넣는다면 연산을 통해 해시값이 된다. String을 검색하는 것보다 빠르게 찾을 수 있기 때문에 검색 선능이 향상된다
  • key 값은 중복 불가능하다
  • 멀티쓰레드에서 문제가 될 수 있으므로 HashTable을 쓴다

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashEx {
     public static void main(String[] args) {
           HashMap<Integer, String> map = new HashMap<Integer,  String>();
           map.put(1, "one");               // 값 넣기
           map.put(2, "two");
           map.put(3, "three");
           String str = map.get(1);   // 값 가져오기
           System.out.println(str);
           
           if(true == map.containsKey(1))   // 값 체크
                System.out.println("값 1은 있다");
           else
                System.out.println("값 1은 없다");
           
           // map은 iterator을 사용할 수 없으므로 map.keyset,  map.entryset을 사용한다
           System.out.println("=== entryset ===");
           Set set = map.entrySet();
           Iterator iter = set.iterator();
           while(iter.hasNext()){
                Map.Entry<Integer, String> mapTemp =  (Map.Entry<Integer, String>)iter.next();
                System.out.println("key:"+mapTemp.getKey()+"value:"+mapTemp.getValue());
           }
           
           // keyset
           System.out.println("=== keyset ===");
           Set<Integer> set2 = map.keySet();
           Iterator<Integer> iter2 = set2.iterator();
           while(iter2.hasNext()){
                int key2 = iter2.next();
                String str2 = map.get(key2);
                System.out.println("key:"+key2+" value:"+str2);
           }

         // map.values(); 를 사용해서 Collection으로 Iterator 하는 방법도 있다
         // Collections.max(values); // 가장 큰 값
         // Collections.min(values) // 가장 작은 값
     }
}

Regular(정규표현식)

2018-11-13 00:00:00 +0000

정규표현식

  • 특정한 규칙을 가진 문자열의 집합을 표현하는데 사용하는 표현식 언어이다 . : ‘.’가 위치한 곳에는 반드시 임의의 한글자가 위치하여야 한다는 의미
  • ‘*‘가 바로 앞의 문자가 없거나 하나 이상 반복한다는 의미
  • ’+’: ‘*‘과 흡사하지만 ‘+’는 반드시 하나 이상의 문자가 반복된다는 의미
  • ’?’: 바로 앞의 문자가 없거나 하나임을 의미
  • ’^’: 문장의 처음을 나타내며 ‘^’가 있는 단어로 문장이 시작됨을 의미
  • ’$’ : 문장의 끝을 나타내며, $가 있는 단어로 문장이 끝남을 의미
  • []괄호 안의 문자 중 일치하는 것을 검색할 경우 사용
    • [abc] : a, b, c, abc 등 문자열에 a, b, c등이 있어야 한다
    • [0-9] : 숫자가 포함된 모든 문자열
    • [a-z] : 알파벳 소문자가 포함된 모든 문자열(범위)
    • ^[a-zA-z0-0] : 영문대소문자 또는 숫자로 시작되는 모든 문자열 검색
  • [] 안에서의 ‘^’ 특수문자(부정)
    • [] 특수문자 안에 있는 문자를 포함하고 있지 않는 모든 문자열을 찾고자 할 경우
  • {} 특수문자 앞의 문자가 반복되는 횟수 의미, {n,m}이면 최소 n, 최대 m 만큼 반복, \d{1,2}는 숫자 1~2자리 숫자가 포함되어있는지, 8\d{1}는 8로 시작하는 2자리 숫자를 나타냄
  • () 안에 문자열을 하나의 문자로 취급, (x){n} 는 하위 항목이 됨 즉 x의 내용이 n번 반복되어야 한다
  • or 연산 수행
  • [a-zA-Z] 모든 영문자
  • 특수문자를 문자 그래도 사용하고 싶다면 특수 문자 앞에는 역슬레시를 써야 한다
  • w : [a-zA-Z0-0] 알파벳이나 숫자
  • W : [^a-zA-Z0-9] 알파벳이나 숫자를 제외한 문자
  • .+(?=:) : 전방탐색 기호 ?=, 다음에 오는 문자가 일치하는 영역에서 제외됨. 예를들어 .+(?=살) 이라면 17살, 18살은 17, 18만 찾음
  • ?<= : 뒤에 있는 문자를 탐색

자바 정규 표현식 처리

  • java.util.regex 패키지
  • Pattern 클래스

Source

import java.util.Scanner;
public class ReqularExam {
     public static void main(String[] args) {
           Scanner sc = new Scanner(System.in);
           System.out.println("문자열 입력:");
           String str = sc.nextLine();
           
           // abc문자 포함
           // . : 앞, 뒤로 데이터가 있다
           // * : 몇 개 반복될 지 모른다
           /*if(str.matches(".*abc.*")){     // 정규표현식 체크
                System.out.println("매칭");
           }else{
                System.out.println("비매칭");
           }*/
           
           /*// 숫자만 3자리 입력
           //[0-9] : 숫자만 입력
           //{} : 앞의 문자가 반복되는 횟수
           if(str.matches("[0-9]{3}")){
                System.out.println("매칭");
           }else{
                System.out.println("비매칭");
           }*/
           
           //
           // 알파벳, 숫자만 5자 이상 입력
           // [//w]{5,}
/*         if(str.matches("^[a-bA-Z0-9]*${6}")){
                System.out.println("매칭");
           }else{
                System.out.println("비매칭");
           }
*/         
           // 한글만 3자리에서 5자리
           if(str.matches("[가-힣]{3,5}"))
                System.out.println("매칭");
           else
                System.out.println("매칭");
     }
}

Enum Class

2018-11-13 00:00:00 +0000

enum class 사용하기

  • enum은 관련있는 상수의 모음
  • 필드와 메소드 추가가 가능하다
  • final 로써 사용한다
  • class 처럼 함수선언, 오버라이드가 가능하다
  • 숫자 뿐 아니라 실제 Type 비교 가능

그 외 enum 정리

  • enum 첫번째 요소는 0이고 순서대로 번호가 부여된다
  • enum이름.요소이름.ordinal() 함수를 사용해서 번호를 확인할 수 있다

Source

public class Main {
     enum SHAPE{
           CICLE{
                @Override
                public void draw() {
                      System.out.println("Cicle draw");
                }
                @Override
                public void getName() {    
                     System.out.println(this.getClass().getSimpleName());
                }
                
           },
           RECTANGLE{
                @Override
                public void draw() {
                      System.out.println("Rectangle draw");
                }
                @Override
                public void getName() {    
                     System.out.println(this.getClass().getSimpleName());
                }
                
           },
           TRIANGLE{
                @Override
                public void draw() {
                      System.out.println("triangle draw");                 
                }
                @Override
                public void getName() {
                     System.out.println(this.getClass().getSimpleName());
                }
                
           };
           
           public abstract void draw();
           public abstract void getName();
     }
     
     public static void main(String[] args) {
           
           SHAPE shape = SHAPE.CICLE;
           shape.draw();
           shape = SHAPE.RECTANGLE;
           shape.draw();
           shape = SHAPE.TRIANGLE;
           shape.draw();
     }
}

결과

Cicle draw
Rectangle draw
Triangle draw

String Function

2018-11-12 00:00:00 +0000

String 생성

  • 문자열이 등록되었다면 참조, 등록 안 되었다면 새로 생성
String str = "ABC"
  • 무조건 새로 생성
String str = new String("ABC");

String 불변성

  • 문자열은 불변하기 때문에 문자열 변경 시 새로운 문자열을 다시 생성함=>비효율적
  • 문자열 붙이기
String str3 = str.concat("DEF");
  • 또 다른 문자열 붙이기
String sql = "select*from board";
int0 num = 10;
if(num == 10){
    sql +="where num = 10";
}
  • StringBuffer, StringBuilder 가변성
StringBuffer sb = new StringBuffer("가나다");
sb.append("라마바");
System.out.println(sb);
  • 해당 문자열 위치 파악 IndexOf=>0시작, 없으면 -1
 System.out.println(sql.indexOf("*"));
  • 문자열 길이 length()
System.out.println(sql.length());
  • 문자열 부분 추출
System.out.println(sql.substring(0, 12));
  • .을 기준으로 kosta, jpg를 나누는 예제
String fileName = "kosta.jpg";
String head = ""; // kosta
String pattern = ""; // jpg
int spotIndex = fileName.indexOf(".");
head = fileName.substring(0, spotIndex);
pattern = fileName.substring(spotIndex+1);
System.out.println("head:"+head);
System.out.println("pattern:"+pattern);
  • 공백 제거 trim
  • 같은 글자인지 체크 equals
String id = "kosta";
String m_id = "kosta ";    // 띄어쓰기가 있는 경우  trim함수로 공백제거를 할 수 있다
           
if(id.trim().equals(m_id.trim())){
    System.out.println("같다");
}else{
    System.out.println("다르다");               
}
  • 문자열=>배열변환
  • 콤마로 나누고 싶다
String fruits = "사과,배,포도,수박";
String arr[] = fruits.split(",");
           
for(String name : arr)
System.out.println(name);
  • 정수형에서 문자열로 변환
int n = 100;                          
String s = new String("100");    // 너무 길다
int n2 = 100;
String s2 = n+"";                     // 간단
  • 문자 끝의 글자를 알아낼 때 endsWith
String[] arrString = {"abcd.jpg", "abb.gif", "iiii.jpg",  "kkkk.gif", "pppp.ini"};
for(String fileName1:arrString){
if(true == fileName1.endsWith("jpg")){
    System.out.println("jpg 파일 입니다");
}else if(true == fileName1.endsWith("gif")){
     System.out.println("gif 파일 입니다");
}else{
    System.out.println("그 외 파일 입니다");
    }
}
  • 문자열 치환 replace(찾을문자열, 바꿀문자열)
String str = "가,나,다,라,마";
String result = str.replace(",", " ");
System.out.println("result:"+result);
  • 그 외 getBytes ( 네트워크로 전달할 때 바이트로 변환),toCharArray()(Char형으로 변환) 등의 String 함수가 있다

refactoring 이란(상수,제어플래그,assert)

2018-11-12 00:00:00 +0000

리팩토링(refactoring) 이란?

  • 외부에서 보는 프로그램 동작은 바꾸지 않고 프로그램의 내부 구조를 개선하는 것

동작이 변하지 않은 걸 확인하는 테스트

  • unit 테스트 반드시 필요
  • 리팩토링 전에 테스트->리팩토링->리팩토링 후 다시 테스트
  • 입문자라면 junit 테스트 프레임워크 사용해볼 것

리팩토링이 필요한 코드들

  • 같은 코드 중복, 사양 변경이 있을 때 수정 내용이 곳곳에 흩어져 있다, 언제나 다른 클래스 내용을 수정하는 클래스가 있다
  • 합쳐서 다뤄야 할 데이터가 한 클래스에 모여있지 않다, 메서드 호출 연쇄가 너무 많다 등..

리팩토리 방법

  • 한번에 하나의 수정만 한다(ex 함수 옮기기, 함수 이름바꾸기가 있다면 함수 옮기기->테스트->이름바꾸기->테스트 한번에 하나만 수정하고 따로 테스트 해야한다)
  • 되돌리게 쉽게 하기: 코드가 섞여 있으면 되돌리기 어렵다
  • 단계마다 확인: 새로운 클래스 생성 후 빌드 테스트, 빌드 성공 후 새로운 클래스를 사용하면서 버그 테스트
  • 오래된걸 바꿈: 동작하는 상태를 유지하면서 새로운 코드를 추가하고 잘 동작하면 오래된 것을 제거한다

리팩토링 상황

  1. 상수인 숫자가 있다면 기호 상수로 바꾸어라(100 -> MAX_COUNT)
    • 상수의 의미를 파악하기 어렵고, 상수가 바뀐다면 관련 상수가 맞는지 확인하면서 일일이 바꿔줘야 한다
    • JAVA에서 상수를 만드는 방법은 static final 클래스 필드 사용, enum 사용이 있다
    • static final 을 사용할 수 있지만 상수 대신 숫자 0을 적어도 문제 없이 작동한다
    • 인자를 int에서 클래스로 치환하거나 enum을 사용해서 잘못된 사용을 막을 수 있다 수정 전
if(command == 0) {
        System.out.println(name+"works");
}else if(command == 1){
        System.out.println(name+"stops");
}

수정 후

if(command == Command.WALK) {
    System.out.println(name+"works");
}else if(command == Command.STOP){
    System.out.println(name+"stops");
}
  • 기호 상수가 적합하지 않은 경우 배열에는 length라는 필드가 있다
for(int i = 0; i < ARR_COUNT; ++i){
}
  1. 제어 플래그 삭제
    • 처리 흐름을 제어하는 플래그를 지나치게 사용하면 가독성이 떨어진다
    • 아래 예제에서 flag가 정확히 어떤의미인지 불분명하므로 found로 변수명을 수정한다
    • 복잡한 이중 체크 대신 찾은 시점에서 바로 break를 시킵니다
    • 찾은 시점에서 바로 return 합니다. 그러면 found 변수가 필요없다는 걸 알 수 있습니다 FindInt.java
public class FindInt {
       public static boolean find(int[] data, int target) {
              boolean flag = false;
              for(int i = 0;  i < data.length && !flag; ++i) {
                     if(data[i] == target) {
                           flag = true;
                     }
              }
              
              return flag;
       }
       
}

Main.java
public class Main {
       
       public static void main(String[] args) {
              int[] data = {
                     1, 9, 0, 2, 8, 5, 6, 3, 4, 7,
              };
              
              if(FindInt.find(data, 5)) {
                     System.out.println("Found!");
              }else {              
                     System.out.println("Not found!...");
              }
       }
}

변경 후 FindInt.java

public class FindInt {
       public static boolean find(int[] data, int target) {
              for(int i = 0;  i < data.length; ++i) {
                     if(data[i] == target)
                           return true;
              }
              return false;
       }
}
  1. assert 도입
    • 주석으로 이 상황에 알맞은 값을 적어도 프로그램 실행 시 다른 값이 올 경우 처리 방법이 없다
    • assert 도입 시 잘못된 값이 들어올 경우 에러를 발생시킨다
    • assert 도입으로 인해 변경되는 내용이 없어야 한다
    • 이클립스에서 assert를 사용하려면 메뉴 Run-Run Configurations-Argments의 VM arguments에서 -ea를 추가한다
    • 아래 소스코드 주석에서 체크하는 함수를 만든 뒤 원하는 결과인지 assert로 체크한다

SortSample.java

public class SortSample {
       private final int[] data;
       
       public SortSample(int[] data) {
              this.data = new int[data.length];
              System.arraycopy(data, 0, this.data, 0, data.length);
       }
       
       public void sort() {
              for(int x = 0; x < this.data.length - 1; ++x) {
                     int m = x;
                     for(int y = x+1; y < data.length; ++y) {
                           if(this.data[m] > this.data[y]) {
                                  m = y;
                           }
                     }
                     
                     // 여기서 data[m]은 data[x]~data[data.length - 1]의  최솟값이어야 함
                     int v = data[m];
                     data[m] = data[x];
                     data[x] = v;
                     // 여기서 datat[0]~data[x+1]은 이미 정렬되어 있어야 함
              }
       }
       
       public String toString() {
              StringBuilder buffer = new StringBuilder();
              buffer.append("[ ");
              for(int i = 0; i < data.length; ++i) {
                     buffer.append(data[i]);
                     buffer.append(", ");
              }
              buffer.append("]");
              return buffer.toString();
       }
}

Main.java

import java.util.Random;
public class Main {
       private static final Random random = new Random(1234);
       
       private static void execute(int length) {
              // 난수로 데이터 작성
              int[] data = new int[length];
              for(int i = 0; i < data.length; ++i) {
                     data[i] = random.nextInt(data.length);
              }
                     
              // 데이터 표시
              SortSample sorter = new SortSample(data);
              System.out.println("BEFORE:"+sorter);
              
              // 정렬해서 표시
              sorter.sort();
              System.out.println("AFTER:"+sorter);
              
              System.out.println();
       }
       
       public static void main(String[] args) {
              execute(10);
              execute(10);
              execute(10);
              execute(10);
              execute(10);         
       }
}

Posts

subscribe via RSS