• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

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

Java 정리 17

05 Dec 2018

Reading time ~8 minutes

Java 정리 17 - StringBuffer, StringBuilder, StringTokenizer, Math, Date, Calendar


문자열 다루기

  • String
    • 문자열 저장소의 주소를 참조, 같은 문자열이 없도록 하나만 생성된다.
    • method를 호출하여 일을 하면 원본 문자열이 변경되지 않는다.
  • StringBuffer
    • multi thread 환경에서 동시접근이 불가능
  • StringBuilder
    • jdk 1.5에서 추가된 클래스
    • StringBuffer와 사용법은 동일
    • String-StringBuffer-StringBuilder 순으로 빠르다.
    • 객체의 문자열을 바로 저장, 같은 문자열이 생성된다.
      • StringBuffer도 동일
    • method 호출하여 일을 하면 문자열이 변경된다.
    • multi thread 환경에서 동시접근이 가능
    • 문자열 +연산시 Compiler가 jdk1.5 이하면 StringBuffer로 처리하고 jdk 1.5이상이면 StringBuilder로 처리한다.

StringBuffer, StringBuilder

  • 문자열을 heap에 저장
    • 같은 문자열을 여러개를 저장하게 됨
    • 메소드를 불러서 일을하면 원본문자열이 변경이 됨
  • 둘 중 하나만 사용가능하면 다 쓸 수 있게됨 (사용법 동일)
  • 차이점
    • StringBuffer - 멀티쓰레드 동시접근 불가능
    • StringBuilder - 멀티쓰레드 동시접근가능
      • 속도때문에 Builder 많이 사용한다.
// 생성
StringBuffer sb = new StringBuffer();

// 값 덧붙임(오버로드로 많이 구현되어 있음)
// 정수, 실수, 문자, 문자열, boolean들을 문자열로 추가 가능
// 추가한 값을 저장한 문자열의 주소를 반환
sb.append(값);

// append 반환형이 StringBuffer이므로 메소드체인 가능
sb.append("Hello ").append("World!");

// 문자열로 반환할 때
String s = sb.toString();

// 값을 삽입, 0번 인덱스에 값 삽입
sb.insert(인덱스, 값);

// 문자열의 순서를 뒤집을 수 있음
sb.reverse();

// 값 삭제
sb.delete(시작인덱스, 끝인덱스+1);

// String과 동일한 기능의 메소드들이 많다
sb.indexOf("12");
sb.lastIndexOf("5");
sb.charAt(23);
sb.substring(sb.indexOf("안녕"));
  • String은 짧은 문자열 다룰 때 StringBuilder와 StringBuffer는 긴 문자열을 다룰 때 사용
    • 짧은 문자열은 글자수 상관없이 “로 시작, “로 끝나는 문자열
    • 긴 문자열은 “안”+”녕”과 같이 추가적인 연산이 들어가는 문자열
      • String은 ‘+’사용하지 않는다.(StringBuilder 사용!)
String str1 = "안";
// 문자열에 '+'가 붙어서 긴 문자열이 된다.
System.out.println(str1+"녕"+"하"+"세"+"요"+".");
// new  StringBuilder().append(str1).append("녕").append("하")...;

// decompiler로 바이트코드를 보면 자바는 긴문자열을 StringBuilder로 처리

01


StringTokenizer

  • java.util 패키지에서 제공
  • 문자열을 짧은 한 마디(token)로 구분할 때 사용
  • StringTokenizer는 포인터
    • 단어 하나하나를 토큰으로 분리
    • nextToken()메소드를 호출하여 값을 얻고 다음 토큰으로 포인터 이동
    • 포인터는 뒤로 갈 수 없다.
  • String의 split과는 다르게 StringTokenizer는 구분자로 ’.’로도 자를 수 있다.
// 공백으로 토큰을 구분한다
String s = "";
StringTokenizer stk = new StringTokenizer(s);

// 토큰의 개수를 알아내는 countTokens()
stk.countTokens();

// 토큰이 존재하면 true, 없으면 false를 리턴하는 hasMoreTokens()
stk.hasMoreTokens();

// 값(String)을 얻고 다음 토큰으로 포인터를 이동하는 nextToken()
stk.nextToken();

// 문자열을 구분자 나눌 땐 인수2개짜리 생성자 호출
String = str = "오늘은, 수요일, 입니다.";
StringTokenizer strStk = new StringTokenizer(str, ",");

// 구분자도 토큰으로 사용할 땐 인수3개짜리 생성자 호출, true면 보호
StringTokenizer strStk2 = new StringTokenizer(str, ",", true);
import java.util.StringTokenizer;
public class STKTest {
  public static void main(String[] args) {
    
    String s = "";
    s = "오늘은 수요일 입니다.";
    StringTokenizer stk = new StringTokenizer(s);
    
    System.out.println(stk.countTokens()); // 3
    
    while(stk.hasMoreTokens()) {
      System.out.println(stk.nextToken());
    }

    String str = "오늘은, 수요일, 입니다.";
    StringTokenizer stk1 = new StringTokenizer(str, ",");
    
    while(stk1.hasMoreTokens()) {
      System.out.println(stk1.nextToken());
    }
    
    StringTokenizer stk2 = new StringTokenizer(str, ",", true);

    while(stk2.hasMoreTokens()) {
      System.out.println(stk2.nextToken());
    }

    String names =  "이재현,이재찬~정택성,김희철.김정운~김정윤,공선의";
    // ',~.'로 구분
    StringTokenizer stk4 = new  StringTokenizer(names, ",~.");
    System.out.println("토큰의 수 :  "+stk4.countTokens());
    while(stk4.hasMoreTokens()) {
      System.out.println(stk4.nextToken());
    }
  }
}

Math

  • java.lang 패키지에 있는 클래스
  • 수학적인 일을 할 때 사용하는 클래스
  • API Doc을 보면 생성자가 없음
    • 생성자에 private이 붙은 것
    • 객체화해서 사용하는 클래스가 아님
  • method만 호출하여 사용하는 클래스
// 절대값
Math.abs(-10); // 10

// 반올림, 자바는 소수점이하 첫 번째자리에서 반올림(오라클 처럼 자리수 지정 못함)
Math.round(10.4); // 10
Math.round(10.5); // 11

// 올림, 0은 올리지 않는다. 
Math.ceil(10.1); // 11

// 절삭, 소수 이하를 절삭하는 메소드는 없다. => 그냥 casting
(int)10.1

// 내림, 소수점 이하 첫번째자리에서 내림
Math.floor(10.6); // 10

// 난수, 0~1사이 임의의 실수(double, 소수점이하 16자리)을 반환
Math.random();
// 0~9 사이 난수를 얻기 위해선 
Math.random()*10;
// A-Z 중 하나의 문자를 반환하는 일.알파벳은 26개. 65-90(대문자),  97-122(소문자)
// 랜덤 대문자 출력
for(int j=0; j<5; j++) {
  System.out.println((char)((int)(Math.random()*26)+65));
}
// 랜덤 소문자 출력
for(int j=0; j<5; j++) {
  System.out.println((char)((int)(Math.random()*26)+97));
}
// 난수 메소드를 이용해서 임의의 비밀번호 구하기
// 계정 비번찾기시 새비번을 반환해주는 메소드
// 48~57 숫자 65~90 대문자, 97~122 소문자
// 영문자대문자,소문자,숫자로 이루어진
// 임의의 비밀번호 8자리를 생성하여 반환하는 일
public class UseMath {
  public char[] createPassword() {
    char[] tempPass = new char[8];
    
    int rNum=0;
    for(int i=0; i<tempPass.length; i++) {
      while(true) {
        rNum = (int)(Math.random()*122)+1;
        if ((rNum > 47 && rNum < 58) || (rNum  > 64 && rNum <91)
                || (rNum > 96 && rNum <  123)) {
          break;
        }
      }
      System.out.println((char)rNum);
      tempPass[i] = (char)rNum;
    }
    System.out.println(tempPass);
    return tempPass;
  }

  // 다른 짧은 방식
  public char[] createPassword2() {
    char[] tempPass = new char[8];
    String flag=
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for(int i=0; i<tempPass.length; i++) {
      tempPass[i] = flag.charAt((int)(Math.random()*flag.length()));
    }
    
    System.out.println(tempPass);
    return tempPass;
  }
  
  public static void main(String[] args) {
      
    new UseMath().createPassword();
    new UseMath().createPassword2();
  }

  // switch문 사용한 방식(if보다 좋은 방식)
  public char[] createPassword3() {
    char[] tempPass = new char[8];
    
    int flag = 0;
    
    for(int i=0; i<tempPass.length; i++) {
      flag = (int)(Math.random()*3)+1;
      
      switch(flag) {
      case 1: // 숫자
        tempPass[i] =  (char)((int)(Math.random()*10)+48);
        break;
      case 2: // 대문자
        tempPass[i] =  (char)((int)(Math.random()*26)+65);
        break;
      case 3: // 소문자
        tempPass[i] =  (char)((int)(Math.random()*26)+97);
        break;
      }
    }

    System.out.println(tempPass);
    return tempPass;
  }
}

System.currentTimeMillis

02

  • 메인보드 CMOS가 날짜정보를 갖고 있고 OS는 CMOS로부터 날짜를 받아온다.
    • JVM System클래스가 OS로부터 날짜정보를 전달받아 사용
  • 시간을 얻는 일을 하는 메소드 System.currentTime
    • 1970-01-01 00:00:00 부터 현재 시간의 차를 long형으로 반환
    • System클래스엔 더 정밀한 시간을 반환하는 nanoTime() 메소드(1/억)도 있다.
  • 코드 수행시간을 잴 때 많이 사용
public class UseCurrentTime {
  public void test() {

    long st = System.currentTimeMillis();
    long sum = 0;
    
    for(int i=0; i<10000; i++) {
      sum = sum + i;
      // System.out.println(); 출력하면  처리속도가 엄청 느려진다.
      // 테스트 때를 제외하면  System.out.println은 거의 안쓴다
      System.out.println(i);
    }
    
    long et = System.currentTimeMillis();
    // 코드 수행 시간
    System.out.println((et-st)+"ms");
  }
  public static void main(String[] args) {
    
    UseCurrentTime uct = new UseCurrentTime();
    uct.test();
  }
}
// 프로그램 평균 시간 구하기 - 10~15회 반복, 
// 평균값을 구하면 평균수행시간을 구할 수 있음
public class ProcessTime {
  public static void main(String[] args) {
    // 프로그램 평균시간 구하기
    long[] processTime = new long[17];
    long st = 0, et = 0;
    long sumTime = 0;
    long avgTime = 0;
    for (int i = 0; i < processTime.length; i++) {
      st = System.currentTimeMillis();
      for (int j = 0; j < 50000; j++) {
        System.out.print(j);
      }
      System.out.println();
      et = System.currentTimeMillis();
      processTime[i] = (et - st);
      sumTime += processTime[i];
    }
    avgTime = sumTime / processTime.length;
    System.out.println("소요되는 평균시간(ms) : " +  avgTime);
  }
}

날짜 관련 클래스

  • java.util 패키지에 존재
  • Date : 형식이 있는 날짜 정보를 얻을 때
    • 객체 생성해서 사용
    • java.text 패키지에 있는 SimpleDateFormat과 같이 사용
    • Date 클래스는 거의 모든 메소드가 Deprecated 따라서 Calendar 클래스 사용
  • Calendar : 단일 날짜 정보를 얻을 때

Date

  • 날짜 정보를 얻을 때 사용
    • 형식을 맡는 SimpleDateFormat과 같이 사용
    • 객체 생성해서 사용
  • Date 클래스는 거의 모든 메소드가 Deprecated 따라서 Calendar 클래스 사용권장

03

SimpleDateFormat

  • java.text 패키지에서 제공
  • 날짜 형식을 제공
    • pattern을 사용해서 형식을 지정
      • 년 - y, 월 - M, 일 - d, 오전 - a
      • 시
        • h - 12시간제
        • K - 0~11시간제
        • H - 0~23시간제
        • k - 1~24시간제
      • 분 - m, 초 - s, 요일 - E

04

  • 패턴 예시

05

// 1.생성 - 사용할 날짜 형식을 만드는 일
SimpleDateFormat sdf = new SimpleDateFormat(String pattern);

// 2.날짜 객체를 생성
Date d = new Date();

// 3.날짜 객체를 넣어서 지정한 형식의 날짜를 얻는다.
// has-a 관계라 말한다(SimpleDateFormat객체가 Date객체를 갖는 관계)
sd.format(date);

06

  • 오라클과 다르게 패턴이 길어도 에러가 없다.
public class UseDate {
     
  public UseDate() {
    Date date = new Date();
    
    System.out.println(date);
    // 1900을 더해야 제대로된 Year나옴(Deprecated)
    System.out.println(date.getYear()+1900);

    SimpleDateFormat sdf = new SimpleDateFormat("y");
    String formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018
    sdf = new SimpleDateFormat("yy");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 18
    
    sdf = new SimpleDateFormat("yyyy");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018
    
    sdf = new SimpleDateFormat("yyyy년MM");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12
    
    sdf = new SimpleDateFormat("yyyy년M");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일 a");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일  오후
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일 a HH");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일  오후 15
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일 a hh");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일  오후 03
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일 a  HH(hh,kk)");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일  오후 15(03,15)
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일 a  HH(hh,kk):mm");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일  오후 15(03,15):39
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일 a  HH(hh,kk):mm:ss");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일  오후 15(03,15):39:36
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일 a  HH(hh,kk):mm:ss E요일");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일  오후 15(03,15):39:36 수요일
    
    sdf = new SimpleDateFormat("yyyy년MM월dd일 a  HH(hh,kk):mm:ss EEEE");
    formatDate = sdf.format(date);
    System.out.println(formatDate); // 2018년12월05일  오후 15(03,15):39:36 수요일
  }
  
  public static void main(String[] args) {
    new UseDate();
  }
}
  • 로케일을 사용하면 다른 나라의 날짜형식을 사용가능
// 2018 12 05 PM 15(03,15):47:23 Wednesday
sdf = new SimpleDateFormat("yyyy MM dd a HH(hh,kk):mm:ss EEEE", Locale.UK);

// 2018 12 05 午後 15(03,15):47:23 水曜日
sdf = new SimpleDateFormat("yyyy MM dd a HH(hh,kk):mm:ss EEEE", Locale.JAPAN);

// 2018 12 05 PM 15(03,15):47:23 mercredi
sdf = new SimpleDateFormat("yyyy MM dd a HH(hh,kk):mm:ss EEEE", Locale.FRANCE);

// 2018 12 05 下午 15(03,15):47:23 星期三
sdf = new SimpleDateFormat("yyyy MM dd a HH(hh,kk):mm:ss EEEE", Locale.CHINESE);

// 2018 12 05 PM 15(03,15):47:23 Mittwoch
sdf = new SimpleDateFormat("yyyy MM dd a HH(hh,kk):mm:ss EEEE", Locale.GERMANY);

07


Calendar

  • java.util 패키지에서 제공
  • 단일 날짜정보를 얻을 때 사용
  • Calendar는 추상클래스
    • 객체화가 안된다
    • GregorianCalendar(자식클래스)를 객체화하거나 getInstance라는 static 메소드를 사용해서 Calendar 인스턴스를 받아와야 사용가능
  • Calendar 클래스는 생성되는 시점의 시간정보를 갖는다.
// Calendar 클래스가 제공하는 getInstance메소드로 사용하는 방법
Calendar c = Calendar.getInstance();

// is-a 관계 객체화로 Gregorian Calendar를 사용하는 방법
Calendar c1 = new GregorianCalendar();
GregorianCalendar c2 = new GregorianCalendar();
  • get, set메소드에 넣는 field와 그렇지 않은 field로 나뉨
    • java API doc참조
// 사용방법) get메소드에 field(Constant)를 집어넣어서 값을 얻는다.
System.out.println(c.get(Calendar.YEAR)); // 2018

// MONTH는 0~11을 반환 +1을 해줘야 함
System.out.println(c.get(Calendar.MONTH)+1); 

// 요일을 나타낼 때 DAY_OF_MONTH 사용
System.out.println(c.get(Calendar.DAY_OF_MONTH));

// 숫자로 1~7 출력됨(일~토). 숫자는 요일의 인덱스를 뜻함
System.out.println(c.get(Calendar.DAY_OF_WEEK));

// 오늘이 올해 몇번째 날인지 출력
System.out.println(c.get(Calendar.DAY_OF_YEAR));

// AM/PM 출력 : 0(오전) 1(오후)
System.out.println(c.get(Calendar.AM_PM));

// 12시간제
System.out.println(c.get(Calendar.HOUR));

// 24시간제
System.out.println(c.get(Calendar.HOUR_OF_DAY));

// 분, 초
System.out.println(c.get(Calendar.MINUTE));
System.out.println(c.get(Calendar.SECOND));

숙제풀이1 Lotto 클래스 숙제풀이2 UseLotto클래스

숙제풀이2



Java