Cohe

13 객체 정렬을 위한 객체 간 크기 비교, 제너릭 , File 입출력 본문

개발 언어/JAVA

13 객체 정렬을 위한 객체 간 크기 비교, 제너릭 , File 입출력

코헤0121 2024. 3. 21. 18:10
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);


    }
}

'개발 언어 > 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