log4jjava.util.logging
Manager class org.apache.log4j.LogManager java.util.logging.LogManager
Logger objects org.apache.log4j.Logger java.util.logging.Logger
Named loggers Supported Supported
Logging levels

Levels are declared in theorg.apache.log4j.Level class. log4j has five pre-defined levels:

  1. FATAL
  2. ERROR
  3. WARN
  4. INFO
  5. DEBUG

Levels are declared in thejava.util.logging.Level class. There are seven pre-defined levels:

  1. SEVERE
  2. WARNING
  3. INFO
  4. CONFIG
  5. FINE
  6. FINER
  7. FINEST
Log event object org.apache.log4j.spi.LoggingEvent java.util.logging.LogRecord
Output destinations Appender classes. These classes implement theorg.apache.log4j.Appender interface. Handler classes. These classes extendjava.util.logging.Handler.
Output message filtering Filter classes. These classes extendorg.apache.log4j.spi.Filter. Filter classes. These classes must implement thejava.util.logging.Filter interface.
Output message formatting Layout classes extend org.apache.log4j.Layout. Formatter classes extendjava.util.logging.Formatter.
Programmatic configuration Supported Supported
Property file configuration Supported Supported
XML configuration Supported. The XML configuration file must comply with log4j.dtd. Not supported
Email notification SMTPAppender class SMTPHandler class (third-party extension)



1.5버전이후인가?? 아무튼 언제부터인가 이클립스의 느낌표를 클릭하면

자동 생성되는 Generic이란 녀석 :)

그냥 그렇게 생각했었는데, 생각외로 여러모로 쓸모가 많았다.

C++의 템플릿의 비스무리 한거 같기도 하지만서도ㅋㅋ

 

늘 자료구조때 골머리를 앓게 하는건, 검색과 정렬이다.

아직도 수많은 컴퓨터공학도들이

자료구조란 학문을 하며 골머리를 썩고 있는데ㅋㅋ

 

그만큼 자료구조라는 학문이 중요하기 때문이고

모든 컴퓨터공학의 근간이 되는 학문임은 강조에 강조를 해도

부족하지 않다.

 

자바를 쓰다보면 느꼈던건 역시 막강하고 손쉽게 사용할 수 있는 API에 있다.

이번에도 항상 나만의 정렬, 검색 알고리즘을 구현(?)해서 사용하다가,

이번에 Collections를 이용해봤는데, 여간 편리한게 아니다-_ -);

역시 난 시대에 뒤떨어지고 있었던 것인가??;;

 

그래서 잠깐 소개하고자 한다.

 

먼저 알아야 할것은 바로 이 두 interface다.

 

java.lang Interface Comparable<T>

java.util Interface Comparator<T>

 

저 두 인터페이스를 이용해서 Collections.sort를 이용해 정렬을 할 수가 있는데,

List에 들어가는 객체에 Comparable을 implements함으로써, 정렬을 할 수있게 된다.

 

방법1. Comparable을 implements한다.

 

class PersonalInfo implements Comparable<PersonalInfo>{
 
 private String name = null;
 
 private String phoneNumber = null;
 
 public String getName() {
  return name;
 }
 
 public void setName(String name) {
   this.name = name;
 }
 
 public String getPhoneNumber() {
  return phoneNumber;
 }
 
 public void setPhoneNumber(String phoneNumber) {
  this.phoneNumber = phoneNumber;
 }
 
  public boolean getSortingMode() {
  return sortingMode;
 }

 public void setSortingMode(boolean sortingMode) {
  this.sortingMode = sortingMode;
 }
 
 
@Override
 public int compareTo(PersonalInfo o) {
    return name.compareTo( o.getName() );
  }

}

 

compareTo라는 메소드를 구현해야 하는데, 그 안에 비교하고자 하는 항목을 compareTo를 이용하여

비교해준 후,

Collections.sort()의 파라미터로 PersonalInfo객체가 들어있는 리스트를 넣어주기만 하면 된다.

 

위와 같은 방법은 편리하나, 여러가지 항목으로 정렬을 해야 할 경우 제약이 좀 있다.

 

그래서 사용하는 것이,

바로 Comparator 이다.

 

방법2. Comparator사용.

 

     Comparator<PersonalInfo> comparator = new Comparator<PersonalInfo>(){
      @Override
      public int compare(PersonalInfo o1, PersonalInfo o2) {      
       return o1.getName().compareTo( o2.getName() );
      }      
     };
     Collections.sort( list, comparator );

 

와 같은 방법으로 할 수 있다. 여러개의 정렬 항목에 따른 comparator를 만든 후, Collections의 파라미터로 던져주면,

정렬은 더이상 고민하지 않아도 될 것이다.

 

참고로 Collections.sort()의 documents내용은 다음과 같다.

public static <T extends Comparable<? super T>> void sort(List<T> list)

public static <T> void sort(List<T> list, Comparator<? super T> c)

 




[출처 : http://blog.naver.com/celestialorb/40065368727]

Java Collections Framework 의 일원이며 Collection 객체들을(set, list, map ..... ) 유용하게 사용하기위한 util class이다.

주로 연산작업이나 콜렉션객체를 리턴한다.

 

Field

  • EMPTY_LIST
  • EMPTY_MAP
  • EMPTY_SET

        모두 직렬화가 가능하며 사이즈가 0인 객체를 만들어 준다. 각각 emptyList(), emptyMap(), emptySet() 메소드와 동일한 기능을 수행 함. (null값이 들어간 객체가 아닌 말그대로의 빈객체이므로 NullPointException이 발생하지 않는다)

 

Method

  • sort  :  public static <T extens Comparable<? super T>> void sort(List<T> list)
                  public static <T> void sort(List<T> list, Comporator<? super T> c)
    리스트 객체를 정렬해주는 메소드 comparble을 implements한 클래스를 이용해 정렬 할 수도 있고, Comparator를 이용해 조건을 여러개 주어서 검색할 수도 있다.
    Comparable 이나 Comparator 응용 방법 링크
  • 01 import java.util.ArrayList;
    02 import java.util.Collections;
    03 import java.util.Comparator;
    04 
    05 import java.lang.Comparable;
    06 
    07 public class TestCollections {
    08     public static void main(String args[]) throws Exception {

    09         ArrayList<PersonalInfo> list = new ArrayList();
    10         list.add(new PersonalInfo("홍길동","11-11-11"));
    11         list.add(new PersonalInfo("김개똥","66-66-66"));
    12         list.add(new PersonalInfo("정지훈","66-66-66"));
    13         list.add(new PersonalInfo("정지훈","44-44-44"));
    14         list.add(new PersonalInfo("이소라","33-33-33"));
    15         list.add(new PersonalInfo("손예진","55-55-55"));
    16         System.out.println("====== 정렬전 ======");
    17         for(int idx = ; idx < list.size() ; idx++) {
    18           System.out.println(list.get(idx).getName() ", " 
    19                            + list.get(idx).getPhoneNumber());
    20         }
    21         Collections.sort(list);
    22         System.out.println("====== 정렬후 ======");
    23         for(int idx = ; idx < list.size() ; idx++) {
    24           System.out.println(list.get(idx).getName() ", " 
    25                            + list.get(idx).getPhoneNumber());
    26         }
    27         //@Override  여러검색조건을 선택할때 사용
    28         Comparator<PersonalInfo> comparator = 

    29           new Comparator<PersonalInfo>(){

    30           public int compare(PersonalInfo o1, PersonalInfo o2) {

    31            return o1.getName().compareToo2.getPhoneNumber() );
    32           }      
    33          };
    34         Collections.sortlist, comparator );
    35         System.out.println("====== 정렬후 ======");
    36         for(int idx = ; idx < list.size() ; idx++) {
    37           System.out.println(list.get(idx).getName() ", " 
    38                            + list.get(idx).getPhoneNumber());
    39         }
    40     }
    41 }
    42 //검색조건이 하나일 때 유용.

    43 class PersonalInfo implements Comparable<PersonalInfo>{
    44  
    45   private String name = null;
    46   private String phoneNumber = null;
    47   private boolean sortingMode = false;
    48   
    49   public PersonalInfo(String name, String phoneNumber) {
    50     this.name = name;
    51     this.phoneNumber = phoneNumber;
    52     this.sortingMode = true;
    53   }
    54  
    55   public void setName(String name) {   
    56     this.name = name; 
    57   }
    58   public void setPhoneNumber(String phoneNumber) {  
    59     this.phoneNumber = phoneNumber; 
    60   }
    61   public void setSortingMode(boolean sortingMode) {  
    62     this.sortingMode = sortingMode; 
    63   }
    64  
    65   public String  getName() {  return name; }
    66   public String  getPhoneNumber() {  return phoneNumber; }
    67   public boolean getSortingMode() {  return sortingMode; }
    68  
    69   //@Override
    70   public int compareTo(PersonalInfo o) {
    71     return name.compareToo.getName() );
    72   }
    73 
    74 }

     

    결과 값 :

    ====== 정렬전 ======
    홍길동, 11-11-11
    김개똥, 66-66-66
    정지훈, 66-66-66
    정지훈, 44-44-44
    이소라, 33-33-33
    손예진, 55-55-55
    ====== 정렬후 ======
    김개똥, 66-66-66
    손예진, 55-55-55
    이소라, 33-33-33
    정지훈, 66-66-66
    정지훈, 44-44-44
    홍길동, 11-11-11
    ====== 정렬후 ======
    홍길동, 11-11-11
    정지훈, 44-44-44
    정지훈, 66-66-66
    이소라, 33-33-33
    손예진, 55-55-55
    김개똥, 66-66-66


  • binarySearch :
    public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
    public static <T> int binarySearch(List<? extends T> list, T key,  Comparator<? super T> c)
    메소드 수행전 반드시 정렬되어있어야 하며, 정렬되지 않았을 때 수행시 결과값은 undefined 된다. 검색 결과가 여러개일 경우 랜덤하게 추출하기 때문에 원하는 값을 보장하지 않는다. 결과값이 없을 경우 : (-(insertion point) - 1).
  • reverse : pubic static void reverse(List<?> list)
    리스트를 역순으로 정렬시킨다. (순차정렬이 아님)
  • suffle : public static void shuffle(List<?> list)
                    public static void shuffle(List<?> list,  Random rnd)
    랜덤하게 리스트를 섞는다.
  • swqp : public static void swap(List<?> list, int i, int j)
    i와 j 포지션의 위치를 서로 바꾼다. IndexOutOfException에 주의할 것
  • fill : public static <T> void fill(List<? super T> list, T obj)
    obj 값으로 모든 엘리먼트들을 변경한다
  • copy : public static <T> void copy(List<? super T> dest, List<? extends T> src )
    src리스트의 모든 엘리먼트들을 dest 리스트에 카피한다. 반드시 dest 리스트가 src리스트보다 커야하며, 아닐 경우 IndexOutOfException이 발생한다.
  • min :
    public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll )
    public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll, Comparator <? Super T>comp )
    최소값을 구한다. 자동소팅된다. 결과값이 여러개일 경우 Comparator 를이용해 처리한다.
  • max :
    public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll )
    public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll, Comparator <? Super T>comp )
    최대값을 구한다. 자동소팅된다. 결과값이 여러개일 경우 Comparator 를이용해 처리한다.
  • rotate : public static void rotate(List<?> list,  int distance)
    distance만큼 옆으로 이동한다. 양수일경우 오른쪽, 음수일경우 왼쪽으로 이동 된다. list.size()보다 클 순 없다.
    보통 subList를 이용해 많이 활용된다. Collections.rotate( list.subList(j, k+1), distance)
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 의 엘리먼트를 갖는 리스트의 경우
    Collections.rotate( list.subList(2,5), 1) ); 수행 하면
    [1, 2, 5, 3, 4, 6, 7, 8, 9, 10] 로변경된다.
  • replaceAll : public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)
    list에서 oldVal값을 찾아서 newVal값으로 변경 (oldVal == null ? e == null : oldVal.equals(e))
  • indexOfSubList : public static int indexOfSubList(List<?> source, List<?> target)
    source리스트에서 target리스트를 검색. source리스트에서 검색되면 가장 첫번째인덱스(lowest index )를 리턴한다. 검색이 되지 않을 경우 -1을 리턴한다.
  • lastIndexOfSubList : public static int lastIndexOfSubList(List<?> source, List<?> target)
    source리스트에서 target리스트를 검색. source리스트에서 검색되면 가장 첫번째인덱스(highest index )를 리턴한다. 검색이 되지 않을 경우 -1을 리턴한다.
  • unmodifiableCollection : public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c)
    읽기전용의 뷰컬렉션을 리턴한다. 컬렉션의 내용을 변경하게 되면 java.lang.UnsupportedOperationException 이 발생함. 각특성은  document확인
    동일기능의 메소드 -
    unmodifiableSet : public static <T> Set<T> unmodifiableSet(Set<? extends T> s )
    unmodifiableSortedSet : public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s )
    unmodifiableList : public static <T> List<T> unmodifiableList(List<? extends T> list )
    unmodifiableMap : public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K,? extends V> m)
    unmodifiableSortedMap : public static <K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K,? extends V> m )
  • synchronizedCollection : public static <T> Collection<T> synchronizedCollection(Collection<T> c )
    컬렉션 동기화 . 동기화된 컬렉션을 리턴받아 Iterator를 사용하여, 리턴된 컬렉션을 반복처리하는 경우에는, 특별히, synchronized 블럭과 함께 사용해야 한다. 각 특성은 document 확인
    동일기능의 메소드 -
    synchronizedSet : public static <T> Set<T> synchronizedSet(Set<T> s )
    synchronizedSortedSet : public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s )
    synchronizedList : public static <T> List<T> synchronizedList(List<T> list )
    synchronizedMap : public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m )
    synchronizedSortedMap : public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m )




  •  

     





[출처 : http://blog.naver.com/ily1201/91140240]
pthread를 써야하는 이유는 단일 프로세서에서는 동시에 여러 작업을 하는 것처럼 유저에게 보여야하는 일이 있는데 간단한 예로 테트리스 게임같이 블록이 일정시간마다 자동적으로 내려가도록 하는 부분과 키 입력을 받을 때만 블록을 입력받은 방향으로 이동시키는 부분등... 이걸 멀티 쓰레드로 만들지 않는다면 아마 프로그래밍이 상당히 복잡해지고 구현하는데도 상당히 어려울 것이다. 이를 쉽게 처리하기위해서 pthread API 함수를 이용하여 쉽게 구현할 수 있다.


pthread API 함수를 쓰기 위해서 pthread.h 파일을 include 해야만 한다.
#include <pthread.h> 

그리고 필히 컴파일시 -lpthread 옵션 추가해주어야만 한다. 빠뜨리면 컴파일 오류가 일어나거나 아니면 쓰레드가 정상 작동하지 않을 것이다.

pthread_t : pthread의 자료형을 의미

int pthread_create( pthread_t *th_id, const pthread_attr_t *attr, void* 함수명, void *arg );
 - pthread 생성한다.
첫 번째 인자 : pthread 식별자로 thread가 성공적으로 생성되면 thread 식별값이 주어진다.
두 번째 인자 : pthread 속성(옵션), 기본적인 thread 속성을 사용할 경우 NULL
세 번째 인자 : pthread로 분기할 함수. 반환값이 void* 타입이고 매개변수도 void* 으로 선언된 함수만 가능하다. ex) void* handler (void* arg) { ... }
네 번째 인자 : 분기할 함수로 넘겨줄 인자값. 어떤 자료형을 넘겨줄 지 모르기 때문에 void형으로 넘겨주고 상황에 맞게 분기하는 함수내에서 원래의 자료형으로 캐스팅해서 사용하면 된다.
리턴 값 : 성공적으로 pthread가 생성될 경우 0 반환

int pthread_join( pthread_t th_id, void** thread_return );
 - 특정 pthread가 종료될 때까지 기다리다가 특정 pthread가 종료시 자원 해제시켜준다.
첫 번째 인자 : 어떤 pthread를 기다릴 지 정하는 식별자
두 번째 인자 : pthread의 return 값, 포인트로 값을 받아오는 점을 주의할 것.

int pthread_detach( pthread_t th_id );
 - th_id 식별자를 가지는 pthread가 부모 pthread로부터 독립한다. 즉 이렇게 독립된 pthread는 따로 pthread_join()이 없어도 종료시 자동으로 리소스 해제된다.

void pthread_exit( void* ret_value );
 - 현재 실행중인 thread를 종료시킬 대 사용한다. 보통 pthread_exit가 호출되면 cleanup handler가 호출되며 보통 리소스 해제하는 일을 수행한다.

void pthread_cleanup_push( void* (함수명), void* arg );
 - pthread_exit()가 호출될 때 호출된 handler를 정하는 함수.  보통 자원 해제용이나 mutex lock 해제를 위한 용도로 사용된다.

void pthread_cleanup_pop(int exec);
- 설정된 cleanup handler를 제거하기 위해서 사용되는 함수.  exec 값을 0일 경우 바로 cleanup handler 제거하고 그외의 값을 가질 경우 cleanup handler를 한번 실행한 후 제거한다.

pthread_t pthread_self(void);
 - 현재 동작중인 pthread의 식별자를 리턴한다.

기초시리즈입니다.
오늘은 Hashtable에 대해서 잠시 이야기해 보도록 하죠.

Hashtable은 key를 이용해서 value를 꺼낼 수 있도록 해 주는 자료구조죠.

                   Hashtable table = new Hashtable();                

                   table.put("영화, "유쥬얼서스펙트);

                   table.put("오락, "황금어장라디오스타);

                   table.put("음악, "윤종신노래짱 ㅎㅎ);

뭐 이런식으로, 우선 table에 key와 value를 넣어 주고

                   String key = "영화";
                   String value = (String) table.get(key);

"영화"를 key로 가지고 있는 value, 즉 "유쥬얼서스펙트"를 꺼낼 수 있도록 되어 있습니다.
보다시피 아주 간단한 방법으로 사용할 수 있습니다.

그래서 간단하게 코드를 한번 짜 보았습니다.

                   Hashtable table = new Hashtable();

                   table.put("영화, "유쥬얼서스펙트);
                   table.put("오락, "황금어장라디오스타);
                   table.put("음악, "윤종신노래짱 ㅎㅎ);                 

                   String key = "오락;

                   String value = null;

                   

                   // "오락"이라고 되어 있는 key에 값이 있는지 확인하다.

                   boolean isContains = table.containsKey(key);


                   if ( isContains ) {
                             // 값이 있으니깐 가져다 쓰도록 하자.

                             value = (String) table.get(key);

                   } else {

                             // 값이 없으니깐 안 정해 놨다고 하자.

                             value = "뭘좋아하는지안정해놨네";

                   }


                   System.err.println(key + " : " + value);

하는 일은,
1. Hashtable을 하나 만들고,
2. 각종 값을 넣고,
3. 가지고 오고자 하는 key가 있다면, value를 가지고 오고
4. 없으면 다른 값을 설정해 준다.

아주 자연스러운 과정으로 보인다.

하지만 위의 코드는 수정되어야 할 부분을 가지고 있다.
위의, 코드를 짤때 Hashtable의 특성을 생각하지 않고, 쉽게 짰기 때문에 수정할 부분이 발생된다.

재미삼아 한번 맞춰 보세요~ 일부러 공란을 조금 두겠습니다.
( 블로그에 오시는 분들은 ;; 고수분들이실꺼라 ;; 걍 공란 없습니다. ㅋㅋ )

그 부분은 바로 아래의 코드이다.

// "오락"이라고 되어 있는 key에 값이 있는지 확인하다.

boolean isContains = table.containsKey(key);


if ( isContains ) { ....

 


해당 key에 설정된 값이 있는지 확인한 뒤에 값을 가지고 오는게 뭐가 틀렸냐고 하겠지만,
위의 코드로 인해서 약간의 손해를 보게 된다.

왜 그런지 Hashtable의 API를 확인해 보자.
get(Object) 메소드를 살펴 보도록 하자.

------

http://java.sun.com/javase/6/docs/api/java/util/Hashtable.html#get(java.lang.Object)

get

public V get(Object key)
Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

.....

Returns:
the value to which the specified key is mapped, or null if this map contains no mapping for the key

......

------

get의 return부분은 아래와 같이 설명되어 있다.

인자로 들어온 key에 맵핑되어 있는 value를 반환하거나,
map에서 인자로 들어온 key로 맵핑된것이 없으면 null을 반환한다.

즉, get했을때 인자로 key를 주어서 null이 나오면, map(table)안에 해당 정보가 없다는 말이다.

그렇다면 put할때, key에 해당하는 value로 null을 줄 수 있지 않을까?
key에 해당하는 value를 null을 줄 수 있다면, get(key) 했을때 null이 반환될 가능성이 있기 때문이다.

하지만 그런 걱정은 안해도 된다.
Hashtable에 대해 설명해둔 API문서를 다시 확인해 보자.

------
http://java.sun.com/javase/6/docs/api/java/util/Hashtable.html

public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, Serializable

This class implements a hashtable, which maps keys to values. Any non-null object can be used as a key or as a value.

.....

------

Hashtable은 key혹은 value로 non-null인 어떠한 Object도 사용가능하다고 한다.
즉, key와 value는 절대로 null이 될 수 없다.


자,
Hashtable에 대한 대충의 정리가 끝났으니, 생각없이 짜 놓았던 소스를 다시 보도록 하자.

                   Hashtable table = new Hashtable();

                   table.put("영화, "유쥬얼서스펙트);
                   table.put("오락, "황금어장라디오스타);
                   table.put("음악, "윤종신노래짱 ㅎㅎ);          

                   

                   String key = "오락;

                   String value = null;

                   

                   // "오락"이라고 되어 있는 key에 값이 있는지 확인하다.

                   boolean isContains = table.containsKey(key);


                   if ( isContains ) {
                             // 값이 있으니깐 가져다 쓰도록 하자.

                             value = (String) table.get(key);

                   } else {

                             // 값이 없으니깐 안 정해 놨다고 하자.

                             value = "뭘좋아하는지안정해놨네";

                   }


                   System.err.println(key + " : " + value);



위의 소스에서 손해 보고 있는 코드는 아래와 같다.



boolean isContains = table.containsKey(key);

if ( isContains ) { ....




위의 소스대로라면

1. containsKey로 실제 key가 존재하는지 확인하고,

2. key가 존재하면 get을 이용해서 값을 가지고 온다.



하지만, 다음과 같이 고쳐 쓸 수도 있다.


                   String key = "오락;

                   String value = table.get(key);


                   if ( value == null ) {

                             // 값이 없으니깐 안 정해 놨다고 하자.

                             value = "뭘좋아하는지안정해놨네";

                   }




get(key)메소드만을 사용해서 null체크를 이용해 똑같은 일을 수행할 수 있다.

굳이 containsKey를 이용해서 확인할 필요가 없다는 말이다.


그렇다면 재미삼에 containsKey메소드와 get 메소드의 내용을 잠시 살펴 보자.



------

JDK 1.6.0_05 ( c:\program files\java\jdk1.6.0_05\src.zip 파일안에 있음 )


 

   public synchronized boolean containsKey(Object key) {

             Entry tab[] = table;

             int hash = key.hashCode();

             int index = (hash & 0x7FFFFFFF) % tab.length;

             for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {

                 if ((e.hash == hash) && e.key.equals(key)) {

                           return true;

                 }

             }

             return false;

   }

 

   public synchronized V get(Object key) {

             Entry tab[] = table;

             int hash = key.hashCode();

             int index = (hash & 0x7FFFFFFF) % tab.length;

             for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {

                 if ((e.hash == hash) && e.key.equals(key)) {

                           return e.value;

                 }

             }

             return null;

   }

------



보다시피, containsKey와 get의 메소드는 거의 동일하며,


마지막에 true, false를 반환하느냐 ( containsKey )

혹은 Object, null을 반환하느냐만 ( get )

다를 뿐이다.


그러므로 constainsKey대신에 get을 사용해도 똑같은 일을 할 수 있다.

( 사실은 get을쓰게 되면 Object의 레퍼런스가 하나 더 생성되겠지만.. 자세한 이야기는 집어 치우자. )




get을 하려고 containsKey를 사용해서 값이 있는지 확인하는것은

전혀 필요 없는짓이며 이로 인해서 많은 손해를 보게 된다.



사실 containsKey를 get하기 전에 사용한다고 해서,그렇게 많이 손해를 보겠느냐~ 라고 생각할 수도 있다.

기껏해야 0.00001초 정도 아닐까. 라고 생각할 수 있다.

그렇다고 치면 10000번씩 호출해도 0.001초 차이 날까 말까 하지 않을까?


그래 그 말도 맞을 수도 있다.


하지만, 위의 코드중에서 containsKey 메소드를 다시 한번 보도록 하자.


   public synchronized boolean containsKey(Object key) {

             Entry tab[] = table;

             int hash = key.hashCode();

             int index = (hash & 0x7FFFFFFF) % tab.length;

             for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {

                 if ((e.hash == hash) && e.key.equals(key)) {

                           return true;

                 }

             }

             return false;

   }


위의 코드에서 눈여겨 볼만한 부분은 synchronized 키워드이다.


Hashtable은 put, remove, get등 모든 데이터 입출력에 대해서 "동기화" 된다.

( 왜 그러냐고 물으면 안된다. Java에서 그렇게 정의해 두었다. 정의라는것에 이유는 없다. )

( 동기화에 관련된 자세한 이야기는 다른 강좌등을 참고하도록 하자. )

------

As of the Java 2 platform v1.2, this class was retrofitted to implement the Map interface, making it a member of the Java Collections Framework. Unlike the new collection implementations, Hashtable is synchronized.

------


Hashtable 객체의 put, remove, get, containsKey 등의 메소드가 호출 될때마다

1. 다른 Thread에서 자신의 객체에 접근할 수 없게 무조건 Lock를 잡고

2. 해당 메소드를 수행하고 결과를 반환한 뒤에

3. 잡았던 Lock를 놓게 된다.


이때 위의 동작만 보더라도 결과만 반환하는것이 아니라, Lock를 잡고, 푸는 과정만해도 2번의 동작이 추가 된다.

그리고 일반적으로 Lock를 잡고, 푸는것은 많은 시간이 소모되는 작업으로 알려져 있다.




그러므로

Hashtable의 특성인

1. cotainsKey대신 get을 이용할 수도 있음.

2. 동기화

에 대해서 잘 알고, Hashtable을 사용하도록 하자.



--------

문제가 될만한 사항이 있으면 언제든지 알려 주세요.



[출처 : http://ggaman.com/tt/917]

아직도 System.out.println()으로 디버그용 메시지를 화면에 출력한다면, 이제 삽질 그만하고 로깅 API들을 사용해 볼 것을 권장하고 싶다.

그 중에서도 난 Log4j를 사용한다. (사실 이거밖에 모른다... ;) )

혹여 log4j.properties 설정이 귀찮아서 Log4J를 사용하지 않는다면 다음의 기본적인 log4j.properties를 사용해보자. 이것만으로도 System.out.println과는 비교할 수 없는 강력하고 편리한 로깅 기능을 사용할 수 있다.

기본적인 log4j.properties
아래 로그설정은 로깅 메시지를 화면에도 출력하고 파일로도 출력한다. 파일의 경우에는 매일매일 날짜별로 다른 파일을 사용하므로 한개의 로그 파일이 무한정 커지는 것을 걱정할 필요는 없다.

이 설정대로 하면 로깅 메시지에 로그를 남긴 소스파일의 이름과 소스에서 메소드 이름과 줄 번호까지 출력된다. System.out.println()으로는 꿈도 못꾸는 기능들이다.

log4j.rootLogger = DEBUG, stdout, dailyfile

log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p ({%t} %F[%M]:%L) [%d] - %m%n

log4j.appender.dailyfile.Threshold = DEBUG
log4j.appender.dailyfile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyfile.File = logfile.log
log4j.appender.dailyfile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyfile.layout.ConversionPattern=%5p ({%t} %F[%M]:%L) [%d] - %m%n


저기서 logfile.log 가 로그의 내용을 출력할 파일 이름이다. 적당히 다른 이름으로 바꾼다. 절대경로로 줘도되고 위와 같이 상대경로로 줘도 된다.

위 파일을 클래스패스가 걸린 디렉토리에 두면 된다. 웹 어플리케이션은 WEB-INF/classes에 두면 된다.

로그는 어떻게 남기지?
각 클래스에서 로그를 남길 때는 다음과 같이..

// 로거 임포트하기
import org.apache.log4j.Logger;

public class ClassName {
    /** Log4J 로거 얻기 */
    private Logger log = Logger.getLogger(ClassName.class);
    //혹은 private Logger log = Logger.getLogger(this.getClass());
    public void method() {

        if (log.isDebugEnabled()) {
            log.debug("디버깅용 메시지");
        }
        log.info("정보를 남기기위한 메시지");
        
        try {
            //어쩌구 저쩌구 실행...
        } catch (Exception ex) {
            //로그에 예외 메시지도 함께 남기기
            log.error("예외가 발생했어요~~", ex);
        }
    }
}


ClassName.class는 로거가 출력할 클래스의 이름이다. 그냥 항상 클래스이름.class로 하면 된다.

만약 static 메소드에서 로거를 사용해야 한다면 로거를 생성하는 부분을

private static Logger log = Logger.getLogger(ClassName.class);



위와 같이 static 으로 선언하면 된다.
되도록 static으로 로거를 생성하지 말라. 이에 관해서는, Logging/StaticLog를 참조한다. 추가: 2006/04/11

실제로 로그 메시지 출력이 어떻게 되는지는 직접 확인해보면 알 수 있을 것이다.

마무리~
자, 이제 프로그램에서 보기 싫은 System.out.println()을 몽땅 없애버리자!!
Log4J하나만으로도 디버깅하기 쉽고 뽀대나고 어딘가 비싸보이는 프로그램이 된다. ^^;


[출처 : http://kwon37xi.egloos.com/2176487]

1. LOG4J 구조

일단 log4j를 잘 모르지만 그 구조만 살짝 살펴보고 넘어갑시다
log4j는 크게 3가지 요소로 구성되며 그 구조는 다음과 같습니다

① Logger(Category) : 로그의 주체 (로그 파일을 작성하는 클래스)
     
     로깅 메세지를 Appender에 전달합니다.
     Log4j의 심장부에 위치하며, 개발자가 로그출력 여부를 런타임에 조정되도록 해준다.
     Logger는 로그레벨을 가지고 있으며, 로그의 출력여부는 로그문의 레벨과 로거의 레벨을 가지고 결정된다.

     어플리케이션을 작성하기전 어떤 로거를 사용해야 할지 정해야 한다.
     ex) static Logger logger = Logger.getLogger(SimpleLog.class);

     [참고] Commons-Logging 는 레퍼클래스도 존재함

② Appender : 로그를 출력하는 위치

     전달된 로깅 메세지를 파일에다 기록할 것인지, 콘솔에 출력할 것인지
     아니면 DB에 저장할 것인지 매개체 역활을 합니다.

     Log4J API문서의 XXXAppender로 끝나는 클래스들의 이름을 보면,
     출력위치를 어느정도 짐작할 수 있다.

     http://logging.apache.org/log4j/docs/api/index.html

③ Layout : Appender의 출력포맷

  Appender가 어디에 출력할 것인지 결정했다면 어떤 형식으로 출력할 것이지
  출력 layout을 결졍합니다.

  일자, 시간, 클래스명등 여러가지 정보를 선택하여 로그정보내용으로 지정할 수 있다.
  자세한 패턴은 아래의 클래스정보를 살펴보면 알수있다.

  ※ Layout의 종류

      1) DateLayout
      2) HTMLLayout
      3) PatternLayout ( 일반적으로 PatternLayout을 사용하는 것이 디버깅에 가장 적합함 )
      4) SimpleLayout
      5) XMLLayout

2. LOG4J 로깅 레벨

log4j는 다양한 로깅레벨을 지원합니다.

① FATAL : 가장 크리티컬한 에러가 일어 났을 때 사용합니다.
② ERROR : 일반 에러가 일어 났을 때 사용합니다.
③ WARN : 에러는 아니지만 주의할 필요가 있을 때 사용합니다.
④ INFO : 일반 정보를 나타낼 때 사용합니다.
⑤ DEBUG : 일반 정보를 상세히 나타낼 때 사용합니다.

레벨을 설정하면 그 이상의 레벨만 로깅하게 된다.
예를 들어 INFO로 설정한 경우 INFO, WARN, ERROR, FATAL이 로깅된다.

3. 샘플코드

파일명 : TestServlet.java

import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TestServlet extends HttpServlet {
    static Logger logger = Logger.getLogger(TestServlet.class);

    public void init(ServletConfig config) throws ServletException {
         super.init(config);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         try {
              ...
              logger.info("Hellow World~");
              ...

          } catch (Exception e) {
              logger.error("Error at TestServlet", e);
          }
     }
}

4. LOG4J 설정

log4j.properties
를 만들어 /WEB-INF/classes 밑에 놓으세요

파일명 : log4j.properties

log4j.rootLogger=INFO, stdout, rolling
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=output.log
# 기본 경로는 %CATALINA_HOME%bin 디렉토리이다.
# 경로를 바꾸고 싶을 때에는 다음과 같이 C:/web/WEB-INF/logs/ssg.log 바꾼다.
log4j.appender.file.Append=true
log4j.appender.file.MaxFileSize=500KB
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n

** 설명

#최상위 카테고리에 INFO로 레벨 설정 및 appender로 stdout, file을 정의
log4j.rootLogger=INFO, stdout, file

#stdout 어펜더는 콘솔에 뿌리겠다는 정의
log4j.appender.stdout=org.apache.log4j.ConsoleAppender

#stdout 어펜더는 patternlayout을 사용하겠다는 정의
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

#페턴은 다음과 같이 포맷팅 하겠다는 것을 정의
log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n

#역시나 rolling 어펜더는 파일로 처리한다라고 정의
log4j.appender.rolling=org.apache.log4j.RollingFileAppender

#로그 파일 이름은 output.log
log4j.appender.rolling.File=output.log

#true면 톰캣을 내렸다 올려도 파일이 리셋되지 않습니다.
log4j.appender.rolling.Append=true

#파일 최대 사이즈는 500KB로 설정
log4j.appender.rolling.MaxFileSize=500KB

#파일 포맷은 output.log.2005-03-10 으로 관리하겠다고 정의
log4j.appender.rolling.DatePattern='.'yyyy-MM-dd

#역시나 rolling 어펜더는 패턴 레이아웃을 사용하겠다고 정의
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout

#rolling 어펜더는 패턴 레이아웃 포맷
log4j.appender.rolling.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n

☆☆☆☆☆☆☆☆☆☆☆☆☆
log4j.xml 관련 내용 추가 예정
☆☆☆☆☆☆☆☆☆☆☆☆☆


5. 설정 포맷

① 로그파일명 포맷 (DatePattern)

로그파일명 포맷입니다. 날짜, 시간 및 분단위로까지 로그 파일을 분리할 수 있습니다.
  
   ※ 형식 설명
      '.'yyyy-MM 매달 첫번째날에 로그파일을 변경합니다 
      '.'yyyy-ww 매주의 시작시 로그파일을 변경합니다.  
      '.'yyyy-MM-dd 매일 자정에 로그파일을 변경합니다. 
      '.'yyyy-MM-dd-a 자정과 정오에 로그파일을 변경합니다. 
      '.'yyyy-MM-dd-HH 매 시간의 시작마다 로그파일을 변경합니다.
      '.'yyyy-MM-dd-HH-mm 매분마다 로그파일을 변경합니다. 

② PatternLayout 포맷

로그자체를 어떤 포맷으로 남길지 결정합니다.
layout에는 HTMLLayout, PatternLayout, SimpleLayout, XMLLayout등이 있으며
PatternLayout이 일반적으로 가장 많이 쓰입니다.

형식 설명
%p debug, info, warn, error, fatal 등의 priority 가 출력된다.
%m 로그내용이 출력됩니다
%d 로깅 이벤트가 발생한 시간을 기록합니다.
포맷은 %d{HH:mm:ss, SSS}, %d{yyyy MMM dd HH:mm:ss, SSS}같은 형태로 사용하며 SimpleDateFormat에 따른 포맷팅을 하면 된다
%t 로그이벤트가 발생된 쓰레드의 이름을 출력합니다.
%% % 표시를 출력하기 위해 사용한다.
%n 플랫폼 종속적인 개행문자가 출력된다. \r\n 또는 \n 일것이다.
%c 카테고리를 표시합니다
예) 카테고리가 a.b.c 처럼 되어있다면 %c{2}는 b.c가 출력됩니다.
%C 클래스명을 포시합니다.
예) 클래스구조가 org.apache.xyz.SomeClass 처럼 되어있다면 %C{2}는 xyz.SomeClass 가 출력됩니다
%F 로깅이 발생한 프로그램 파일명을 나타냅니다.
%l 로깅이 발생한 caller의 정보를 나타냅니다
%L 로깅이 발생한 caller의 라인수를 나타냅니다
%M 로깅이 발생한 method 이름을 나타냅니다.
%r 어플리케이션 시작 이후 부터 로깅이 발생한 시점의 시간(milliseconds)
%x 로깅이 발생한 thread와 관련된 NDC(nested diagnostic context)를 출력합니다.
%X 로깅이 발생한 thread와 관련된 MDC(mapped diagnostic context)를 출력합니다.

예시) (같은 색끼리 보시면 됩니다)

위의 test.jsp를 다음 포맷으로 출력해본다면
[%c] [%C] [%d] [%F] [%l] [%L] [%m] [%M] [%n] [%p] [%r] [%t] [%x] [%X]는 다음과 같다

[test.jsp] [org.apache.jsp.test_jsp] [2005-03-10 12:37:23,561] [test_jsp.java] [org.apache.jsp.test_jsp._jspService(test_jsp.java:64)] [64] [fatal!!] [_jspService] [개행] [FATAL] [765567] [http-8080-Processor25] [] []


[출처 : http://www.ssial.com/162]
가. 이해 및 유틸

- 시스템 시간에 대한 이해
- 날짜 계산 종합 유틸리티

나. 응용팁

시스템의 밀리초 구하기.(국제표준시각(UTC, GMT) 1970/1/1/0/0/0 으로부터 경과한 시각)
------------------------------------------------------------------
// 밀리초 단위(*1000은 1초), 음수이면 이전 시각
long time = System.currentTimeMillis ( );
System.out.println ( time.toString ( ) );
------------------------------------------------------------------

현재 시각을 가져오기.
------------------------------------------------------------------
Date today = new Date ();
System.out.println ( today );

결과 : Sat Jul 12 16:03:00 GMT+01:00 2000
------------------------------------------------------------------

경과시간(초) 구하기
------------------------------------------------------------------
long time1 = System.currentTimeMillis ();
long time2 = System.currentTimeMillis ();
system.out.println ( ( time2 - time1 ) / 1000.0 );
------------------------------------------------------------------

Date를 Calendar로 맵핑시키기
------------------------------------------------------------------
Date d = new Date ( );
Calendar c = Calendar.getInstance ( );
c.setTime ( d );
------------------------------------------------------------------

날짜(년/월/일/시/분/초) 구하기
------------------------------------------------------------------
import java.util.*;
import java.text.*;

SimpleDateFormat formatter = new SimpleDateFormat ( "yyyy.MM.dd HH:mm:ss", Locale.KOREA );
Date currentTime = new Date ( );
String dTime = formatter.format ( currentTime );
System.out.println ( dTime );
------------------------------------------------------------------

날짜(년/월/일/시/분/초) 구하기2
------------------------------------------------------------------
GregorianCalendar today = new GregorianCalendar ( );

int year = today.get ( today.YEAR );
int month = today.get ( today.MONTH ) + 1;
int yoil = today.get ( today.DAY_OF_MONTH );

GregorianCalendar gc = new GregorianCalendar ( );

System.out.println ( gc.get ( Calendar.YEAR ) );
System.out.println ( String.valueOf ( gc.get ( Calendar.MONTH ) + 1 ) );
System.out.println ( gc.get ( Calendar.DATE ) );
System.out.println ( gc.get ( DAY_OF_MONTH ) );
------------------------------------------------------------------

날짜(년/월/일/시/분/초) 구하기3
------------------------------------------------------------------
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.KOREA);
Calendar cal = Calendar.getInstance(Locale.KOREA);
nal = df.format(cal.getTime());
------------------------------------------------------------------

- 표준시간대를 지정하고 날짜를 가져오기.
------------------------------------------------------------------
TimeZone jst = TimeZone.getTimeZone ("JST");
Calendar cal = Calendar.getInstance ( jst ); // 주어진 시간대에 맞게 현재 시각으로 초기화된 GregorianCalender 객체를 반환.// 또는 Calendar now = Calendar.getInstance(Locale.KOREA);
System.out.println ( cal.get ( Calendar.YEAR ) + "년 " + ( cal.get ( Calendar.MONTH ) + 1 ) + "월 " + cal.get ( Calendar.DATE ) + "일 " + cal.get ( Calendar.HOUR_OF_DAY ) + "시 " +cal.get ( Calendar.MINUTE ) + "분 " + cal.get ( Calendar.SECOND ) + "초 " );

결과 : 2000년 8월 5일 16시 16분 47초
------------------------------------------------------------------

영어로된 날짜를 숫자로 바꾸기
------------------------------------------------------------------
Date myDate = new Date ( "Sun,5 Dec 1999 00:07:21" );
System.out.println ( myDate.getYear ( ) + "-" + myDate.getMonth ( ) + "-" + myDate.getDay ( ) );
------------------------------------------------------------------

"Sun, 5 Dec 1999 00:07:21"를 "1999-12-05"로 바꾸기
------------------------------------------------------------------
SimpleDateFormat formatter_one = new SimpleDateFormat ( "EEE, dd MMM yyyy hh:mm:ss",Locale.ENGLISH );
SimpleDateFormat formatter_two = new SimpleDateFormat ( "yyyy-MM-dd" );

String inString = "Sun, 5 Dec 1999 00:07:21";

ParsePosition pos = new ParsePosition ( 0 );
Date frmTime = formatter_one.parse ( inString, pos );
String outString = formatter_two.format ( frmTime );

System.out.println ( outString );
------------------------------------------------------------------

숫자 12자리를, 다시 날짜로 변환하기
------------------------------------------------------------------
Date conFromDate = new Date();
long ttl = conFromDate.parse ( "Dec 25, 1997 10:10:10" );
System.out.println ( ttl ); //예 938291839221

Date today = new Date ( ttl );
DateFormat format = DateFormat.getDateInstance ( DateFormat.FULL,Locale.US );
String formatted = format.format ( today );
System.out.println ( formatted );
------------------------------------------------------------------

특정일로부터 n일 만큼 이동한 날짜 구하기
------------------------------------------------------------------
특정일의 시간을 long형으로 읽어온다음..
날짜*24*60*60*1000 을 계산하여.
long형에 더해줍니다.
그리고 나서 Date클래스와 Calender클래스를 이용해서 날짜와 시간을 구하면 됩니다
------------------------------------------------------------------

특정일에서 일정 기간후의 날짜 구하기2
------------------------------------------------------------------
//iDay 에 입력하신 만큼 빼거나 더한 날짜를 반환 합니다.
import java.util.*;

public String getDate ( int iDay )
{
Calendar temp=Calendar.getInstance ( );
StringBuffer sbDate=new StringBuffer ( );

temp.add ( Calendar.DAY_OF_MONTH, iDay );

int nYear = temp.get ( Calendar.YEAR );
int nMonth = temp.get ( Calendar.MONTH ) + 1;
int nDay = temp.get ( Calendar.DAY_OF_MONTH );

sbDate.append ( nYear );
if ( nMonth < 10 )
sbDate.append ( "0" );
sbDate.append ( nMonth );
if ( nDay < 10 )
sbDate.append ( "0" );
sbDate.append ( nDay );

return sbDate.toString ( );
}
------------------------------------------------------------------

현재날짜에서 2달전의 날짜를 구하기
------------------------------------------------------------------
Calendar cal = Calendar.getInstance ( );//오늘 날짜를 기준으루..
cal.add ( cal.MONTH, -2 ); //2개월 전....
System.out.println ( cal.get ( cal.YEAR ) );
System.out.println ( cal.get ( cal.MONTH ) + 1 );
System.out.println ( cal.get ( cal.DATE ) );
------------------------------------------------------------------

달에 마지막 날짜 구하기
------------------------------------------------------------------
for ( int month = 1; month <= 12; month++ )
{
GregorianCalendar cld = new GregorianCalendar ( 2001, month - 1, 1 );
System.out.println ( month + "/" + cld.getActualMaximum ( Calendar.DAY_OF_MONTH ) );
}
------------------------------------------------------------------

해당하는 달의 마지막 일 구하기
------------------------------------------------------------------
GregorianCalendar today = new GregorianCalendar ( );
int maxday = today.getActualMaximum ( ( today.DAY_OF_MONTH ) );
System.out.println ( maxday );
------------------------------------------------------------------

특정일을 입력받아 해당 월의 마지막 날짜를 구하는 간단한 예제.(달은 -1 해준다.)...윤달 30일 31일 알아오기.
------------------------------------------------------------------
Calendar cal = Calendar.getInstance ( );
cal.set ( Integer.parseInt ( args[0] ), Integer.parseInt ( args [1] ) - 1, Integer.parseInt ( args [2] ) );
SimpleDateFormat dFormat = new SimpleDateFormat ( "yyyy-MM-dd" );
System.out.println ( "입력 날짜 " + dFormat.format ( cal.getTime ( ) ) );
System.out.println ( "해당 월의 마지막 일자 : " + cal.getActualMaximum ( Calendar.DATE ) );
------------------------------------------------------------------

해당월의 실제 날짜수 구하기 ( 1999년 1월달의 실제 날짜수를 구하기 )
------------------------------------------------------------------
Calendar calendar = Calendar.getInstance ( );
calendar.set ( 1999, 0, 1 );
int maxDays = calendar.getActualMaximum ( Calendar.DAY_OF_MONTH );
------------------------------------------------------------------

어제 날짜 구하기
------------------------------------------------------------------
오늘날짜를 초단위로 구해서 하루분을 빼주고 다시
셋팅해주면 쉽게 구할수 있죠..
setTime((기준일부터 오늘까지의 초를 구함) - 24*60*60)해주면 되겠죠..
------------------------------------------------------------------

어제 날짜 구하기2
------------------------------------------------------------------
import java.util.*;

public static Date getYesterday ( Date today )
{
if ( today == null )
throw new IllegalStateException ( "today is null" );
Date yesterday = new Date ( );
yesterday.setTime ( today.getTime ( ) - ( (long) 1000 * 60 * 60 * 24 ) );

return yesterday;
}
------------------------------------------------------------------

내일 날짜 구하기
------------------------------------------------------------------
Date today = new Date ( );
Date tomorrow = new Date ( today.getTime ( ) + (long) ( 1000 * 60 * 60 * 24 ) );
------------------------------------------------------------------

내일 날짜 구하기2
------------------------------------------------------------------
Calendar today = Calendar.getInstance ( );
today.add ( Calendar.DATE, 1 );
Date tomorrow = today.getTime ( );
------------------------------------------------------------------

오늘날짜에서 5일 이후 날짜를 구하기
------------------------------------------------------------------
Calendar cCal = Calendar.getInstance();
c.add(Calendar.DATE, 5);
------------------------------------------------------------------

날짜에 해당하는 요일 구하기
------------------------------------------------------------------
//DAY_OF_WEEK리턴값이 일요일(1), 월요일(2), 화요일(3) ~~ 토요일(7)을 반환합니다.
//아래 소스는 JSP일부입니다.
import java.util.*;

Calendar cal= Calendar.getInstance ( );
int day_of_week = cal.get ( Calendar.DAY_OF_WEEK );
if ( day_of_week == 1 )
m_week="일요일";
else if ( day_of_week == 2 )
m_week="월요일";
else if ( day_of_week == 3 )
m_week="화요일";
else if ( day_of_week == 4 )
m_week="수요일";
else if ( day_of_week == 5 )
m_week="목요일";
else if ( day_of_week == 6 )
m_week="금요일";
else if ( day_of_week == 7 )
m_week="토요일";

오늘은 : 입니다.
------------------------------------------------------------------

콤보박스로 선택된 날짜(예:20001023)를 통해 요일을 영문으로 가져오기
------------------------------------------------------------------
//gc.get(gc.DAY_OF_WEEK); 하면 일요일=1, 월요일=2, ..., 토요일=7이 나오니까,
//요일을 배열로 만들어서 뽑아내면 되겠죠.
GregorianCalendar gc=new GregorianCalendar ( 2000, 10 - 1 , 23 );
String [] dayOfWeek = { "", "Sun", "Mon", .... , "Sat" };
String yo_il = dayOfWeek ( gc.get ( gc.DAY_OF_WEEK ) );
------------------------------------------------------------------

두 날짜의 차이를 일수로 구하기
------------------------------------------------------------------
각각의 날짜를 Date형으로 만들어서 getTime()하면
long으로 값이 나오거든요(1970년 1월 1일 이후-맞던가?- 1/1000 초 단위로..)
그러면 이값의 차를 구해서요. (1000*60*60*24)로 나누어 보면 되겠죠.
------------------------------------------------------------------

두 날짜의 차이를 일수로 구하기2
------------------------------------------------------------------
import java.io.*;
import java.util.*;

Date today = new Date ( );
Calendar cal = Calendar.getInstance ( );
cal.setTime ( today );// 오늘로 설정.

Calendar cal2 = Calendar.getInstance ( );
cal2.set ( 2000, 3, 12 ); // 기준일로 설정. month의 경우 해당월수-1을 해줍니다.

int count = 0;
while ( !cal2.after ( cal ) )
{
count++;
cal2.add ( Calendar.DATE, 1 ); // 다음날로 바뀜

System.out.println ( cal2.get ( Calendar.YEAR ) + "년 " + ( cal2.get ( Calendar.MONTH ) + 1 ) + "월 " + cal2.get ( Calendar.DATE ) + "일" );
}

System.out.println ( "기준일로부터 " + count + "일이 지났습니다." );
------------------------------------------------------------------

두 날짜의 차이를 일수로 구하기3
------------------------------------------------------------------
import java.io.*;
import java.util.*;

public class DateDiff
{
public static int GetDifferenceOfDate ( int nYear1, int nMonth1, int nDate1, int nYear2, int nMonth2, int nDate2 )
{
Calendar cal = Calendar.getInstance ( );
int nTotalDate1 = 0, nTotalDate2 = 0, nDiffOfYear = 0, nDiffOfDay = 0;

if ( nYear1 > nYear2 )
{
for ( int i = nYear2; i < nYear1; i++ )
{
cal.set ( i, 12, 0 );
nDiffOfYear += cal.get ( Calendar.DAY_OF_YEAR );
}
nTotalDate1 += nDiffOfYear;
}
else if ( nYear1 < nYear2 )
{
for ( int i = nYear1; i < nYear2; i++ )
{
cal.set ( i, 12, 0 );
nDiffOfYear += cal.get ( Calendar.DAY_OF_YEAR );
}
nTotalDate2 += nDiffOfYear;
}

cal.set ( nYear1, nMonth1-1, nDate1 );
nDiffOfDay = cal.get ( Calendar.DAY_OF_YEAR );
nTotalDate1 += nDiffOfDay;

cal.set ( nYear2, nMonth2-1, nDate2 );
nDiffOfDay = cal.get ( Calendar.DAY_OF_YEAR );
nTotalDate2 += nDiffOfDay;

return nTotalDate1-nTotalDate2;
}

public static void main ( String args[] )
{
System.out.println ( "" + GetDifferenceOfDate (2000, 6, 15, 1999, 8, 23 ) );
}
}
------------------------------------------------------------------

파일에서 날짜정보를 가져오기
------------------------------------------------------------------
File f = new File ( directory, file );

Date date = new Date ( f.lastModified ( ) );
Calendar cal = Calendar.getInstance ( );
cal.setTime ( date );

System.out.println("Year : " + cal.get(Calendar.YEAR));
System.out.println("Month : " + (cal.get(Calendar.MONTH) + 1));
System.out.println("Day : " + cal.get(Calendar.DAY_OF_MONTH));
System.out.println("Hours : " + cal.get(Calendar.HOUR_OF_DAY));
System.out.println("Minutes : " + cal.get(Calendar.MINUTE));
System.out.println("Second : " + cal.get(Calendar.SECOND));
------------------------------------------------------------------

날짜형식으로 2000-01-03으로 처음에 인식을 시킨후
7일씩 증가해서 1년정도의 날짜를 출력해 주고 싶은데요.
------------------------------------------------------------------
SimpleDateFormat sdf = new SimpleDateFormat ( "yyyy-mm-dd" );
Calendar c = Calendar.getInstance ( );

for ( int i = 0; i < 48; i++ )
{
c.clear ( );
c.set ( 2000, 1, 3 - ( i * 7 ) );
java.util.Date d = c.getTime ( );
String thedate = sdf.format ( d );
System.out.println ( thedate );
}
------------------------------------------------------------------

쓰레드에서 날짜 바꾸면 죽는 문제
------------------------------------------------------------------
Main화면에 날짜와시간이Display되는 JPanel이 있습니다.
date로 날짜와 시간을 변경하면 Main화면의 날짜와 시간이 Display되는 Panel에
변경된 날짜가 Display되지 않고 Main화면이 종료되어 버립니다.

문제소스:
public void run ( )
{
while ( true )
{
try{
timer.sleep ( 60000 );
}
catch ( InterruptedException ex ) { }

lblTimeDate.setText ( fGetDateTime ( ) );
repaint ( );
}
}

public String fGetDateTime ( )
{
final int millisPerHour = 60 * 60 * 1000;
String DATE_FORMAT = "yyyy / MM / dd HH:mm";
SimpleDateFormat sdf = new SimpleDateFormat ( DATE_FORMAT );
SimpleTimeZone timeZone = new SimpleTimeZone ( 9 * millisPerHour, "KST" );
sdf.setTimeZone ( timeZone );

long time = System.currentTimeMillis ( );
Date date = new Date ( time );
return sdf.format ( date );
}

해답:
// 날짜와 요일 구한다. timezone 으로 날짜를 다시 셋팅하시면 됨니다.
public String getDate ( )
{
Date now = new Date ( );
SimpleDateFormat sdf4 = new SimpleDateFormat ( "yyyy/MM/dd HH:mm EE" );
sdf4.setTimeZone ( TimeZone.getTimeZone ( "Asia/Seoul" ) );

return sdf4.format ( now );
}
------------------------------------------------------------------

날짜와 시간이 유효한지 검사하려면...?
------------------------------------------------------------------
import java.util.*;
import java.text.*;

public class DateCheck
{
boolean dateValidity = true;

DateCheck ( String dt )
{
try
{
DateFormat df = DateFormat.getDateInstance ( DateFormat.SHORT );
df.setLenient ( false );
Date dt2 = df.parse ( dt );
}
catch ( ParseException e ) { this.dateValidity = false; }
catch ( IllegalArgumentException e ) { this.dateValidity = false; }
}

public boolean datevalid ( )
{
return dateValidity;
}

public static void main ( String args [] )
{
DateCheck dc = new DateCheck ( "2001-02-28" );
System.out.println ( " 유효한 날짜 : " + dc.datevalid ( ) );
}
}
------------------------------------------------------------------

두 날짜 비교하기(아래보다 정확)
------------------------------------------------------------------
그냥 날짜 두개를 long(밀리 세컨드)형으로 비교하시면 됩니다...

이전의 데이타가 date형으로 되어 있다면, 이걸 long형으로 변환하고.
현재 날짜(시간)은 System.currentTimeMillis()메소드로 읽어들이고,
두수(long형)를 연산하여 그 결과 값으로 비교를 하시면 됩니다.

만약 그 결과값이 몇시간 혹은 며칠차이가 있는지를 계산할려면,
결과값을 Calender의 setTimeInMillis(long millis) 메소드를 이용해
설정한다음 각각의 날짜나 시간을 읽어오시면 됩니다
------------------------------------------------------------------

두 날짜 비교하기2
------------------------------------------------------------------
//Calendar를 쓸 경우 데이타의 원본을 고치기 때문에 clone()을 사용하여
//복사한 후에 그 복사본을 가지고 비교한다
import java.util.*;
import java.util.Calendar.*;
import java.text.SimpleDateFormat;

public class DayComparisonTest
{
public static void main(String args[])
{
Calendar cal = Calendar.getInstance();
SimpleDateFormat dateForm = new SimpleDateFormat("yyyy-MM-dd");

Calendar aDate = Calendar.getInstance(); // 비교하고자 하는 임의의 날짜
aDate.set(2001, 0, 1);

Calendar bDate = Calendar.getInstance(); // 이것이 시스템의 날짜

// 여기에 시,분,초를 0으로 세팅해야 before, after를 제대로 비교함
aDate.set( Calendar.HOUR_OF_DAY, 0 );
aDate.set( Calendar.MINUTE, 0 );
aDate.set( Calendar.SECOND, 0 );
aDate.set( Calendar.MILLISECOND, 0 );

bDate.set( Calendar.HOUR_OF_DAY, 0 );
bDate.set( Calendar.MINUTE, 0 );
bDate.set( Calendar.SECOND, 0 );
bDate.set( Calendar.MILLISECOND, 0 );


if (aDate.after(bDate)) // aDate가 bDate보다 클 경우 출력
System.out.println("시스템 날짜보다 뒤일 경우 aDate = " + dateForm.format(aDate.getTime()));
else if (aDate.before(bDate)) // aDate가 bDate보다 작을 경우 출력
System.out.println("시스템 날짜보다 앞일 경우 aDate = " + dateForm.format(aDate.getTime()));
else // aDate = bDate인 경우
System.out.println("같은 날이구만");
}
}


[출처 : http://oybso.tistory.com/77]
 

+ Recent posts