[JAVA] Collection
ArrayList<E>
※계층도 숙지 중요
Collection<E>
|__ List<E>
|__ ArrayList<E>, LinkedList<E>
* List 특징(ArrayList와 LinkedList의 공통점)
1. 중복 저장 허용
2. 저장 순서 유지 (인덱스 존재)
ArrayList vs LinkedList
- ArrayList 장점: 검색/조회 속도
n 번째 데이터에 대한 검색/조회 속도가 빠르다!
왜? 배열은 고정크기 연속된 메모리 공간에 있기 때문에
배열첨자연산 → 포인터 연산으로 매우 빠르게 n 번째 데이터 가져올 수 있다.
- ArrayList 단점: 삽입, 삭제
배열이니까 length(데이터 개수) 범위 내에서 운용.
사용하지 않는 데이터에 대해서도 메모리에 차지하고 있다.
동적으로 데이터가 늘어나고 줄어드는 것이 힘들다. → 데이터 삭제, 삽입이 어렵고, 시간이 많이 걸린다.
이유: 배열은 ‘연속된 메모리 공간’ 에 구축된 자료이니까.
- LinkedList 의 장점 - 삽입, 삭제, 추가 용이
* ArrayList:
1. 저장 용량을 늘리는 데 많은 시간 소요 - 단점
2. 데이터를 삭제하는 데 많은 연산 - 단점
3. 데이터 참조 매우 빠름 - 장점
* LinkedList:
1. 저장 용량을 늘리는 과정이 매우 간단 - 장점
2. 데이터를 삭제하는 과정이 간단 - 장점
3. 데이터 참조가 불편 - 단점
※ Vector<E> <-- ArrayList 와 비슷하나... ArrayList 추천.
※ 데이터 자료구조를 다룰시 각 자료구조에서 데이터에 대한 다음 동작들이 어떻게 되는지 주목하자
- C (Create) 생성
- R (Read) 조회
- U (Update) 수정
- D (Delete) 삭제
public class Collection01Main {
public static void main(String[] args) {
System.out.println("ArrayList<E>");
// ArrayList 선언 - ArrayList 인스턴스 생성
ArrayList<Integer> list1 = new ArrayList<Integer>();
// 데이터 추가(저장): add(element) 메소드 사용
// add(index, element) -> index 번째 삽입
list1.add(100);
list1.add(400);
list1.add(500);
list1.add(200);
list1.add(2, 700); // 2번째 삽입
list1.add(2, 200); // 2번째 삽입
// 데이터 참조(읽기, 검색): get(index) 메소드 사용
// size(): ArrayList의 크기를 반환(리턴)
System.out.println("size(): " + list1.size());
for(int i = 0; i < list1.size(); i++) {
System.out.println(i + ":" + list1.get(i));
}
// System.out.println(list1.get(100)); // IndexOutOfBoundsException
// 데이터 삭제: remove(index) 메소드 사용
list1.remove(2);
System.out.println("삭제후");
for(int i = 0; i < list1.size(); i++) {
System.out.println(i + ":" + list1.get(i));
}
// 데이터 수정: set(index, element) 메소드 사용
list1.set(2, 333);
System.out.println("수정후");
for(int i = 0; i < list1.size(); i++) {
System.out.println(i + ":" + list1.get(i));
}
// ArrayList 출력 방법
// 1) for
// 2) Enhanced-for 사용
// 3) Iterator(반복자) 사용
// 4) forEach() 사용
System.out.println("Enhanced for를 사용한 출력");
// Enhanced for 사용 가능
for(Integer e : list1) {
System.out.println(e);
}
System.out.println("Iterator 를 사용한 출력");
// Iterator(반복자) 사용법
// iterator() 메소드를 사용해서 인스턴스 생성
Iterator<Integer> itr = list1.iterator();
// hasNext(): iterator가 다음 원소를 가지고 있는 지(true/false)
// next(): 현재 iterator 위치의 원소를 값을 리턴하고,
// iterator의 위치를 다음 원소의 위치로 변경
while(itr.hasNext()) {
System.out.println(itr.next());
}
System.out.println("forEach() 를 사용한 출력");
// forEach() + functional interface
// Java8 부터 등장
list1.forEach(System.out::println);
System.out.println("toString() 사용");
// Collection<> 대부분은 toString() 오버라이딩 되어 있다.
System.out.println(list1);
System.out.println("\n프로그램 종료");
} // end main
} // end class
package com.lec.java.collection02;
import java.util.ArrayList;
import java.util.Iterator;
public class Collection02Main {
public static void main(String[] args) {
System.out.println("ArrayList 연습");
//TODO:
// String 타입을 담는 ArrayList를 만들고
// 5개 이상의 String을 저장하고
// set(), remove() 등의 메소드 사용하여
// 임의의 것을 수정, 삭제 도 해보시고
// 3가지 방식으로 출력해보세요
// for, Enhanced-for, Iterator
// String 타입을 저장할 수 있는 ArrayList 인스턴스 생성
ArrayList<String> list = new ArrayList<String>();
// 데이터 저장: add()
list.add("Java");
list.add("C++");
list.add("C#");
list.add("Python");
list.add("Swift");
// Scanner sc = new Scanner(System.in);
// System.out.println("5개 문자열을 입력해주세요");
// for(int i = 0; i < 5; i++) {
// list.add(sc.nextLine());
// }
// sc.close();
System.out.println("삽입(insertion) 도 add(i, 데이타) ");
list.add(2, "Python");
for(int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 데이터 검색: get(), size()
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 데이터 삭제: remove()
list.remove(1);
System.out.println("삭제:");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 데이터 수정: set()
list.set(2, "Object-C");
System.out.println("수정:");
// enhanced for
for (String lang : list) {
System.out.println(lang);
}
System.out.println("for 를 사용한 출력");
for(int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("Enhanced-for 를 사용한 출력");
for(String i : list) {
System.out.println(i);
}
// Iterator 사용
// ArrayList에 있는 iterator() 메소드를 사용해서 인스턴스 생성
System.out.println("Iterator 사용:");
Iterator<String> itr = list.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
System.out.println("\n프로그램 종료");
} // end main()
} // end class
package com.lec.java.collection03;
import java.util.ArrayList;
public class Collection03Main {
public static void main(String[] args) {
System.out.println("ArrayList 연습");
//TODO:
// Student 타입을 담는 ArrayList를 만드고
// 사용자로부터 3개의 Student 데이터 을 입력받아서
// 3가지 방법으로 출력해보세요.
// for, Enhanced-for, Iterator
ArrayList<Student> list = new ArrayList<Student>();
Score score1 = new Score(100, 90, 80);
Student stu1 = new Student(1, "김남주", score1);
list.add(stu1);
Score score2 = new Score(80, 100, 90);
Student stu2 = new Student(2, "김동혁", score2);
list.add(stu2);
Student stu3 = new Student(3, "김병기", new Score(80, 73, 36));
list.add(stu3);
for(Student s : list) {
System.out.println(s);
}
// 김동혁 학생의 정보 수정 (김동혁 학생이 List의 몇번째 저장되었는지 모른다고 하면?)
// id 값 -> 10
// 국어, 영어, 수학 -> 99, 88, 76
for(int i = 0; i < list.size(); i++) {
Student stu = list.get(i);
if("김동혁".equals(stu.getName())) {
stu.setId(10);
stu.getScore().setKorean(99);
stu.getScore().setEnglish(88);
stu.getScore().setMath(76);
}
}
// 수정후 출력
System.out.println("수정후");
for(Student s : list) {
System.out.println(s);
}
System.out.println("\n프로그램 종료");
} // end main()
} // end class
자료구조의 데이터들을 추출 하려면?
자료구조(data structure) 는 여러 자료(data) 들이 저장된 형태다.
특정 자료구조에 저장되어 있는 data 들을 추출하려면 어떻게 하나?
‘고민’해야 할 것들이 있다.
꺼내기 전까진 총 몇개의 자료가 담겨 있는지 당장 알수 없는 자료구조도 있다.
추출하는 순서는 어떻게 할것인가?
특히, 비선형 자료구조 의 경우, 추출순서는?
* iteration(순환), iterator (순환자)
일반적으로 자료구조에선, 저장된 데이터들을 ‘차례대로’ 추출하기 위해 순환자(iterator)를 구현하여 순환(iterate) 하면서 추출한다.
구현된 순환자(iterator) : 마치, 자료구조 안의 자료들을 일렬로 줄세워 놓고, 부를 때마다 다음(next) 자료들이 추출되게 동작하는 존재다. 다 뽑아내기 위해선, 더 이상 자료들이 없을때까지 (hasNext?). 뽑아내면 된다.
Set, HashSet<E>
Collection<E>
|__ Set<E>
|__ HashSet<E>, TreeSet<E>
* Set:
1. 자료의 중복 저장이 허용되지 않는다. (hashCode() 값의 중복여부!)
2. 저장 순서가 유지되지 않는다.(인덱스 없다.)
(예) {1, 2, 3} = {1, 1, 2, 2, 3} : 중복 저장이 안되기 때문에 같은 Set
(예) {1, 2, 3} = {1, 3, 2}: 저장 순서가 중요하지 않기 때문에 같은 Set
* HashSet: 매우 빠른 검색 속도를 제공
(※ HashXXX ← '검색속도 향상'을 쓰는 자료구조 입니다)
데이터 검색:
Set은 인덱스가 없기 때문에 get() 메소드를 제공하지 않습니다.
데이터 검색을 위해서는 Iterator를 사용해야 함
데이터 삭제
remove(element): Set에 있는 element를 찾아서 삭제
element 있다면 삭제 후 true를 리턴
element 없다면 false 리턴
Set 자료형 데이터 변경을 할 수 있는 set() 메소드를 제공하지 않습니다.
삭제(remove) 후 추가(add)하면 변경하는 효과
public class Collection06Main {
public static void main(String[] args) {
System.out.println("HashSet 클래스");
// Integer 타입을 저장할 수 있는 HashSet 인스턴스 생성
HashSet<Integer> set = new HashSet<Integer>();
// 데이터 저장: add()
set.add(100);
set.add(200);
set.add(300);
set.add(100);
set.add(400);
set.add(500);
set.add(1);
set.add(2);
// HashSet의 크기: size()
System.out.println("Set의 크기: " + set.size());
// Set은 중복 저장을 허용하지 않는다.
// 데이터 검색:
// Set은 인덱스가 없기 때문에 get() 메소드를 제공하지 않습니다.
// 데이터 검색을 위해서는 Iterator를 사용해야 함
System.out.println();
Iterator<Integer> itr = set.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
// ↑ 출력결과를 통해 Set 은 저장된 순서가 유지안됨을 알수 있다.
// 데이터 삭제
// remove(element): Set에 있는 element를 찾아서 삭제
// element 있다면 삭제 후 true를 리턴
// element 없다면 false 리턴
// TODO
System.out.println();
System.out.println("삭제 후:");
System.out.println("삭제결과: " + set.remove(2)); // index 2번째를 삭제하는게 아니다!. 데이터 2 를 삭제하는 것이다!
System.out.println("삭제결과: " + set.remove(2));
itr = set.iterator(); // 한번 사용한 iterator 는 다시 사용할수 없다. (새로 생성해야 한다)
while(itr.hasNext()) {
System.out.println(itr.next());
}
// Set 자료형 데이터 변경을 할 수 있는 set() 메소드를 제공하지 않습니다.
// 삭제(remove) 후 추가(add)하면 변경하는 효과
// TODO : 500 -> 555 로 변경하고 싶다면?
set.remove(500);
set.add(555);
System.out.println("변경후");
itr = set.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
// enhanced-for 사용
System.out.println();
System.out.println("Enhanced for 사용 출력");
for(Integer x : set) {
System.out.println(x);
}
// forEach() 메소드 사용
System.out.println();
System.out.println("forEach() 사용 출력");
// TODO
// toString() 제공됨
System.out.println();
System.out.println(set);
System.out.println("\n프로그램 종료");
} // end main()
} // end class
package com.lec.java.collection07;
import java.util.HashSet;
import java.util.Iterator;
public class Collection07Main {
public static void main(String[] args) {
System.out.println("HashSet 연습");
// TODO
// String 타입을 저장할 수 있는 HashSet 를 생성하고
// 5개 이상의 데이터는 저장, 수정, 삭제 등의 동작을 해보고,
// iterator, enhanced-for 문을 사용해서 출력해보기
HashSet<String> set = new HashSet<String>();
// 데이터 저장
System.out.println("add 결과: " + set.add("One"));
System.out.println("add 결과: " + set.add("Two"));
System.out.println("add 결과: " + set.add("Three"));
System.out.println("add 결과: " + set.add("Four"));
System.out.println("add 결과: " + set.add("Five"));
System.out.println("add 결과: " + set.add("Two"));
System.out.println("add 결과: " + set.add("Three"));
System.out.println();
System.out.println("데이터 저장");
System.out.println("데이터 개수: " + set.size());
System.out.println();
// 데이터 검색 - Iterator 사용
Iterator<String> itr = set.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
System.out.println();
// 데이터 삭제
set.remove("Five");
System.out.println("삭제 후:");
itr = set.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
System.out.println();
// enhanced for는 인덱스가 필요 없는 for문이기 때문에
// Set 타입의 자료형에서도 사용 가능
System.out.println("enhanced for 사용");
for (String str : set) {
System.out.println(str);
}
System.out.println("\n프로그램 종료");
} // end main()
} // end class
* TreeSet
Collection<E>
|__ Set<E>
|__ HashSet<E>, TreeSet<E>
TreeSet : 데이터가 정렬된 상태로 저장(오름차순, 내림차순)
(※ TreeXXX ← 주로 '정렬'에 특화된 자료구조 입니다)
package com.lec.java.collection09;
import java.util.Iterator;
import java.util.TreeSet;
/* TreeSet
Collection<E>
|__ Set<E>
|__ HashSet<E>, TreeSet<E>
TreeSet: 데이터가 정렬된 상태로 저장(오름차순, 내림차순)
(※ TreeXXX ← 주로 '정렬'에 특화된 자료구조 입니다)
*/
public class Collection09Main {
public static void main(String[] args) {
System.out.println("TreeSet 클래스");
// Integer 타입을 저장할 수 있는 TreeSet 인스턴스 생성
TreeSet<Integer> tset = new TreeSet<Integer>();
// 데이터 저장 : add()
tset.add(11);
tset.add(2);
tset.add(14);
tset.add(1);
tset.add(7);
tset.add(15);
tset.add(5);
tset.add(8);
// 데이터 검색 - Iterator 사용
// TreeSet인 경우에 iterator() 메소드 오름차순 정렬
System.out.println("오름차순:");
Iterator<Integer> itr = tset.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
System.out.println();
System.out.println("내림차순:");
// 내림차순 Iterator : descendingIterator() 사용
itr = tset.descendingIterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
// enhanced for
System.out.println();
System.out.println("enhanced for");
for(Integer num: tset) {
System.out.println(num);
}
// 삭제 등의 동작은 HashSet 과 동일.
System.out.println("\n프로그램 종료");
} // end main()
} // end class
package com.lec.java.collection10;
import java.util.Iterator;
import java.util.TreeSet;
public class Collection10Main {
public static void main(String[] args) {
System.out.println("TreeSet 연습");
// String 타입을 저장할 수 있는 TreeSet 인스턴스 생성
// 5개 이상의 데이터를 저장해보고
// 오름차순, 내림차순으로 출력해보기
TreeSet<String> tset = new TreeSet<String>();
// 데이터 저장
tset.add("qwerty");
tset.add("asdf");
tset.add("zxcv");
tset.add("bnm");
tset.add("jkl");
tset.add("AaAa 1"); // 1.
tset.add("aaaa 2"); // 2.
tset.add("aAaA 3"); // 3.
tset.add("AAaa 4"); // 4.
tset.add("aaAA 5"); // 5.
// 오름 차순 결과 4 1 3 5 2
// 데이터 검색 - Iterator(오름차순, 내림차순)
Iterator<String> itr = tset.iterator();
System.out.println("오름차순:");
while (itr.hasNext()) {
System.out.println(itr.next());
}
System.out.println();
System.out.println("내림차순:");
Iterator<String> itr2 = tset.descendingIterator();
while (itr2.hasNext()) {
System.out.println(itr2.next());
}
System.out.println("\n프로그램 종료");
} // end main
} // end class
* Map<K, V>, HashMap<K, V>
Collection<E>
|__ List<E>, Set<E>
List<E>
|__ ArrayList<E>, LinkedList<E>
Set<E>
|__ HashSet<E>, TreeSet<E>
Map<K, V>
|__ HashMap<K, V>, TreeMap<K, V>
* Map: key-value 저장 방식의 자료 구조
1. key는 중복되지 않는 값만 허용
2. value는 같더라도 key 값이 다르면 저장 가능
3. 검색, 수정, 삭제를 할 때 key를 사용
package com.lec.java.collection11;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/* Map<K, V>, HashMap<K, V>
Collection<E>
|__ List<E>, Set<E>
List<E>
|__ ArrayList<E>, LinkedList<E>
Set<E>
|__ HashSet<E>, TreeSet<E>
Map<K, V>
|__ HashMap<K, V>, TreeMap<K, V>
Map: key-value 저장 방식의 자료 구조
1. key는 중복되지 않는 값만 허용
2. value는 같더라도 key 값이 다르면 저장 가능
3. 검색, 수정, 삭제를 할 때 key를 사용
*/
public class Collection11Main {
public static void main(String[] args) {
System.out.println("HashMap 클래스");
// HashMap 인스턴스 생성
// Key - Integer 타입
// Value - String 타입
HashMap<Integer, String> hmap =
new HashMap<Integer, String>();
// 데이터 저장: put() 메소드 사용
System.out.println("put 결과" + hmap.put(1, "최진형")); // 생성
System.out.println("put 결과" + hmap.put(2, "최민영"));
System.out.println("put 결과" + hmap.put(3, "정은선"));
System.out.println("put 결과" + hmap.put(1, "조은이")); // 수정
// 기존에 없던 key 값으로 put 하면 null 리턴하고
// 같은 키 값으로 데이터를 put하게 되면, 기존 값이 수정(replace)되고 기존 값을 리턴함
// 저장된 데이터 개수 확인 : size()
System.out.println("데이터 개수: " + hmap.size());
System.out.println();
// 데이터 읽기
// get(key) 사용해서 value 읽기
System.out.println(hmap.get(1)); // 조회
System.out.println(hmap.get(2));
System.out.println(hmap.get(3));
// 데이터 삭제
// remove(key) : 삭제된 value 리턴
// 없는 key 를 삭제하면 null 리턴
System.out.println("삭제: " + hmap.remove(2)); // 삭제
System.out.println("삭제: " + hmap.remove(2));
// 방법1 HashMap에서 Iterator 사용
// 1. HashMap의 keySet() 메소드를 사용해서
// 저장된 키(key)값들만 이루어진 Set을 만듬.
// 2. 1에서 만들어진 Set에 있는 iterator() 메소드를 사용해서
// Iterator를 생성
System.out.println();
Set<Integer> keySet = hmap.keySet();
Iterator<Integer> itr = keySet.iterator();
while(itr.hasNext()) {
int key = itr.next();
System.out.println(key + " : " + hmap.get(key));
}
System.out.println();
// 방법2 : Map.Entry 사용
// entrySet() 은 Set<Entry<Integer, String>> 리턴함
for(Map.Entry<Integer, String> m : hmap.entrySet()) {
System.out.println(m.getKey() + " : " + m.getValue());
}
// 방법3 : toString()
System.out.println(hmap);
System.out.println();
// 도전과제
// arr[] = {2, 4, 5, 4, 3, 3, 4}
// 주어진 배열이 위와 같을때 다음과 같이 발생회수 나타내기
// 2 : 1개
// 3 : 2개
// 4 : 3개
// 5 : 1개
System.out.println("HashMap 응용: 배열에서 발생빈도 구하기");
int arr[] = {11, 12, 2, 4, 5, 4, 3, 3, 4, 3, 3, 3, 9, 9, 9, 11, 12, 12, 12};
printFreq(arr);
System.out.println("\n프로그램 종료");
} // end main()
static void printFreq(int[] arr) {
// TODO Auto-generated method stub
/*
* 첫등장이면 -> 개수 1번 -> put (숫자, 1)
* 두번째부터 등장 -> 기존개수 +1 -> put (숫자, 기존값 + 1)
*/
// 발생빈도 담을 Map 준비
// key : 등장 숫자
// value : 등장 횟수
Map<Integer, Integer> hmap = new HashMap<Integer, Integer>();
// 발생빈도 작성
for (int i = 0; i < arr.length; i++) {
Integer v = hmap.get(arr[i]); // get() 의 결괏값은 등장 횟수, 없으면 null 리턴
if(v == null) { // 첫등장이면 -> 개수 1번 -> put (숫자, 1)
hmap.put(arr[i], 1);
} else {
hmap.put(arr[i], v + 1); // 두번째부터 등장 -> 기존개수 +1 -> put (숫자, 기존값 + 1)
}
} // end for
// 결과 출력.
for(Map.Entry<Integer, Integer> e: hmap.entrySet()) {
System.out.println(e.getKey() + " : " + e.getValue() + "개");
}
}
// TODO
} // end class
package com.lec.java.collection12;
import java.util.HashMap;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeMap;
// Hash: 검색을 빠르게 하기 위한 용도
// Tree: 데이터 정렬을 하기 위한 용도
public class Collection12Main {
public static void main(String[] args) {
System.out.println("TreeMap 클래스");
// TreeMap<Integer, String> 타입 인스턴스 생성
TreeMap<Integer, String> tmap = new TreeMap<Integer, String>();
// 데이터 저장: put(key, value) 메소드 사용
tmap.put(1, "aaa");
tmap.put(3, "asdf");
tmap.put(4, "zxcv");
tmap.put(2, "qwerty");
// values() : value 들로 이루어진 Collection 리턴
System.out.println("values()");
for(String value : tmap.values()) {
System.out.println(value);
}
// ↑ value 에 대해 정렬된건 아니라는 사실을 알수 있다.
// 데이터 검색: get(key) 메소드를 사용
// 1. 키값들로만 이루어진 Set을 만듬
Set<Integer> kset = tmap.keySet();
// 2. keySet을 가지고 iterator를 만듬
Iterator<Integer> itr = kset.iterator();
while(itr.hasNext()) {
int key = itr.next();
System.out.println(key + " : " + tmap.get(key));
}
// ↑ key 에 대해서 정렬되어 있다!
System.out.println();
// key 역순 출력
// TreeMap에만 있는 KeySet을 만들어 내는 메소드
NavigableSet<Integer> navi = tmap.navigableKeySet();
Iterator<Integer> itr2 = navi.descendingIterator();
while(itr2.hasNext()) {
int key = itr2.next();
System.out.println(key + " : " + tmap.get(key));
}
// HashMap --> TreeMap 전환하기
System.out.println("HashMap() -> TreeMap() ");
HashMap<String, Integer> hmap = new HashMap<String, Integer>();
hmap.put("이순신", 50000);
hmap.put("강감찬", 70000);
hmap.put("최영", 20000);
System.out.println(hmap);
TreeMap<String, Integer> tmap2 = new TreeMap<String, Integer>(hmap);
System.out.println(tmap2);
System.out.println("\n프로그램 종료");
} // end main()
} // end class
package com.lec.java.collection14;
import java.text.ParseException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
/* java.util.Collections 클래스
Collections 클래스는 여러 유용한 알고리즘을 구현한 메소드들을 제공
대부분 클래스메소드 (static) 형태로 제공됨
정렬(sort)
섞기(shuffle)
탐색(search)
*/
public class Collection14Main {
public static void main(String[] args) throws ParseException {
System.out.println("Collections 메소드");
List<String> list1 = new LinkedList<String>();
list1.add("장길산");
list1.add("김철수");
list1.add("구자철");
System.out.println(list1);
System.out.println("sort()");
// sort()
// 기본적으로 속도가 비교적 빠르고 안전성이 보장되는 Merge Sort 사용
Collections.sort(list1);
System.out.println(list1);
// String 타입이면 알파벳 순으로 정렬된다.
// Date, Calendar, java.time.* 타입이면 날짜/시간 순으로 정렬된다
// ↑ 이들은 기본적으로 Comparable<T> 인터페이스가 구현되었기 때문.
// ※ String 온라인 도움말 확인해보자
System.out.println();
List<LocalDate> list2 = new LinkedList<LocalDate>();
list2.add(LocalDate.parse("2018-08-16"));
list2.add(LocalDate.parse("2017-05-21"));
list2.add(LocalDate.parse("2022-02-09"));
System.out.println(list2);
Collections.sort(list2);
System.out.println(list2);
System.out.println();
List<Student> list3 = new ArrayList<Student>();
list3.add(new Student("Susie", 50));
list3.add(new Student("James", 80));
list3.add(new Student("Kevin", 30));
System.out.println(list3);
System.out.println("Comparable 구현, sort() 적용");
Collections.sort(list3); // Student 는 Comparable<> 이 구현안되어 있으므로 에러난다.
System.out.println(list3);
// 역순 정렬
System.out.println("reverseOrder() 적용");
Collections.sort(list3, Collections.reverseOrder());
System.out.println(list3);
System.out.println("reverse() 적용"); // 뒤집기
Collections.reverse(list3);
System.out.println(list3);
// Comparator<> 적용
// Collections.sort 메소드는 두 번째 인자로 Comparator 인터페이스를 받을 수 있도록 해놓았습니다.
// Comparator 인터페이스의 compare 메소드를 오버라이드 하면 됩니다.
System.out.println("Comparator<> 적용");
Collections.sort(list3); // 기본 정렬 동작은 Comparable
Collections.sort(list3, new Asc()); // Asc . 이름 오름차순
System.out.println("Asc적용:" + list3);
Collections.sort(list3, new Desc()); // Desc . 이름 내림차순
System.out.println("Desc적용:" + list3);
// Collections 에서 많이 쓰이는 인터페이스임
// Comparable<> 은 클래스 자체에 구현하는 인터페이스 compareTo(자기사진 vs 매개변수)
// Comparator<> 는 두개의 객체 비교하는 기능제공 인터페이스 compare(매개변수1 vs 매개변수2)
// 구현된 객체가 매개변수 등에 넘겨지는 형태로 많이 쓰임
// Shuffling 하기 (섞기)
System.out.println();
System.out.println("shuffle()");
Collections.shuffle(list1);
System.out.println(list1);
Collections.shuffle(list1);
System.out.println(list1);
// 배열에서 랜덤으로 3명만 뽑기
String [] arr = {"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg"};
// 배열 -> List<>
List<String> arrList = Arrays.asList(arr);
Collections.shuffle(arrList);
arrList = arrList.subList(0, 3); // index 0 부터 3 전까지의 List<> 생성
System.out.println(arrList);
// min(), max()
// Comparable 메소드 영향 받음
System.out.println();
System.out.println("min(), max()");
System.out.println("min():" + Collections.min(list3));
System.out.println("max():" + Collections.max(list3));
// copy()
System.out.println();
List<Student> list4 = new ArrayList<Student>();
list4.add(new Student("aaa", 10));
list4.add(new Student("bbb", 20));
list4.add(new Student("ccc", 30));
System.out.println("copy()전: " + list4);
Collections.copy(list4, list3);
System.out.println("copy()후: " + list4);
System.out.println("\n프로그램 종료");
} // end main
} // end class
// 우선은 Comparable 구현 없이 해보자
class Student implements Comparable<Student>{
String name;
double point;
public Student(String name, double point) {
super();
this.name = name;
this.point = point;
}
@Override
public String toString() {
return this.name + ":" + this.point + "점";
}
//comparaTo() 메소드는 매개변수 객체를 현재의 객체와 비교하여
// 정렬순위가 낮으면 음수, 같으면 0, 높으면 양수를 반환한다.
@Override
public int compareTo(Student o) {
// 점수(point) 오름차순
if(o.point > this.point) return -1;
if(this.point > o.point) return 1;
return 0;
// 점수(point) 내림차순
// if(o.point < this.point) return -1;
// if(this.point < o.point) return 1;
// return 0;
// 이름(name) 오름차순
// return this.name.compareTo(o.name);
// 이름(name) 내림차순
// return -this.name.compareTo(o.name);
}
// TODO
} // end class
class Asc implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
// 이름(name) 오름차순
return o1.name.compareTo(o2.name);
}
} // end Asc
class Desc implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
// 이름(name) 내림차순
return -o1.name.compareTo(o2.name);
}
} // end Desc
경과시간 (Elapsed Time, Lap Time, Duration) 체크하기
알고리즘의 성능, 프로그램의 성능을 가늠하는 대표적인 두가지 척도는
- 시간복잡도 (Time Complexity) : 얼마나 시간이 많이 걸리나?
- 공간복잡도 (Space Complexity) : 얼마나 많은 메모리를 소모하나?
시간복잡도, 즉 수행 '경과시간'을 정밀하게 체크하려면
연월일시분초 개념의 시간보다는 그보다 더 정밀한 시간, 가령 ms, ns 단위로 체크해봐야 한다.
참고]
UTC 란?
협정 세계시(協定世界時, 프랑스어: Temps Universel Coordonné, 영어: Coordinated Universal Time)
또는 UTC(협정 세계표준시)는 1972년 1월 1일부터 시행된 국제 표준시이다.
UTC는 국제원자시와 윤초 보정을 기반으로 표준화되었다.
UTC는 그리니치 평균시(GMT)에 기반하므로 GMT로도 불리기도 하는데,
UTC와 GMT는 초의 소숫점 단위에서만 차이가 나기 때문에 일상에서는 혼용되어 사용된다.
기술적인 표기에서는 UTC가 사용된다.
현재 UTC 확인해보기 : https://www.worldtimeserver.com/current_time_in_UTC.aspx
public class DurationMain {
public static void main(String[] args) {
// 연월일시분초 개념의 시간이 아니라, 현재 시점을 알고 싶을때.
// TODO
//----------------------------------------------------
// 경과시간 체크하기
// TODO
System.out.println();
System.out.println("1] System.currentTimeMillis() 사용");
// TODO
System.out.println();
System.out.println("2] System.nanoTime() 사용");
// TODO
System.out.println();
System.out.println("3] java.time.Instant 사용"); // Java8 이상
// TODO
System.out.println("프로그램 종료");
} // end main()
// 주어진 시간 (millisec) 만큼 딜레이 발생하는 메소드
// TODO
} // end class
Generic 클래스:
- 클래스의 멤버변수나 혹은 메소드의 리턴'타입', 매개변수 등의 '타입'을
- 지정하지 않고 generic(일반적으로)하게 정의하는 클래스
- '동작' 은 같으나, '데이터 타입' 만 다른 경우 Generic 으로 설계함으로 코드 생산성 향상
// '과일' 클래스들 정의
class Banana{
int num;
public Banana() {}
public Banana(int num) {this.num = num;}
public void displayNum() {
System.out.println("바나나 송이개수: " + num);
}
} // end class Banana
class Orange{
int sugar;
public Orange() {}
public Orange(int sugar) {this.sugar = sugar;}
public void displaySugar() {
System.out.println("오렌지 당도: " + sugar);
}
} // end class Orange
class Apple{
int weight;
public Apple() {}
public Apple(int weight) {this.weight = weight;}
public void displayWeight() {
System.out.println("사과 무게: " + weight);
}
} // end class Apple
//------------------------------------------
// 위 과일 들을 담을 box 클래스들 정의
class BananaBox {
Banana banana;
public BananaBox() {}
public BananaBox(Banana banana) {this.banana = banana;}
public Banana pullOut() {return banana;}
}
class OrangeBox {
Orange orange;
public OrangeBox() {}
public OrangeBox(Orange orange) {this.orange = orange;}
public Orange pullOut() { return orange; }
}
class AppleBox {
Apple apple;
public AppleBox() {}
public AppleBox(Apple apple) {this.apple = apple;}
public Apple pullOut() { return apple; }
}
//Generic 클래스:
//클래스의 멤버변수나 혹은 메소드의 리턴'타입', 매개변수 등의 '타입'을
//지정하지 않고 generic(일반적으로)하게 정의하는 클래스
//< > 안에 타입매개변수 (type parameter) 지정
class FruitBox<T>{
T fruit; // T타입 필드
public FruitBox() {}
public FruitBox(T fruit) {this.fruit = fruit;} // T타입 매개변수
public T pullOut() {return fruit;} // T타입 리턴
public class Generic01Main {
public static void main(String[] args) {
System.out.println("Generics(제네릭스)");
System.out.println();
System.out.println("[1] generic 클래스 사용 전");
Orange orange1 = new Orange(10);
OrangeBox orangeBox1 = new OrangeBox(orange1);
orangeBox1.pullOut().displaySugar();
Apple a1 = new Apple(100);
AppleBox appleBox1 = new AppleBox(a1);
appleBox1.pullOut().displayWeight();
Banana b1 = new Banana(15);
BananaBox bananaBox1 = new BananaBox(b1);
bananaBox1.pullOut().displayNum();
// 동작은 pullOut() 으로 같음에도 불구하고,
// 다루는 데이터가 다르다는 이유로 클래스를 매 데이터마다 정의하는 것은 매우 비효율
// 그래서 자바에서는 generic 클래스를 제공
System.out.println();
System.out.println("[2] generic 클래스 사용");
FruitBox<Orange> orangeBox2 = new FruitBox<Orange>(orange1);
orangeBox2.pullOut().displaySugar();
FruitBox<Banana> bananaBox2 = new FruitBox<>(b1);
bananaBox2.pullOut().displayNum();
FruitBox<Apple> appleBox2 = new FruitBox<>(a1);
appleBox2.pullOut().displayWeight();
System.out.println("\n프로그램 종료");
} // end main()
} // end class
제네릭 클래스의 타입
제네릭 클래스에서 사용되는 타입은 기본 자료형(primitive type)은 사용될 수 없고,
Object 타입의 자료형들만 올 수 있음.
(예) int는 사용할 수 없고, Integer를 사용해야 함
(예) double은 사용할 수 없고, Double을 사용해야 함
public class Generic02Main {
public static void main(String[] args) {
System.out.println("Generic 클래스 2");
Test<Integer, String> t1 =
new Test<>(123, "Hello Java!");
t1.display();
System.out.println();
Test<Integer, Double> t2 =
new Test<>(111, 3.14);
t2.display();
System.out.println("\n프로그램 종료");
} // end main
} // end class Collection02Main
class Test<T, U>{
T item1;
U item2;
public Test(T item1, U item2) {
this.item1 = item1;
this.item2 = item2;
}
public void display() {
System.out.println("item1: " + item1);
System.out.println("item2: " + item2);
}
} // end class Test