Cohe
13 객체 정렬을 위한 객체 간 크기 비교, 제너릭 , File 입출력 본문
728x90
반응형
객체 정렬을 위한 객체 간 크기 비교
- TreeSet, TreeMap은 엘리먼트들을 자동적으로 정렬하는 기능이 있습니다. List의 경우는 자동적으로 정렬되지 않지만, sort메서드를 메서드를 사용하여 정렬이 가능합니다.
- 그러나, 만일 이런 Collection에 기본 데이터 타입이 아닌 일반적인 객체가 들어갈 경우, 정렬을 위해서 객체간의 크기 비교가 선행되어야 한다. 객체간의 크기 비교를 구현하기 위해서 2가지 인터페이스(Comparable, Comparator)를 활용할 수 있습니다.
Comparable 인터페이스 구현
- Collection.sort(list) 사용하여 List를 정렬
- TreeSet() 생성자를 사용했을 때 기본적으로 객체가 정렬되는 방식
- 구현 시 기존의 클래스를 수정해야 하며, compareTo() 구현해야 합니다.
- 기본 정렬 기준을 지정하는 것이라고 볼 수 있습니다.
- 기존 클래스를 수정해야한다!!
Comparator 인터페이스 구현
- Collection.sort(list, comparator) 사용하여 List를 정렬
- TreeSet(Comparator객체) 생성자 사용하여 원하는 방식으로 정렬되게 합니다.
- Comparator를 구현하는 새로운 클래스를 만들어서 compare()메서드를 구현
- 기존 클래스를 수정하지 않고도 기존의 객체를 비교할 수 있습니다.
- 추가 정렬 기준을 지정하는 것이라고 볼 수 있습니다.
package E_java;
import java.util.Comparator;
import java.util.TreeSet;
public class E10_compareEx2 {
public static void main(String[] args) {
//TreeSet, TreeMap
//이진 검색 트리를 구현
TreeSet<GymMember> gym = new TreeSet<>();
gym.add(new GymMember("채현영", 0));
gym.add(new GymMember("채원기", 1));
gym.add(new GymMember("채운이", 2));
gym.add(new GymMember("채수연", 3));
gym.add(new GymMember("윤나영", 4));
gym.add(new GymMember("조현우", 5));
gym.add(new GymMember("김지훈", 6));
System.out.println(gym);
//2. Comparator 이용
TreeSet<GymMember> gym2 = new TreeSet<>(new Comparator<GymMember>() {
public int compare(GymMember o1, GymMember o2) {
//compare 메서드 사용법
// o1과 o2의 자리를 바꾸고 싶다면 1을 리턴
// o1과 o2의 자리를 바꾸고 싶지 않다면 -1을 리턴
// o1과 o2의 같은 값임을 나타내고 싶다면 0을 리턴
if(o1.name.charAt(0) < o2.name.charAt(0)){
return -1;
}
else if (o1.name.charAt(0) > o2.name.charAt(0)){
return 1;
}
else{
return 0; //set인 경우 0이 리턴되면 중복으로 간주 -> 들어가지 않는다.
}
return 0;
};
});
//에러가 떠요ㅠㅠ
gym2.add(new GymMember("채현영", 0));
gym2.add(new GymMember("채원기", 1));
gym2.add(new GymMember("채운이", 2));
gym2.add(new GymMember("채수연", 3));
gym2.add(new GymMember("윤나영", 4));
gym2.add(new GymMember("조현우", 5));
gym2.add(new GymMember("김지훈", 6));
System.out.println(gym2);
}
}
class GymMember implements Comparable<GymMember>{
double height;
double weight;
int age;
String name;
int memNum;
public GymMember(String name, int memNum) {
this.name = name;
this.memNum = memNum;
}
@Override
public String toString() {
return String.format("%s [%d] \n", name, memNum);
}
@Override
public int compareTo(GymMember o) {
return Integer.compare(this.memNum, o.memNum);
}
// @Override
// public int compareTo(GymMember o) {
// int next = o.memNum ;
// System.out.println(memNum + " vs "+next);
// if(memNum < next){
// return -1;
// }
// else if(memNum == next){
// return 0;
// }
// else{
// return 1;
// }
// }
}
CompateTo 메서드는 매개변수 o를 통해 비교대상을 전달 받고,
비교 대상이 해시값 혹은 int 형 => 계산하게 된다. 양수가 나오면 자리를 교체한다.
현재 인스턴스와 o의 자리를 바꾸고 싶은 경우에 1을 리턴한다.
현재 인스턴스와 o의 자리를 유지하고 싶으면 -1을 리턴한다.
현재 인스턴스와 o가 같은 값임을 나타내고 싶다면 0을 리턴
제너릭과 형 안정성(Generic & Type Safety)
제너릭 사용법
- 클래스 이름<데이터 타입>, 메서드 이름
- 제너릭은 JDK 1.5(JDK5)부터 도입.
- 이전까지는 Object유형의 객체를 받기 때문에 어떤 객체이든지 엘리먼트로 넣을 수 있었음.
- 형 안전성이 떨어짐 → 자유롭지만 프로그램 불안정의 문제가 크다.
- 하지만, 엘리먼트 사용하기 위해서 넣기전의 상태로 되돌려야 했고, 반드시 형변환이 필요했음.
- 제너릭 표현을 통해서 컬렉션의 엘리먼트에 해당 데이터 타입만 들어가게 체크.
- 더 이상 형변환을 할 필요가 없게 만들고, 다양한 엘리먼트가 들어갈 때 발생할 수 있는 오류를 원천 차단.
- 1.7(JDK7) 부터 제너릭 표현이 중복된 경우 뒤에 표현을 <>로 생략이 가능( Diamond operation )
클래스에서 제너릭 사용! public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, Serializable
클래스 선언부에 있는 는 유형 매개변수라고 합니다. 객체 생성시 이라고 하면 자리로 들어감. 예) ArrayList myList = new ArrayList<>(); 이라면, 가 자리에 들어감.
- 제너릭 클래스가 가진 변수 타입으로 E를 이용할 수 있습니다. ex) E name;
- 제너릭 클래스가 가진 메서드에서도 인자의 타입이나 리턴타입으로 E를 이용할 수 있음.
package E_java;
import E_java.generic.Person;
public class E11_genericEx {
public static void main(String[] args) {
E_java.generic.Person<Character> p1 = new Person<>('딸', 8);
System.out.println(p1.getName());
Person<String> p2 = new Person<String>("아빠", 45);
System.out.println(p2.getName());
System.out.println(p1.test(4.8));
System.out.println(p1.test("4.8"));
int[] i = {112,3,4,5,6,7,78};
System.out.println(p1.test(i));
}
}
package E_java;
import java.util.ArrayList;
public class E12_genericEx2 {
public static void main(String[] args) {
Wallet<Card, Money> card_wallet = new Wallet<>("파란색");
Wallet<CreditCard, Money> card_wallet2 = new Wallet<>("검은색");
// Wallet<String, Integer> card_wallet3 = new Wallet<>("하늘색");
card_wallet.pouch.add(new CreditCard());
card_wallet.pouch.add(new CheckCard());
card_wallet.pouch.add(new BusCard());
// card_wallet2.pouch.add(new CheckCard());
card_wallet2.pouch.add(new CreditCard());
card_wallet2.pouch2.add(new Dollar());
card_wallet2.pouch2.add(new Won());
//
ArrayList<Integer> int_list = new ArrayList<>();
ArrayList<String> str_list = new ArrayList<>();
ArrayList<Object> obj_list = new ArrayList<>();
str_list.add("제너릭 때문에 문자열만 들어갑니다.!");
str_list.add("이유는? 문자열 제너릭 컬럭션으로 지정되기 때문이죠!");
int_list.add(100);
// int_list.add(new Integer(20));
// obj_list.add(new Person<String>("홍길동", 11));
usingArrayListMethod(obj_list);
usingArrayListMethod(str_list);
usingArrayListMethod(int_list);
usingArrayListMethod(card_wallet);
usingArrayListMethod(card_wallet2);
}
// 제너릭이 다른 것만으로 오버로딩은 할 수 없다는 것!!
// static void usingArrayListMethod(ArrayList<Integer> list) {
// System.out.println(list);
// }
// static void usingArrayListMethod(ArrayList<String> list) {
// System.out.println(list);
// }
// <?> : 와일드 카드. 제너릭으로 오버로드를 구현하고 싶을 때 사용!
static void usingArrayListMethod(ArrayList<?> list) {
System.out.println(list);
}
static void usingArrayListMethod(Wallet<? extends Card, ? extends Money> w) {
System.out.println(w);
}
}
// 제너릭에서 extends는 타입 범위를 제한하는 역할을 하게 됨.
// - One extends Card : 첫번째 타입으로 Card를 상속받는 클래스만 허용!
// - Two extends Money : 두번째 타입으로 Money를 상속받는 클래스만 허용!
class Wallet<One extends Card, Two extends Money> {
ArrayList<One> pouch;
ArrayList<Two> pouch2;
String color;
public Wallet(String color) {
this.pouch = new ArrayList<>();
this.pouch2 = new ArrayList<>();
this.color = color;
}
public One get(int index) {
return pouch.get(index);
}
@Override
public String toString() {
return "지갑의 내용물을 출력합니다.";
}
}
class Card {}
class CreditCard extends Card {}
class CheckCard extends Card {}
class BusCard extends Card {}
class Money {}
class Won extends Money {}
class Dollar extends Money {}
package E_java.generic;
public class Person<E> {
private E name;
private int age;
public Person(E name, int age){
this.age = age;
this.name = name;
}
public Object getName() {
return this.name;
}
public void setName(E name) {
this.name = name;
}
//메서드
//클래스 선언부에서 정의되지((E) 않은 유형 매개변수를 사용하는 방법
public <T extends Object> T test(T t){ //리턴타입이 제너릭이 되었다.
return t;
}
}
File 입출력
package F_java;
import java.io.File;
import java.io.IOException;
public class F01_FileEx {
static String env_path="C:\\Program Files\\Amazon Corretto\\jdk17.0.10_7\\bin;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\Program Files\\firemodels\\SMV6;C:\\Program Files\\firemodels\\FDS6\\bin;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\MinGW\\bin;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Microsoft SQL Server\\150\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn\\;C:\\Program Files\\Amazon\\AWSCLIV2\\;C:\\Users\\hyeonyeong\\AppData\\Roaming\\Python\\Python310\\Scripts;:wq;C:\\Program Files\\n" + //
"odejs;C:\\Program Files\\n" + //
"odejs\\;:wq;C:\\Program Files\\n" + //
"odejs;C:\\Program Files\\dotnet\\;&JAVA_HOME%;;C:\\Program Files\\Docker\\Docker\\resources\\bin;C:\\Users\\hyeonyeong\\AppData\\Local\\Programs\\Python\\Python310\\Scripts\\;C:\\Users\\hyeonyeong\\AppData\\Local\\Programs\\Python\\Python310\\;C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin;C:\\Users\\hyeonyeong\\AppData\\Local\\Programs\\Microsoft VS Code\\bin;C:\\Users\\hyeonyeong\\anaconda3\\envs\\Lecture2022_1_DataAnalysis\\Lib\\site-packages\\parso\\python;C:\\Users\\hyeonyeong\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Python 3.10;C:\\Users\\hyeonyeong\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Python 3.9;C:\\tools\\flutter\\bin;C:\\Program Files\\Git\\cmd;C:\\tools\\dart-sdk\\bin;C:\\Users\\hyeonyeong\\AppData\\Roaming\\Pub\\Cache\\bin;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath\\java.exe;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath\\javaw.exe;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath\\javaws.exe;C:\\Users\\hyeonyeong\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Program Files\\Git\\cmd\\git.exe;C:\\Program Files\\Git\\mingw64\\bin\\git.exe;C:\\Windows\\System32;C:\\Users\\hyeonyeong\\anaconda3\\envs\\server\\Scripts;C:\\Users\\hyeonyeong\\anaconda3\\Lib\\site-packages\\faiss;C:\\ProgramData\\n" + //
"vm;C:\\Program Files\\n" + //
"odejs;C:\\Program Files\\OpenSSL-Win64\\bin;C:\\Users\\hyeonyeong\\AppData\\Roaming\\n" + //
"pm;C:\\Program Files\\JetBrains\\IntelliJ IDEA Community Edition 2022.3.2\\jbr\\bin;C:\\Users\\hyeonyeong\\.dotnet\\tools";
public static void main(String[] args) {
//File객체는 파일과 디렉터리 작업을 위해서 사용하는 객체
File f = new File("C:\\fileTest\\a.txt");
File dir = new File("./"); //현재 작업위치
//1.exits() : 파일 혹은 디렉터리 존재 유무 확인
System.out.println("exits? : "+f.exists());
System.out.println("exists? : " + dir.exists());
//2. isDirectory() : 디렉토리 여부 확인(파일이면 false)
System.out.println("isDirectory? : "+f.isDirectory());
System.out.println("isDirectory? : " + dir.isDirectory());
//3. isAbsolute() : 해당 경로가 절대경로 t/f 확인
System.out.println("isAbsolute() : "+ f.isAbsolute());
System.out.println("isAbsolute() : " + dir.isAbsolute());
// 4. canExecute, canRead, canWrite : 권한 확인
System.out.println("canExecute? : "+f.canExecute());
System.out.println("canRead? : "+f.canRead());
System.out.println("canWrite? : "+f.canWrite());
// 5. getAbsolutePath : 절대 경로 반환 (상대경로의 절대경로를 찾아줌)
System.out.println("./의 실제 위치(절대 경로) : "+dir.getAbsolutePath());
// 6. 부모 폴더를 문자열 반환
System.out.println(f.getParent()); // 문자열
// 7. 부모 폴더를 File 객체로 반환
File f_parent = f.getParentFile(); // File 객체
System.out.println(f_parent);
// 8. static 값들....
System.out.println(File.separator);
System.out.println(File.separatorChar);
System.out.println(File.pathSeparator);
System.out.println(File.pathSeparatorChar);
//환경변수
String[] path = env_path.split(File.pathSeparator);
for (String s:path){
System.out.println(s);
}
//file에 대한 생성 수정 삭제 메서드
File test = new File("C:\\fileTest\\temp\\abc");
//mkdir : 해당 경로에 폴더 생성, 단 경로상 빠진 부분이 없어야 한다.
//mkdirs : 존재하지 않는 부모 경로 폴더까지 모두 포함하여 폴더를 생성
if(!test.exists()){//폴더가 존재하지 않는 경우
test.mkdirs();
}
else{
test.mkdir();
}
//createNewFile : 파일이 없으면 새로 생성
test = new File("C:\\fileTest\\temp\\a.txt");
try {
test.createNewFile();
} catch (Exception e) {
e.printStackTrace();
System.out.println("실패했습니다.");
}
//Delete : 파일 혹은 폴더를 삭제합니다. 단, 폴더는 비어있지 않으면 삭제할 수 없다.
test = new File("C:\\fileTest\\temp\\abc");
test.delete();
// test = new File("C:\\fileTest\\temp\\a.txt");
// test.delete();
// test = new File("C:\\fileTest\\temp");
// test.delete();
//renameTo : 파일이나 폴더의 이름 및 경로를 변경합니다.
test = new File("C:/fileTest/temp");
File dst = new File("C:/fileTest/temp2222");
test.renameTo(dst);
}
}
728x90
반응형
'개발 언어 > JAVA' 카테고리의 다른 글
15. Operator, Stream (0) | 2024.03.27 |
---|---|
14 람다식 (0) | 2024.03.25 |
12 JAVA API (0) | 2024.03.20 |
11 Exception (0) | 2024.03.19 |
10 Interface 인터페이스 (1) | 2024.03.18 |