/*
컬렉션프레임워크(Collection Framework)
애플리케이션을 개발하다 보면 다수의 객체를 저장해서 필요할 때마다 꺼내서 사용하는 경우가 많다.
이러한 객체를 효율적으로 추가, 삭제, 검색을 할 경우에 가장 간단한 방법은 배열을 이용하는 것이다.
배열은 쉽게 생성하고 사용할 수 있지만 저장객체의 크기가 배열생성시에 고정되기 때문에 불특정 다수의
객체를 저장하거나 관리하기에는 문제가 많다.
자바는 배열의 이러한 문제점을 해결하기 위해 자료구조(Data Structure)를 바탕으로 객체를 효율적으로
추가, 삭제, 검색할 수 있도록 java.util패키지에 컬렉션과 관련된 인터페이스와 구현클래스를 포함시켜
놓았다. 이들을 총칭해서 컬렉션프레임워크라고 한다.
컬렉션프레임워크에는 몇가지 인터페이스를 통해서 다양한 컬렉션을 이용할 수 있도록 하고 있다. 주요
인터페이스로는 List, Set, Map이 있다.
1. 인터페이스의 분류
1) Collection 계열
a. List : 순서가 있다. 증복저장 가능. index로 접근(ArrayList, Vector, LinkedList)
b. Set : 순서가 없다. 중복저장 불가. 반복자(Iterator)로 접근(HashSet, TreeSet)
2) Map 계열
- Key와 값을 한쌍(EntrySet)으로 저장. Key는 중복불가. Value는 저장가능.
- 구현클래스 : HashMap, HashTable, TreeMap, Properties
2. List Collection
List Collection은 객체를 일렬로 늘어 놓은 구조를 가지고 있고 객체를 인덱스로 관리하기 때문에
객체를 지정하면 자동으로 인덱스가 부여되고 이 인덱스로 객체를 검색, 삭제할 수 있는 기능을 제공
한다. 동일한 객체를 중복 저장할 수 있는데 이 경우에는 동일한 객체를 참조하는 번지가 저장된다.
null도 저장이 가능한데 이 경우에는 해당 인덱스에는 참조하는 객체가 없기 때문에 검색할 경우에는
NullPointException예외가 발생한다.
1) ArrayList
ArrayList는 List인터페이스의 구현 클래스로 ArrayList에 객체를 추가하면 객체가 인덱스로 관리
된다. 일반 배열과 ArrayList는 인덱스로 객체를 관리한다는 점에서는 유사하지만 큰 차이점은
일반배열은 생성시에 크기가 고정되고 사용중에는 크기를 변경할 수 없지만 ArrayList는 저장용량
이 초과할 경우에 객체가 추가되면 자동으로 저장용량(크기)이 증가된다.
ArrayList는 객체의 크기를 저장하지 않고 생성하면 기본크기는 10개의 크기를 가진다. 처음부터
객체의 크기를 저장할 경우에는 ArrayList<참조타입>(20)의 형태로 크기를 지정하면 된다.
2) Vector
Vector는 ArrayList와 동일한 내부구조를 가지고 있다. Vector를 생성하기 위해서는 저장할 객체
타입을 타입파라미터로 표기하고 기본생성자를 호출하면 된다.
ArrayList와 다른 점은 Vector는 동기화(Synchronized)메서드로 구성되어 있기 때문에 멀티쓰레드
환경에서 안전하다. 즉, 다른 쓰레드가 동시에 Vector에 접근할 수 없고 하나의 쓰레드 작업이 완료가
되어야 다른 쓰레드가 실행할 수 있게 된다. 그래서 멀티쓰레드환경에서 안전하게 객체를 추가
삭제를 할 수가 있다.
3) LinkedList
LinkedList는 List인터페이스의 구현클래스이므로 ArrayList와 사용방법은 동일하지만 내부구조는
상이하다. ArrayList는 내부 배열에 객체를 저장해서 인덱스로 관리하지만 LinkedList는 인접자료의
주소를 링크해서 체인연결처럼 관리한다.
LinkedList에서 특정 인덱스에 위치한 객체를 제거하면 전후의 링크만 변경되고 나머지 링크는 변경되지
않는다. 특정 인덱스에 객체를 삽입할 경우에도 동일하게 적용된다.
LinkedList를 생성하기 위해서는 저장할 객체타입을 타입파라미터<E>로 표기하고 기본생성자를 호출
하면 된다. LinkedList는 처음 생성될 때 어떤 링크도 만들어지지 않기 때문에 내부는 비어 있게
된다.
*/
public class ArrayListMain {
public static void main(String[] args) {
// 1. ArrayList - non generic
// 1) add
List list = new ArrayList(); // 크기는 기본값이 10
list.add("문자열");
list.add(new String("손흥민"));
list.add(100); // 자동 Boxing Integer.valueOf(100)
list.add(Integer.valueOf(100)); // 직접 Boxing
list.add(new Car());
list.add(new Apple());
list.add(new Hammer());
// 2) get
String val0 = (String)list.get(0);
String val1 = (String)list.get(1);
Integer val2 = (Integer)list.get(2);
Integer val3 = (Integer)list.get(3);
Car val4 = (Car)list.get(4);
Apple val5 = (Apple)list.get(5);
Hammer val6 = (Hammer)list.get(6);
System.out.println(val0);
System.out.println(val1);
System.out.println(val2);
System.out.println(val3);
System.out.println(val4);
System.out.println(val5);
System.out.println(val6);
System.out.println();
// 2. ArrayList - generic
// 1) add
List<String> list1 = new ArrayList<>();
// list1.add(100);
// list1.add(new Car());
list1.add("Java");
list1.add("JDBC");
list1.add("JSP");
// 2) get - generic으로 String으로 제한했기 때문에 형변환 필요없음
System.out.println(list1.get(0));
System.out.println(list1.get(1));
System.out.println(list1.get(2));
// 3) 삽입 - add(index, 값)
list1.add(2, "JavaScript");
for(int i=0; i<list1.size();i++) {
System.out.println("list1["+i+"] = "+ list1.get(i));
}System.out.println();
// 4) 삭제- remove(index)
list1.remove(3);
for(String lst:list1) {
System.out.println(lst);
}System.out.println();
// 5) 중복확인
list1.add(3,"JDBC");
for(String lst:list1) {
System.out.println(lst);
}System.out.println();
// 6) 전체삭제
list1.clear();
System.out.println("list1의 갯수 = "+list1.size());
}
}
class Apple{}
class Hammer{}
class Car{}
public class ArraysAsListMain {
public static void main(String[] args) {
// 일반배열의 초기화
String[] names = {"홍길동","홍길순","홍길자","홍길상","손흥민","이강인","김민재"};
// ArrayList에는 초기화 기능이 없다. 대신에 Arrays.asList(값,...)메서드를 이용해서
// 초기화시킬 수 있다. ArrayList를 생성하고 Runtime시에 필요에 따라 객체를 추가하는
// 방법이 일반적이지만 고정된 객체로 구성된 List를 생성할 경우에는 Arrays.asList()
// 메서드를 사용하는 것이 편리하다. 다만 Arrays.asList()로 생성된 ArrayList객체는
// 더 이상 크기를 변경할 수 없다.
List<String> list1 = new ArrayList<>(6);
list1.add("추가가능");
list1.remove(0); // 삭제가능
System.out.println("list1의 갯수= "+list1.size());
// ArrayList생성자를 이용하는 대신에 Arrays.asList()로 간편하게 생성할 수 있다.
// 다만, asList()로 생성된 List는 고정된 객체로 생성이 된다. 즉 추가, 삭제할 수 없다.
List<String> list2 = Arrays.asList("홍길동","홍길순","홍길자","홍길상","손흥민","이강인","김민재");
// list2.add("추가불가");
// list2.remove(0); // 삭제 불가
for(String name:list2) {
System.out.println(name+", ");
}
System.out.println();
List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
int sum = 0;
for(Integer num:numbers) {
sum += num;
}System.out.println("1~10까지 합= " +sum);
}
}
public class LinkedListMain {
public static void main(String[] args) {
List<String> arrList = new ArrayList<>();
List<String> lnkList = new LinkedList<>();
// ArrayList vs LinkedList 성능비교
// add, remove일 경우 처리속도 비교
long start,finish;
// 1. ArrayList
start = System.nanoTime();
for(int i=0;i<100000;i++) {
arrList.add(0,String.valueOf(i));
}
finish = System.nanoTime();
System.out.println("ArrayList의 소요시간= "+(finish-start)+"ns");
// 2. LinkedList
start = System.nanoTime();
for(int i=0;i<100000;i++) {
lnkList.add(0,String.valueOf(i));
}
finish = System.nanoTime();
System.out.println("LinkedList의 소요시간= "+(finish-start)+"ns");
}
}
public class VectorMain {
public static void main(String[] args) {
// 1. ArrayList - Member
List<Member> members = new ArrayList<>();
members.add(new Member(1,"12345","홍길동","hong1@gmail.com"));
members.add(new Member(2,"12345","홍길순","hong2@gmail.com"));
members.add(new Member(3,"12345","홍길녀","hong3@gmail.com"));
members.add(new Member(4,"12345","홍길자","hong4@gmail.com"));
members.add(new Member(5,"12345","홍길상","hong5@gmail.com"));
for(Member member:members) {
System.out.println(member.toString());
}System.out.println();
// 2. Vector - Board
List<Board> boards = new Vector<>();
boards.add(new Board(1,"제목1","홍길동","글내용1"));
boards.add(new Board(2,"제목2","홍길순","글내용2"));
boards.add(new Board(3,"제목3","홍길녀","글내용3"));
boards.add(new Board(4,"제목4","홍길자","글내용4"));
boards.add(new Board(5,"제목5","홍길상","글내용5"));
for(Board board:boards) {
System.out.println(board.toString());
}System.out.println();
// 삭제 : delete from where bno = 4
boards.remove(3);
// 조회 : select * from board;
System.out.println("<table>");
for(int i=0;i<boards.size();i++) {
Board board = boards.get(i);
System.out.println("<tr><td>"
+board.bno+"</td><td>"
+board.title+"</td><td>"
+board.writer+"</td><td>"
+board.Content+"</td><td>"
+"</tr>");
}
System.out.println("</table>");
}
}
class Member{
int id;
String pw;
String name;
String email;
public Member(int id, String pw, String name, String email) {
this.id = id;
this.pw = pw;
this.name = name;
this.email = email;
}
@Override
public String toString() {
return "Member [id=" + id + ", pw=" + pw + ", name=" + name + ", email=" + email + "]";
}
}
class Board{
int bno;
String title;
String writer;
String Content;
public Board(int bno, String title, String writer, String content) {
this.bno = bno;
this.title = title;
this.writer = writer;
Content = content;
}
@Override
public String toString() {
return "Board [bno=" + bno + ", title=" + title + ", writer=" + writer + ", Content=" + Content + "]";
}
}
/*
Set 컬렉션
List 컬렉션은 저장순서를 유지하지만 Set컬렉션은 저장순서를 유지하지 않으며 또한 객체를
중복저장할 수 없다. (null은 저장가능하지만 단 한개의 null값만 저장할 수 있다)
set컬렉션은 HashSet, TreeSet, LinkedHashSet등이 있다. set컬렉션은 순서가 없어서
인덱스로 객체를 검색할 수 없다. 대신에 전체 객체를 한번씩 반복해서 읽어오는 반복자(Iterator)
를 제공한다. 반복자는 Iterator인터페이스를 구현한 객체를 말하는데 iterator()메서드를 호출해서
자료를 읽을 수가 있다.
Iterator에는 아래와 같은 메서드를 제공한다.
1. hasNext() : 읽어올 객체가 있을 경우에는 true, 없을 경우 false를 리턴
2. next() : set컬렉션에서 다음 객체를 읽어오는 메서드, 더 이상 읽을 객체가 없다면 예외발생
3. remove() : set컬렉션에서 객체를 제거
HashSet은 객체를 순서없이 저장하고 동일한 객체는 중복저장하지 않는다. 하지만 HashSet이 판단하는
동일 객체란 꼭 같은 인스탄스를 뜻하지는 않는다. HashSet객체를 저장하기 전에 먼저 객체의
hashCode()메서드를 호출해서 해시코드를 가져오고 이미 저장되어 있는 객체들의 hashCode와 비교한다.
만약, 동일한 hashCode가 있다면 다시 equals()메서드를 호출해서 두 객체를 비교해서 같으면 true를 리턴하고
true가 리턴되면 동일객체로 판단하고 더 이상 저장하지 않는다.
*/
public class HashSetMain1 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("Java");
set.add("DataBase");
set.add("Python");
set.add("JDBC");
set.add("R");
set.add("Java"); // 중복발생의 경우는 에러는 발생하지 않지마 ㄴ저장되지는 않는다.
set.add("SQL");
System.out.println("총 객체수= "+set.size());
System.out.println();
// set컬렉션 객체읽기
Iterator<String> data = set.iterator();
System.out.println(data.hasNext());
while(data.hasNext()) {
String element = data.next();
System.out.println(element);
}
System.out.println(data.hasNext());
System.out.println();
// data.next(); // 더이상 읽을 자료가 없을 경우 에러
data=set.iterator();
System.out.println(data.hasNext());
String str = data.next();
System.out.println(str);
System.out.println();
// 객체삭제
set.remove("DataBase");
data = set.iterator();
while(data.hasNext()) {
String element = data.next();
System.out.println(element);
}
System.out.println();
// 전체삭제
set.clear();
System.out.println("총 객체수= "+set.size());
}
}
class Member{
String name;
}
public class HashSetMain2 {
public static void main(String[] args) {
Set<Member> members = new HashSet<>();
members.add(new Member("손흥민",31));
members.add(new Member("손흥민",31));
members.add(new Member("손흥민",20));
members.add(new Member("이강인",23));
System.out.println("총 객체수= " +members.size());
for(Member member:members) {
System.out.println(member.toString()+", "+member.hashCode());
}
}
}
class Member{
// @Override
// public int hashCode() {
// return Objects.hash(age, name);
// }
String name;
int age;
public Member(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Member [name=" + name + ", age=" + age + "]";
}
// @Override
// public int hashCode(){
// //System.out.println(this.name.hashCode());
// //System.out.println(this.age);
// // name의 hashCode와 age가 같을 경우 동일한 hashCode를 리턴
// return name.hashCode() + age;
// }
// @Override
// public boolean equals(Object obj) {
// // name과 age가 같은 경우에 동일객체로 판단해서 true를 리턴
// // 아닐 경우에는 false가 되도록 equals메서드를 재정의
// if(obj instanceof Member) {
// Member member = (Member) obj;
// return (member.name.equals(this.name)) && (member.age == this.age);
// }
// return false;
// }
//hashCode와 equals - eclipse의 자동완성
@Override
public int hashCode() {
return Objects.hash(age);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Member other = (Member) obj;
return age == other.age;
}
}
/*
Map Collection
Map 컬렉션은 키(Key)와 값(Value)으로 구성된 Map.Entry객체를 저장하는 구조를 가지고 있다.
키와 값은 모두 참조타입(객체)이다. 키는 중복이 불가하고 값은 중복저장이 가능하다. 만약
기존에 저장된 키와 동일한 키가 있다면 기존값은 없어지고 새로운 값으로 대체된다.
Map컬렉션은 HashMap, LinkedHashMap, Properties, TreeMap등이 있다. Map에 대한 값을 얻고자할
경우에는 2가지 방법이 있다.
키 값을 알고 있다면 get()메서드로 간단히 객체를 검색할 수 있지만 저장된 전체 객체를 대상
으로 값을 하나씩 읽고자 할 경우에는
1. KeySet() : 이 메서드로 모든 키를 set컬렉션으로 저장한 후에 반복자(Iterator)를 통해서
키를 하나씩 읽은 후에 get()메서드를 이용해서 값을 읽는 방법
2. entrySet() : 이 메서드로 모든 MAP.Entry객체를 set컬렉션으로 읽은 후 반복자를 통해
Map.Entry객체를 하나씩 읽어서 getKey(),getValue()메서드를 이용해서 읽는 빙법이 있다.
*/
public class HashMapMain1 {
public static void main(String[] args) {
// 1. Map객체 생성
Map<String, Integer> map = new HashMap<>();
// 2. 객체저장 - put()
map.put("홍길동", 85);
map.put("홍길순", Integer.valueOf(80));
map.put("홍길자", 85);
map.put("홍길녀", 75);
map.put("홍길성", 88);
map.put("홍길동", 90); // 키가 중복, 에러는 발생하지 않지만 최종값으로 대체 즉, 85점이 90점으로 대체.
System.out.println("총 객체 수 = "+map.size());
Map<Integer, String> map2 = new HashMap<>();
map2.put(1, "소향");
map2.put(1, "나얼");
System.out.println("총 객체 수 = "+map2.size()); // 키는 중복이 불가능
System.out.println();
// 3. 객체검색(1) - get()
System.out.println("홍길동의 점수= "+map.get("홍길동"));
System.out.println("홍길녀의 점수= "+map.get("홍길녀"));
System.out.println();
// 4. 객체검색(2) - keySet()
Set<String> keySet = map.keySet();
Iterator<String> names = keySet.iterator();
while(names.hasNext()) {
String name = names.next();
Integer score = map.get(name);
System.out.println(name+"의 점수 = "+score);
}System.out.println();
// 5. 객체검색(3) - entrySet()
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<String, Integer>> entrys = entrySet.iterator();
while(entrys.hasNext()) {
Map.Entry<String, Integer> entry = entrys.next();
String name = entry.getKey();
Integer score = entry.getValue();
System.out.println(name+"의 점수= "+score);
}System.out.println();
// 6. 객체삭제
map.remove("홍길동");
System.out.println("총 객체수 = "+ map.size());
// 7. 전체삭제
map.clear();
System.out.println("총 객체수 = "+ map.size());
}
}
public class HashMapMain2 {
public static void main(String[] args) {
Map<Student, Integer> map = new HashMap<>();
map.put(new Student(1, "소향"), 80);
map.put(new Student(1, "소향"), 99);
System.out.println("총 객체 수= "+map.size());
Set<Student> keySet = map.keySet();
Iterator<Student> students = keySet.iterator();
while(students.hasNext()) {
Student student = students.next();
Integer score = map.get(student);
System.out.println(student+"의 점수= "+score);
}
}
}
class Student{
private int sno;
private String name;
public Student(int sno, String name) {
this.sno = sno;
this.name = name;
}
@Override
public String toString() {
return "Student [sno=" + sno + ", name=" + name + "]";
}
@Override
public int hashCode() {
return this.sno+this.name.hashCode();
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Student) {
Student student = (Student) obj;
return(this.sno == student.sno) &&(this.name.equals(obj));
}
return false;
}
}
public class HashTableMain {
public static void main(String[] args) {
Map<String, String> map = new Hashtable<>();
// 로그인 정보 : select id, pw from member;
map.put("hong", "12345");
map.put("sohyang", "67890");
map.put("sonny", "abcde");
map.put("kangin", "fghjik");
// 1. containsKey() : 키 존재여부를 리턴
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.println("Id와 pw를 입력하세요");
System.out.println("id=> ");
String id = scanner.nextLine();
System.out.println("pw=> ");
String pw = scanner.nextLine();
if(map.containsKey(id)) {
if(map.get(id).endsWith(pw)) {
System.out.println("로그인성공");
}else {
System.out.println("로그인실패");
}
}else {
System.out.println("아이디를 찾지 못했습니다");
break;
}
}System.out.println("프로그램 종료");
}
}
/*
Properties
Properties는 HashTable의 하위 클래스이기 때문에 HashTable의 모든 속성을 그대로 가지고 있는데
차이점은 HashTable은 키와 값에 다양한 참조타입으로 정의할 수 있지만 Properties는 키와 값의
참조타입이 오직 String으로만 정의할 수 있도록 제한된 Map컬렉션이다.
Properties는 애플리케이션의 옵션정보, 데이터베이스의 연결정보, 그리고 국제화(다국어)정보가
제공된 프로퍼티파일을 읽을 때 주로 사용한다.
Properties파일은 키와 값이 "="로 연결되어 있는 텍스트파일로 ISO8859-1문자셋으로 저장된다.
이 문자셋으로 직접 표현할 수 없는 값 즉, 한글은 유니코드(\u9999)로 변환되어 저장된다.
이클립스에서는 유니코드로 변환된 내용을 한글로 확인하려면 마우스를 유니코드위에 올려놓으면
한글을 볼 수가 있다.
이클립스를 사용하지 않는다면 한글이 포함된 Properties파일을 다른 에디터(예를 들어 notepad)
에서 작성하고 JDK설치 폴더에 native2ascii.exe프로그램을 이용해서 ISO8859-1파일로 저장하면 된다.
*/
public class PropertiesMain {
public static void main(String[] args) throws Exception {
// Properties파일 읽기
// 1. 파일경로확인
String path = PropertiesMain.class.getResource("database.properties").getPath();
path = URLDecoder.decode(path,"utf-8"); // 폴더명에 한글이 있을 경우에 decoding, UnsupportedEncodingException 예외처리
System.out.println("파일경로= "+path);
System.out.println();
// 2. 파일읽기
Properties properties = new Properties(); // HashTable의 하위클래스
properties.load(new FileReader(path)); // FileNotFoundException 예외처리
// 3. key와 value을 읽기
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String hangul = properties.getProperty("hangul");
System.out.println(driver);
System.out.println(url);
System.out.println(user);
System.out.println(password);
System.out.println(hangul);
}
}
database.properties
driver = oracle.jdbc.OracleDriver
url = jdbc.oracle.thin:@localhost:1521
user=scott
password=tiger
hangul=\uAD00\uB9AC\uC790
# comment=properties\uD30C\uC77C\uC758 \uC8FC\uC11D\uCC98\uB9AC \uBC29\uBC95
mariadb = maria.jdbc.driver
mysql = mysql.jdbc.driver
TreeMap
public class TreeMapMain1 {
public static void main(String[] args) {
// 1. TreeMap 값 가져오기
TreeMap<Integer, String> students = new TreeMap<>();
students.put(87, "홍길동");
students.put(98, "손흥민");
students.put(75, "이강인");
students.put(95, "김민재");
students.put(80, "소향");
Map.Entry<Integer, String> student = null;
// 가장 낮은 점수, 가장 높은 점수, 95바로 아래 점수, 95 바로 위 점수
student = students.firstEntry();
System.out.println("가장 낮은 점수 = "+ student.getValue()+"의 점수는 "+student.getKey()+"입니다");
student = students.lastEntry();
System.out.println("가장 높은 점수 = "+ student.getValue()+"의 점수는 "+student.getKey()+"입니다");
student = students.lowerEntry(95);
System.out.println("95바로 아래 점수 = "+ student.getValue()+"의 점수는 "+student.getKey()+"입니다");
student = students.higherEntry(95);
System.out.println("95바로 위 점수 = "+ student.getValue()+"의 점수는 "+student.getKey()+"입니다");
student = students.floorEntry(90);
System.out.println("90이거나 바로 아래 점수 = "+ student.getValue()+"의 점수는 "+student.getKey()+"입니다");
student = students.ceilingEntry(90);
System.out.println("90이거나 바로 위 점수 = "+ student.getValue()+"의 점수는 "+student.getKey()+"입니다");
while(!students.isEmpty()) {
student = students.pollFirstEntry();
System.out.println(student.getValue() + "의 점수는 "+ +student.getKey()+", 남은객체수= "+students.size());
}
}
}
public class TreeMapMain2 {
public static void main(String[] args) {
// 2. TreeMap 정렬하기
TreeMap<Integer, String> students = new TreeMap<>();
students.put(87, "홍길동");
students.put(98, "손흥민");
students.put(75, "이강인");
students.put(95, "김민재");
students.put(80, "소향");
for(Entry<Integer, String> score : students.entrySet()) {
System.out.println(score.getValue()+"의 점수= "+score.getKey());
}System.out.println();
// descendingMap()
// descendingEntry()
NavigableMap<Integer, String> descMap = students.descendingMap();
Set<Map.Entry<Integer, String>> desEntry = descMap.entrySet();
System.out.println("오름차순");
for(Map.Entry<Integer, String> student : desEntry) {
System.out.print("("+student.getKey()+", "+student.getValue()+")");
}System.out.println();
NavigableMap<Integer, String> ascMap = descMap.descendingMap();
System.out.println("내림차순");
for(Entry<Integer, String> score : ascMap.entrySet()) {
System.out.print("("+score.getKey()+", "+score.getValue()+")");
}System.out.println();
}
}
public class TreeMapMain3 {
public static void main(String[] args) {
// 3. 범위검색하기
TreeMap<String,Integer> words = new TreeMap<>();
words.put("apple", Integer.valueOf(10));
words.put("orange", 20);
words.put("banana", 25);
words.put("cherry", 10);
words.put("mango", 30);
words.put("pea", 28);
words.put("for", 40);
words.put("f", 45);
words.put("c", 50);
//c~f사이의 단어검색
NavigableMap<String, Integer> rm = words.subMap("c", false, "f", false);
for(Map.Entry<String, Integer> entry:rm.entrySet()) {
System.out.println(entry.getKey() +"="+ entry.getValue());
}
}
}
/*
TreeSet
TreeSet은 이진트리(Binary Tree)를 기반으로 한 set컬렉션이다. 하나의 노드는 노드값인 value와 왼쪽,
오른쪽 노드를 참조하기 위한 2개의 변수로 구성된다.
TreeSet객체를 저장하면 자동으로 정렬되는데 부값과 비교해서 작은 값은 왼쪽, 큰 값은 오른쪽
자식노드에 저장된다.
TreeSet은 Set인터페이스타입변수에 대입해도 되지만 TreeSet클래스 타입으로 하는 이유는 객체를
검색하거나 범위검색과 관련된 메서드를 사용하기 위해서 있다.
*/
public class TreeSetMain1 {
public static void main(String[] args) {
// 1. TreeSet값 꺼내오기
TreeSet<Integer> scores = new TreeSet<>();
scores.add(new Integer(87));
scores.add(Integer.valueOf(98));
scores.add(75);
scores.add(95);
scores.add(80);
scores.add(80); // 중복저장불가
System.out.println("총 객체수= "+scores.size());
System.out.println();
// 가장 낮은 점수, 가장 높은 점수, 95바로 아래 점수, 95 바로 위 점수
Integer score = 0;
score = scores.first();
System.out.println("가장 낮은 점수=" +score);
score = scores.last();
System.out.println("가장 높은 점수=" +score);
score = scores.lower(95);
System.out.println("95바로 아래 점수=" +score);
score = scores.higher(95);
System.out.println("95바로 위 점수=" +score);
score = scores.floor(94);
System.out.println("94이거나 바로 아래 점수=" +score);
score = scores.ceiling(96);
System.out.println("96이거나 바로 위 점수=" +score);
System.out.println();
while(!scores.isEmpty()) {
score = scores.pollLast(); // 가장 큰 값부터 꺼내오고 삭제
System.out.println(score + ", 남은 객체 수= "+scores.size());
}
}
}
public class TreeSetMain2 {
public static void main(String[] args) {
// 2. TreeSet 정렬하기
TreeSet<Integer> scores = new TreeSet<>();
scores.add(87);
scores.add(98);
scores.add(75);
scores.add(95);
scores.add(80);
// 정렬하기 - TreeSet은 저장될 때 자동으로 오름차순으로 정렬되어 저장한다.
for(Integer score:scores) {
System.out.print(score+", ");
}System.out.println();
// 2) 내림차순, 오름차순 정렬하기
// descendingSet() : 내림차순, NavigableSet객체로 리턴
// descendingIterator() : 내림차순, Iterator 객체로 리턴
NavigableSet<Integer> descSet = scores.descendingSet();
for(Integer score:descSet) {
System.out.print(score+", ");
}System.out.println();
// 내림차순 -> 오름차순
NavigableSet<Integer> ascSet = descSet.descendingSet();
System.out.print("내림->오름차순");
for(Integer score:ascSet) {
System.out.print(score+", ");
}System.out.println();
}
}
public class TreeSetMain3 {
public static void main(String[] args) {
// 3. TreeSet 검색하기
TreeSet<String> words = new TreeSet<>();
words.add("apple");
words.add("c");
words.add("forever");
words.add("description");
words.add("love");
words.add("zoo");
words.add("ever");
words.add("base");
words.add("guess");
words.add("cherry");
words.add("f");
for(String word:words) {
System.out.print(word+", ");
}System.out.println();
// 범위검색
System.out.println("[c~f 사이의 단어 검색하기]");
NavigableSet<String> rangeSet = words.subSet("c", false, "f", true);
for(String word:rangeSet) {
System.out.print(word+", ");
}
}
}
/*
Comparable vs Comparator
TreeSet객체와 TreeMap의 키는 저장과 동시에 자동으로 오름차순으로 정렬되는데 숫자(Integer, Double..)
타입일 경우에는 값을 정렬하고, 문자열(String)타입일 경우에는 유니코드로 정렬된다.
TreeSet객체와 TreeMap을 정렬하기 위해서는 java.lang.Comparable 인터페이스를 구현한 객체를 요구하는데
Integer, Double, String 등으로 모두 Comparable 인터페이스를 구현하고 있다.
사용자가 정의한 클래스를 TreeSet이나 TreeMap에 저장할 경우에 Comparable을 구현하고 있지 않을 경우에
자동정렬을 할 수가 없다. Comparable 인터페이스는 compareTo() 추상메서드가 정의되어 있기 때문에 사용자가
정의하는 클래스도 Comparable을 구현하려면 compareTo()메서드를 재정의해야 한다.
compareTo()메서드는 int값을 리턴하는데 객체가 동일할 경우는 0, 작을 경우는 -1, 클 경우는 1을 리턴한다.
TreeSet객체와 TreeMap의 키가 Comparable을 구현하고 있지 않을 경우에는 객체를 저장하는 순간 ClassCastException
예외가 발생한다.
*/
public class ComparableMain {
public static void main(String[] args) {
TreeSet<Person> persons = new TreeSet<>();
persons.add(new Person("홍길동", 1000));
persons.add(new Person("손흥민", 31));
persons.add(new Person("이강인", 22));
persons.add(new Person("김민재", 25));
persons.add(new Person("소향", 43));
persons.add(new Person("나얼", 40));
persons.add(new Person("거미", 42));
persons.add(new Person("거미", 10));
System.out.println("총 객체수= "+persons.size());
System.out.println();
Iterator<Person> persons1 = persons.iterator();
while(persons1.hasNext()) {
Person person = persons1.next();
System.out.println(person.name+", "+person.age);
}
}
}
class Person implements Comparable<Person>{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 1. 이름순으로 정렬
// @Override
// public int compareTo(Person p) {
// return this.name.compareTo(p.name);
// }
// 2. 나이순으로 정렬
// @Override
// public int compareTo(Person p) {
// if(this.age<p.age) return -1;
// else if(this.age==p.age) return 0;
// else return 1;
// }
//@Override
// public int compareTo(Person p) {
// return(this.age<p.age)?-1 : ((this.age==p.age)? 0 : -1);
// }
// @Override
// public int compareTo(Person p) {
// return Integer.compare(this.age, p.age);
// }
// 3. 이름, 나이순으로 정렬
@Override
public int compareTo(Person p) {
String x = this.name+this.age;
String y = p.name + p.age;
// return x.compareToIgnoreCase(y);
return x.compareTo(y);
}
}
public class ComparatorMain {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<>(new StudentComparator());
ts.add(new Student("홍길동", 1000));
ts.add(new Student("손흥민", 31));
ts.add(new Student("이강인", 22));
ts.add(new Student("김민재", 25));
ts.add(new Student("소향", 43));
ts.add(new Student("나얼", 40));
ts.add(new Student("거미", 42));
ts.add(new Student("거미", 10));
System.out.println("총 객체수= "+ts.size());
Iterator<Student> students = ts.iterator();
while(students.hasNext()) {
Student student = students.next();
System.out.println(student.name+", "+student.sno);
}
System.out.println();
}
}
class Student{
String name;
int sno;
public Student(String name, int sno) {
this.name = name;
this.sno = sno;
}
}
class StudentComparator implements Comparator<Student>{
// 1. 이름순
// @Override
// public int compare(Student s1, Student s2) {
// return s1.name.compareTo(s2.name);
// }
// 2. 번호순
@Override
public int compare(Student s1, Student s2) {
return (s1.sno<s2.sno)? -1 : ((s1.sno==s2.sno)? 0: -1);
}
// 3. 학생번호와 이름순
// @Override
// public int compare(Student s1, Student s2) {
// int x = s1.name.hashCode()+s1.sno;
// int y = s2.name.hashCode()+s2.sno;
// return (x<y)?-1 : ((x==y)? 0 : 1);
//
// }
}
/*
LIFO(후입선출)dhk FIFO(선입선출) 컬렉션
후입선출(LIFO, Last In First Out)은 나중에 저장된 객체를 먼저 꺼내오는 자료구조이고 반댁로
선입선출(FIFO, First In First Out)은 먼저 저장된 객체가 먼저 꺼내지는 자료구조를 ㅏㅁㄹ한다.
컬렉션 프레임워크에는 LIFO자료구조를 지원하는 Stack클래스와 FIFO자료구조를 지원하는 Queue
인터페이스를 지원한다.
1. Stack class
Stack 클래스는 LIFO자료 구조를 구현한 클래스이다. 주요 메서드는
1) push(E item) : 주어진 객체를 stack에 저장
2) peek() : stack의 맨위(맨 나중에 저장된) 객체를 꺼내만 온다.
3) pop() : stack의 맨위(맨 나중에 저장된) 객체를 꺼내온 후 삭제
2. Queue Interface
Queue 인터페이스는 FIFO자료 구조를 구현한 LinkedList이고 주요 메서드는
1) offer(E item) : 주어진 객체를 stack에 저장
2) peek() : 맨 처음에 저장된 객체를 꺼내만 온다.
3) poll() : 맨 처음에 저장된 객체를 꺼내온 후 삭제
*/
public class StackMain {
public static void main(String[] args) {
Stack<Coin> coin_box = new Stack<>();
coin_box.push(new Coin(50));
coin_box.push(new Coin(100));
coin_box.push(new Coin(10));
coin_box.push(new Coin(1));
coin_box.push(new Coin(500));
while(!coin_box.isEmpty()) {
Coin coin = coin_box.pop();//peek로 하면 500원 무한루프
System.out.println("꺼내온 동전: "+coin.getValue()+"원");
}System.out.println("프로그램 종료");
}
}
class Coin{
private int value;
public Coin(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public class QueMain {
public static void main(String[] args) {
Queue<Message> message = new LinkedList<>();
message.offer(new Message("Send Twitter", "홍길동"));
message.offer(new Message("Send Mail", "홍길순"));
message.offer(new Message("Send Facebook", "홍길자"));
message.offer(new Message("Send Facebook", "홍길자"));
message.offer(new Message("Send Kakaotalk", "홍길녀"));
System.out.println("총 객체수= "+message.size());
System.out.println();
while(!message.isEmpty()) {
Message msg = message.poll();
System.out.println(msg.to+"="+msg.msg);
}System.out.println();
message.offer(new Message("Send Twitter", "홍길동"));
message.offer(new Message("Send Mail", "홍길순"));
message.offer(new Message("Send Facebook", "홍길자"));
System.out.println("총 객체수= "+message.size());
System.out.println();
while(!message.isEmpty()) {
Message msg = message.poll();
switch(msg.msg) {
case "Send Mail":
System.out.println(msg.to+"에게 메일을 보냈습니다");break;
case "Send Facebook":
System.out.println(msg.to+"에게 문자를 보냈습니다");break;
case "Send Twitter":
System.out.println(msg.to+"에게 트윗을 보냈습니다");break;
}
System.out.println(msg.to+"="+msg.msg);
}System.out.println();
}
}
class Message{
public String msg;
public String to;
public Message(String msg, String to) {
this.msg=msg;
this.to=to;
}
}
'일 > JAVA' 카테고리의 다른 글
java16.stream.pipeline (0) | 2023.05.30 |
---|---|
java16.stream.intro (0) | 2023.05.30 |
java14.lambda 람다람다 (0) | 2023.05.26 |
java13.generic (1) | 2023.05.26 |
java12.thread (0) | 2023.05.26 |