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 - 자바 #
- 존재하는 숫자만 출력
- 오라클 0 - 자바 0
- 오라클보다 자바 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 지원)
- Collection
- List
- 1차원 배열처럼 생성, 사용
- 가변길이형
- 중복값 저장가능, 검색 기능이 있다
- 데이터가 순차적으로 입력됨
- List 인터페이스를 구현한 클래스 존재
- ArrayList, LinkedList, Vector
- Set
- 1차원 배열처럼 생성, 사용
- 가변길이형
- 중복값 저장불가, 검색 기능이 없다
- 검색 기능이 없어 Iterator(포인터 객체)를 사용
- 데이터가 순차적으로 입력되지 않음
- Set 인터페이스를 구현한 클래스 존재
- HashSet
- List
- Map
- 2차원 배열처럼 생성
- 가변길이형
- 키와 값의 쌍(entry)으로 이루어진 데이터형
- 2차원 배열이지만 열은 2개
- 키는 중복될 수 없음, 값은 중복가능
- 데이터(<K,V>, entry)가 순차적으로 입력되지 않음
- Map 인터페이스를 구현한 클래스 존재
- Hashtable, HashMap
- Map 인터페이스를 구현한 클래스 존재
Generic (<>)
- jdk 1.5부터 추가된 기능
- JCF에서 입력데이터형의 제한을 설정할 때 사용
- 단일 데이터형으로 구성
- Generic은 기본 데이터형으로는 설정할 수 없다
- 랩퍼클래스(wrapper class)로만 사용가능
- 기본형 데이터형을 객체로 생성하여 사용하는 클래스
- 값에 대해서 method를 호출하여 일을 더 할 수 있음
- 랩퍼클래스(wrapper class)로만 사용가능
- 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 모두 사용이 가능해짐
- 습득의 시간이 짧아진다.
- 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
- FIFO(First In First Out)
- 부모의 기능을 사용하지 않는다.
- 사용하면 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());
}