• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java 정리 18

06 Dec 2018

Reading time ~9 minutes

Java 정리 18 - Calendar, DecimalFormat, Random, JCF


Calendar

  • 한가지 날짜정보를 얻을 땐 Calendar가 좋고 형식있는 전체를 얻을 땐 SimpleDateFormat이 좋음.
  • Calendar는 생성된 시점의 날짜 정보를 갖고 있다.
    • 다른날의 날짜를 얻기 위해선 set을 사용
import java.util.Calendar;
import java.util.GregorianCalendar;
public class UseCalendar {
  public UseCalendar() {
    Calendar cal = Calendar.getInstance();
    Calendar cal1 = new GregorianCalendar();
    GregorianCalendar gc = new GregorianCalendar();
    
    int year = cal.get(Calendar.YEAR);
    // 월, java에서는 월의 시작이 0월
    int month = cal.get(Calendar.MONTH)+1;
    int day = cal.get(Calendar.DAY_OF_MONTH);
    
    // 올해 몇번째 날인지
    int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);
    
    System.out.printf("%d-%d-%d 오늘은 올해의 %d번째  날\n",
              year,month,day,dayOfYear);
    // 요일 : 일(1), 월(2), 화(3), 수(4), 목(5), 금(6),  토(7)
    int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
    
    /*switch(dayOfWeek) { // case 1~7, 가독성이 낮다
    case 1:    System.out.println("일요일");   break;
    case 2:    System.out.println("월요일");   break;
    case 3:    System.out.println("화요일");   break;
    case 4:    System.out.println("수요일");   break;
    case 5:    System.out.println("목요일");   break;
    case 6:    System.out.println("금요일");   break;
    case 7:    System.out.println("토요일");   break;
    }*/
  
    /*String week="";
    // 상수 사용하여 가독성 향상
    switch(dayOfWeek) {
    case Calendar.SUNDAY:
        week="일요일";  break;
    case Calendar.MONDAY:
        week="월요일";  break;
    case Calendar.TUESDAY:
        week="화요일";  break;
    case Calendar.WEDNESDAY:
        week="수요일";  break;
    case Calendar.THURSDAY:
        week="목요일";  break;
    case Calendar.FRIDAY:
        week="금요일";  break;
    case Calendar.SATURDAY:
        week="토요일";  break;
    }
    System.out.printf("%d요일 %s\n",dayOfWeek, week);*/
    
    // 배열 활용하는 방식(권장)
    String[] weekTitle = {  "일","월","화","수","목","금","토" };
    System.out.printf("%d요일 %s요일\n",dayOfWeek,
              weekTitle[dayOfWeek-1]);
  
    // 오전(0) 오후(1)
    int amPm = cal.get(Calendar.AM_PM);
      
    // 상수 Calendar.AM, Calendar.PM을 이렇게 사용
    /*switch(amPm) {
    case Calendar.AM:
        System.out.println("오전");
        break;
    case Calendar.PM:
        System.out.println("오후");
        break;
    }*/
      
    // 배열로
    String[] arrAmPm = { "오전", "오후" };
    System.out.printf("%d %s\n",amPm, arrAmPm[amPm]);

    // 삼항연산자로
    System.out.printf("%s\n", amPm == Calendar.AM ?  "오전" : "오후");
      
    // 시간
    int hour = cal.get(Calendar.HOUR);   // 12시간제
    int hour24 = cal.get(Calendar.HOUR_OF_DAY); //  24시간제
    System.out.printf("%d(%d)시\n", hour, hour24);
      
    int minute = cal.get(Calendar.MINUTE);
    int second = cal.get(Calendar.SECOND);
    System.out.printf("%d(%d):%d:%d\n",hour,hour24,minute,second);
      
      // Calendar는 생성된 시점의 날짜 정보를 가짐
      // 다른 날짜를 얻기 위해선 set을 사용
    System.out.println("-----------------------------------------------");
    System.out.printf("설정 전 %d-%d-%d %s요일\n",
        cal1.get(Calendar.YEAR),  cal1.get(Calendar.MONTH)+1,
        cal1.get(Calendar.DAY_OF_MONTH),
        "일,월,화,수,목,금,토".split(",")[cal1.get(Calendar.DAY_OF_WEEK)-1]);
      
    // 년
    cal1.set(Calendar.YEAR, 2019);
    // 월 - 사람이 생각하는 월보다 1적게 설정
    cal1.set(Calendar.MONTH, 4);
    // 일 - 해당월의 존재하지 않는 일자가 설정되면  자동으로 다음달로 넘어가 설정됨
    cal1.set(Calendar.DAY_OF_MONTH, 32);
    
    System.out.printf("설정 후 %d-%d-%d %s요일\n",
      cal1.get(Calendar.YEAR),  cal1.get(Calendar.MONTH)+1,
      cal1.get(Calendar.DAY_OF_MONTH),
      "일,월,화,수,목,금,토".split(",")[cal1.get(Calendar.DAY_OF_WEEK)-1]);
    System.out.println("-----------------------------------------------");
      
    // 이번달의 마지막 날을 알 수 있는 getActualMaximum
    System.out.println(cal1.getActualMaximum(Calendar.DATE));
    System.out.println(cal1.getActualMaximum(Calendar.DAY_OF_MONTH));
  }
  
  public static void main(String[] args) {
    new UseCalendar();
  }
}

DecimalFormat

  • 숫자 형식을 변경(1000(정수) -> 1,000(문자열))
  • java.text 패키지에 존재
  • 패턴
    • 오라클 0 - 자바 0
      • 0으로 채우기
    • 오라클 9 - 자바 #
      • 존재하는 숫자만 출력
  • 오라클보다 자바 format해주는게 좋은점은 오라클은 입력값이 패턴길이를 넘어가면 출력을 못하는 반면 자바는 입력값이 넘어가도 패턴을 적용시켜줌
// 1.생성
DecimalFormat df = new DecimalFormat("패턴");

// 2.사용
df.format(패턴을적용할숫자);
public class UseDecimalFormat {
  
  public UseDecimalFormat() {
    int temp = 20181206;
    
    // 데이터가 없음 0을 채움
    DecimalFormat df = new  DecimalFormat("0,000,000,000");
    // 데이터가 없으면 채우지 않음
    DecimalFormat df1 = new  DecimalFormat("#,###,###,###");
    
    System.out.println("0사용 : "+df.format(temp)); // 0,020,181,206
    System.out.println("#사용 : "+df1.format(temp)); // 20,181,206
    
    DecimalFormat df2 = new DecimalFormat("#,###.00");
    // 실수자릿수를 사용하면 마지막 뒷자리의 값이
    // 반올림대상이라면 반올림한 결과를 보여준다.
    System.out.println("소수자리수 표현 :  "
      +df2.format(201812.066)); // 201,812.07
  }
  
  public static void main(String[] args) {
    new UseDecimalFormat();
  }
}

Random

  • java.util 패키지
  • 다양한 난수를 뽑기 위해서 제작된 클래스
  • 생성되면 모든 난수가 발생
    • 패턴을 분석하면 다음 수 예측가능(보안에 취약)
// 1.생성
Random r = new Random();

// 2.난수얻기
r.nextDouble(); // 실수난수(0~1 사이 실수)
// 실수난수로 발생가짓수 내 정수난수를 얻을 때
(int)(r.nextDouble()*발생가짓수); 

r.nextInt(); // 정수난수 (-2147483648~+2147483647 사이 랜덤값)

// 발생가짓수 안에 랜덤한 값을 얻고자 할 때 아래와 같이하면
// 음수도 나올 수 있다. 따라서 Math.abs()를 사용
r.nextInt()%발생가짓수;
Math.random(r.nextInt()%발생가짓수);

// 오버로딩된 nextInt를 사용하면 발생가짓수-1의 
// 임의의 양의 정수가 반환된다(권장)
r.nextInt(발생가짓수);

// 랜덤 Boolean값도 가질 수 있다.
r.nextBoolean();
public class UseRandom {
  public UseRandom() {
    // 1.생성
    Random r = new Random();
    
    // 2.난수얻기
    // 실수난수
    double d = r.nextDouble();
    System.out.println(d);
    System.out.println(d*5);
    System.out.println((int)(d*5));
    
    System.out.println("-----------------------");
    
    // 정수난수
    int i = r.nextInt(); // 음수가 발생하므로  절대값처리
    System.out.println(i);
    System.out.println(i%5);
    System.out.println(Math.abs(i%5)); // 양수처리
    
    System.out.println("-----------------------");
    int j = r.nextInt(5); // 음수가 발생하지 않는다.
    System.out.println(j);
    
    System.out.println("-----------------------");
    
    // 불린난수
    boolean b = r.nextBoolean();
    System.out.println(b);
  }
  public static void main(String[] args) {
    new UseRandom();
  }
}

오토박싱 & 언박싱(autoboxing & unboxing)

  • jdk 1.5 이전에는 기본형과 참조형 간 연산 불가능했었음
    • 래퍼 클래스로 기본형을 객체로 만들어 연산해야 했다.
  • jdk 1.5부터는 컴파일러가 자동으로 변환하는 코드를 넣어줌.
    • 기본형 값을 래퍼 클래스의 객체로 자동변환해주는 것을 오토박싱(autoboxing), 반대로 변환하는 것을 언박싱(unboxing)이라 함

JCF(Java Collection FrameWork)

  • 데이터를 다룰 때 사용(=자료구조)
  • java.util 패키지에서 제공
  • Collection 계열, Map
    • Collection 계열 = List, Set
  • 가변길이형
    • 데이터를 추가하면 크기가 늘어나고 삭제하면 크기가 줄어듦.
    • 메모리를 효율적으로 사용
  • Generic과 같이 사용
    • Generic은 jdk 1.5에서 추가된 기능
    • jdk 1.4까지는 Object만 저장 가능했지만 jdk 1.5부터는 모든 값을 저장할 수 있다. (autoboxing, unboxing 지원)

01

  • Collection
    • List
      • 1차원 배열처럼 생성, 사용
      • 가변길이형
      • 중복값 저장가능, 검색 기능이 있다
      • 데이터가 순차적으로 입력됨
      • List 인터페이스를 구현한 클래스 존재
        • ArrayList, LinkedList, Vector
    • Set
      • 1차원 배열처럼 생성, 사용
      • 가변길이형
      • 중복값 저장불가, 검색 기능이 없다
        • 검색 기능이 없어 Iterator(포인터 객체)를 사용
      • 데이터가 순차적으로 입력되지 않음
      • Set 인터페이스를 구현한 클래스 존재
        • HashSet
  • Map
    • 2차원 배열처럼 생성
    • 가변길이형
    • 키와 값의 쌍(entry)으로 이루어진 데이터형
      • 2차원 배열이지만 열은 2개
    • 키는 중복될 수 없음, 값은 중복가능
    • 데이터(<K,V>, entry)가 순차적으로 입력되지 않음
      • Map 인터페이스를 구현한 클래스 존재
        • Hashtable, HashMap

Generic (<>)

  • jdk 1.5부터 추가된 기능
  • JCF에서 입력데이터형의 제한을 설정할 때 사용
    • 단일 데이터형으로 구성
  • Generic은 기본 데이터형으로는 설정할 수 없다
    • 랩퍼클래스(wrapper class)로만 사용가능
      • 기본형 데이터형을 객체로 생성하여 사용하는 클래스
      • 값에 대해서 method를 호출하여 일을 더 할 수 있음
  • jdk 1.7부터는 객체 생성하는 쪽에 Generic은 데이터형을 생략가능
List arrList = new ArrayList();

// 어떤 타입(기본형, 참조형)이든 담을 수 있다.
arrList.add(12);
arrList.add(12.32);
arrList.add('A');
arrList.add("문자열");
arrList.add(new Date());

// 일괄처리가능
for(int i=0; i<arrList.size(); i++) {
  // 사용할 때 문제가 발생가능 => Generic 등장 배경
  System.out.print(arrList.get(i)*10); //error!
}

// JCF클래스명<데이터형> 으로 Generic 사용
// E - 해당 리스트에 저장할 elements 타입
List<E> l = new ArrayList<>();
// Generic으론 참조형 데이터형만 들어올 수 있다
// wrapper class를 이용하면 기본형데이터형을 담을 수 있음
List<Integer> l = new ArrayList<>();

// autoboxing (int -> Integer)
// wrapper class로 생성 안해도 자동으로 참조형객체로 바꿔주는게 autoboxing
// jdk 1.5이전 : l.add(new Integer(10)) 
// jdk 1.5+ : l.add(10); 
l.add(10); 

// unboxing (Integer -> int)
// wrapper class의 값을 기본형데이터형 값으로 바꿔주는게 unboxing
// jdk 1.5이전 :((Integer)l.get(0)).intValue()*10 
// jdk 1.5+ : l.get(0)*10 으로 처리가능(generic을 썼기 때문에 형변환 불필요)
System.out.println(l.get(0)*10); 

List

  • 상속 때문에 부모만 쓸 줄 알면 어떤 자식이든 사용이 가능해진다.
    • ArrayList 사용법만 알고도 Vector, LinkedList 모두 사용이 가능해짐
      • 습득의 시간이 짧아진다.
// 1.생성
// 객체다형성
// List 공통 특징 - 데이터가 순차적으로 추가됨
// ArrayList - Multi Thread에서 동시접근 가능(StringBuilder), 동기화 안됨
List l = new ArrayList();

// Vector - Multi Thread에서 동시접근 불가능(StringBuffer), 동기화 됨 
List l1 = new Vector();

// LinkedList - 데이터가 기존 데이터 사이에 추가되는 일이 많을 때 사용
List l2 = new LinkedList();

// 2.추가 add : 방의 개수가 증가
l.add(값); // 속도가 가장 빠름(권장)
l.add(인덱스, 값); // 원하는 인덱스에 추가(속도 느림)

// 3.방의 개수 size (size !=여유공간(capacity))
l.size();

// 4.방의 값얻기 get
l.get(인덱스);

// 5.모든 방의 값
for(int i=0; i<l.size(); i++) {
     System.out.println(l.get(i));
}

// 6.삭제 remove : 방의 개수가 감소
l.remove(인덱스);
l.remove(값);

// 7.모든 방의 값 삭제 clear
l.clear();

// 8.리스트의 값을 배열로 복사 toArray (Generic이 된 경우만 복사가능)
List<String> strList = new ArrayList<String>();

strList.add("오");
strList.add("영");
strList.add("근");

String[] strArr = new String[strList.size()];
strList.toArray(strArr);
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;
import java.util.LinkedList;

/**
* List<br>
* 중복값 허용하며 검색의 기능이 있고, 순서대로 값을 입력하는 가변길이형
*/
public class UseList {
    
  public UseList() {
    // jdk 1.4에서는 Generic이 제공되지 않고 객체만 저장됨
    List list = new ArrayList();
    // 값 추가
    // jdk 1.5이하에서는 객체로만 값을 넣을 수 있음
    list.add(new Integer(10));
    list.add(new Short((short)10));
    list.add(new String("공선의"));
    
    System.out.println("크기 "+list.size());
    System.out.println(((Integer)list.get(0)).intValue()+10);
    
    // jdk 1.5+ 사용 : Generic, autoboxing, unboxing 사용가능
    // Generic을 권장
    List<Integer> list1 = new ArrayList<Integer>();
    list1.add(10); // autoboxing
    list1.add(20);
    list1.add(new Integer(30));
    // Generic으로 설정된 형이 아닌 데이터형은 추가할 수 없다.
    // list1.add("김건하");
    
    System.out.println("크기 "+list1.size());
    for(int i=0; i<list1.size(); i++) {
      System.out.print(list1.get(i)+" ");
    }
    System.out.println();
  }
  
  // ArrayList 사용 : Multi Thread환경에서 동시 접근 가능(동기화 X)
  public void useArrayList() {
      // 1. 생성
      ArrayList<String> al = new ArrayList<String>(); // capacity X(방 0개)
      List<String> al1 = new ArrayList<String>(100); // capacity O(방 100개)
      
      System.out.println(al+" / "+al1);
      
      // 값 추가
      // 값은 순서대로 추가됨, 중복값 허용
      al.add("이재현"); al.add("이재현"); al.add("김정윤"); al.add("노진경");
      al.add("김정윤"); al.add("김정운");    al.add("공선의"); al.add("정택성");
      System.out.println(al+" / "+al1);

      // size() : 데이터의 크기(size != capacity )
      System.out.println("al 크기 : "+al.size()+" / al1 크기 : "+al1.size());
      
      // 배열에 복사
      String[] names = new String[al.size()];
      al.toArray(names);
      
      // 복사된 배열 출력
      System.out.println("---------- 복사된 배열 출력 ----------");
      for(int i=0; i<names.length; i++) {
          System.out.printf("%s\t",names[i]);
      }
      System.out.println();
      System.out.println("--------------------------------------");
      
      // 방의 값 삭제
      // -인덱스로 삭제
      al.remove(5);
      System.out.println(al+" / "+al1);
      // -값으로 삭제
      // 중복된 값이 존재 시 L->R로 진행하면서
      // 일치하는 첫방의 값만 삭제
      al.remove("김정윤");
      System.out.println(al+" / "+al1);

      // 향상된 for문 출력
      for(String name : al) {
          System.out.print(name+" ");
      }
      System.out.println();
      
      // 모두 삭제
      al.clear();
      System.out.println("전체 삭제 후 size : "+al.size()+" / "+al);
  }
  
  // Vector, LinkedList는 같은 List를 구현했기 때문에 사용법 동일
  public void useVector() {
      // 1. 생성
      Vector<String> vec = new Vector<String>(); // capacity X(방 0개)
      List<String> vec1 = new Vector<String>(100); // capacity O(방 100개)
      
      System.out.println(vec+" / "+vec1);
      
      // 값 추가
      // 값은 순서대로 추가됨, 중복값 허용
      vec.add("이재현"); vec.add("이재현"); vec.add("김정윤"); vec.add("노진경");
      vec.add("김정윤"); vec.add("김정운");    vec.add("공선의"); vec.add("정택성");
      System.out.println(vec+" / "+vec1);

      // size() : 데이터의 크기(size != capacity )
      System.out.println("vec 크기 : "+vec.size()+" / vec1 크기 : "+vec1.size());
      
      // 배열에 복사
      String[] names = new String[vec.size()];
      vec.toArray(names);
      
      // 복사된 배열 출력
      System.out.println("---------- 복사된 배열 출력 ----------");
      for(int i=0; i<names.length; i++) {
          System.out.printf("%s\t",names[i]);
      }
      System.out.println();
      System.out.println("--------------------------------------");
      
      // 방의 값 삭제
      // -인덱스로 삭제
      vec.remove(5);
      System.out.println(vec+" / "+vec1);
      // -값으로 삭제
      // 중복된 값이 존재 시 L->R로 진행하면서
      // 일치하는 첫방의 값만 삭제
      vec.remove("김정윤");
      System.out.println(vec+" / "+vec1);

      // 향상된 for문 출력
      for(String name : vec) {
          System.out.print(name+" ");
      }
      System.out.println();
      
      // 모두 삭제
      vec.clear();
      System.out.println("전체 삭제 후 size : "+vec.size()+" / "+vec);
  }
  
  public void useLinkedList() {
      // 1. 생성    
      LinkedList<String> ll = new LinkedList<String>();
      // LinkedList는 크기를 초기화 안함
      List<String> ll1 = new LinkedList<String>();
      
      System.out.println(ll+" / "+ll1);
      
      // 값 추가
      // 값은 순서대로 추가됨, 중복값 허용
      ll.add("이재현"); ll.add("이재현"); ll.add("김정윤"); ll.add("노진경");
      ll.add("김정윤"); ll.add("김정운");    ll.add("공선의"); ll.add("정택성");
      System.out.println(ll+" / "+ll1);

      // size() : 데이터의 크기(size != capacity )
      System.out.println("ll 크기 : "+ll.size()+" / ll1 크기 : "+ll1.size());
      
      // 배열에 복사
      String[] names = new String[ll.size()];
      ll.toArray(names);
      
      // 복사된 배열 출력
      System.out.println("---------- 복사된 배열 출력 ----------");
      for(int i=0; i<names.length; i++) {
          System.out.printf("%s\t",names[i]);
      }
      System.out.println();
      System.out.println("--------------------------------------");
      
      // 방의 값 삭제
      // -인덱스로 삭제
      ll.remove(5);
      System.out.println(ll+" / "+ll1);
      // -값으로 삭제
      // 중복된 값이 존재 시 L->R로 진행하면서
      // 일치하는 첫방의 값만 삭제
      ll.remove("김정윤");
      System.out.println(ll+" / "+ll1);

      // 향상된 for문 출력
      for(String name : ll) {
          System.out.print(name+" ");
      }
      System.out.println();
      
      // 모두 삭제
      ll.clear();
      System.out.println("전체 삭제 후 size : "+ll.size()+" / "+ll);
  }
  
  public static void main(String[] args) {
      UseList ul = new UseList();
      
      System.out.println("************************ArrayList*************************");
      ul.useArrayList();
      System.out.println("************************Vector****************************");
      ul.useVector();
      System.out.println("************************LinkedList************************");
      ul.useLinkedList();
  }
}

Stack

  • LIFO를 구현한 클래스
    • Last In First Out : 마지막으로 입력된 데이터가 마지막으로 나오는 자료구조.
  • Vector의 자식클래스
    • FIFO(First In First Out)
      • 배열, List
  • 부모의 기능을 사용하지 않는다.
    • 사용하면 Stack이 아니게 된다(LIFO 특징을 잃게됨)
    • is-a 관계의 객체화를 하지 않는다.
  • 상태를 저장할 때 (history기능) stack을 사용한다.
    • ctrl+z UNDO가 stack을 활용한 예
// stack 생성(is-a관계 객체화 안됨)
Stack<String> stk = new Stack<String>();

// 값넣기 push) 하나하나의 값을 item이라 함
stk.push("정택성");
stk.push("이재현");
stk.push("김정운");
stk.push("김정윤");

// stack의 크기보다 많은 데이터를 넣으면 StackOverflow 예외가 발생
// Vector클래스의 size()로 크기를 알 수 있다.
// 값 얻기) 얻은 값은 stack에서 꺼내지기 때문에 두번 사용할 수 없다.
stk.pop();

// peek()을 사용하면 재사용 가능(삭제 안하고 가장 위에 값 얻어옴)
stk.peek();

// 비었는지 확인해서 boolean 반환
stk.empty();

// stack의 모든 item 꺼내기
while(!stk.empty()) {
    System.out.println(stk.pop());
}

숙제풀이 ScoreProcessor 숙제풀이 RunProcessor



Java