JAVA

[Java] Collections Framework 예제

SangRok Jung 2022. 7. 28. 15:49
반응형

 

 

 

 

▶ 예제1


- ArrayList에 6개의 int data를 넣고 HashSet, TreeSet, Stack에 차례대로 6개의 데이터를 넣은뒤 stack이 비어있지 않을 때 까지 pop() 시켜 출력하시오.

 

 

public class ex1 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();   //ArrayList : 중복O, 순서 저장 유지
        list.add(3);
        list.add(6);
        list.add(2);
        list.add(2);
        list.add(2);
        list.add(7);
        
        HashSet set = new HashSet(list);    //HashSet : 순서X, 중복X, 제거유리      // 3, 6, 2, 7
        TreeSet tSet = new TreeSet(set);    //TreeSet : 정렬O, 범위탐색O            // 3, 6, 2, 7
        Stack stack = new Stack();          //Stack : FILO구조 
        stack.addAll(tSet);

        while (!stack.isEmpty()) {
            System.out.println(stack.pop());
        }

    }
}

 

 

 

 

 

 

▶ 예제2


- 이름, 반, 번호, 국, 영, 수의 점수가 있는 학생 클래스를 완성하고 ArrayList에 5개의 데이터를 넣은뒤 이름순서대로 출력하시오.

 

class Student implements Comparable {
    String name;
    int ban;
    int no;
    int kor, eng, math;

    public Student(String name, int ban, int no, int kor, int eng, int math){
        this.name = name;
        this.ban = ban;
        this.no = no;
        this.kor = kor;
        this.eng = eng;
        this.math = math;
    }

    int getTotal(){
        return kor + eng + math;
    }

    float getAverage(){
        return (int)((getTotal() / 3f) * 10 + 0.5) / 10f;
    }

    public String toString(){
        return name + ", " + ban + ", " + no + ", " + kor + ", " + eng + ", " + math + ", " + getTotal() + ", " + getAverage();
    }

    @Override
    public int compareTo(Object o) {
        if(o instanceof Student){
            Student tmp = (Student)o;
            return name.compareTo(tmp.name);
        }
        else{
            return -1;
        }
        
    }
}


public class ex2 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Student("이재성", 1, 1, 100, 100, 100));
        list.add(new Student("손흥민", 1, 2, 90, 70, 80));
        list.add(new Student("박지성", 1, 3, 80, 80 ,90));
        list.add(new Student("김무열", 1, 4, 70, 90, 70));
        list.add(new Student("이승우", 1, 5, 60, 100, 80));

        Collections.sort(list);
        Iterator it = list.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }

}

 

 

 

 

 

 

 

▶ 예제3


- 이름, 반, 번호, 국, 영, 수의 점수와 총점, 평균을 구하고 출력하는 기능이 있는 학생 클래스를 완성하고 ArrayList에 5개의 데이터를 넣은뒤 Student Instance들이 반과 번호로 오름차순되게 정렬하시오. (반이 같은 경우 번호를 비교해서 정렬합니다.)

 

class Student {
    String name;
    int ban;
    int no;
    int kor;
    int eng;
    int math;

    Student(String name, int ban, int no, int kor, int eng, int math) {
        this.name = name;
        this.ban = ban;
        this.no = no;
        this.kor = kor;
        this.eng = eng;
        this.math = math;
    }

    int getTotal(){
        return kor + eng + math;
    }

    float getAverage(){
        return (int)(getTotal() / 3f * 10 + 0.5 / 10f);
    }

    public String toString(){
        return name + ", " + ban + ", " + no + ", " + kor + ", " + eng + ", " + math + 
        ", " + getTotal() + ", " + getAverage();
    }
}

class BanNoAscending implements Comparator {
    public int compare(Object o1, Object o2) {
        //반과 번호로 오름차순 되게 정렬 (반이 같은 경우 번호를 비교해서 정렬)
        if(o1 instanceof Student && o2 instanceof Student){
            Student tmp1 = (Student)o1;
            Student tmp2 = (Student)o2;

            int result = tmp1.ban - tmp2.ban;

            if(result == 0){
                return tmp1.no - tmp2.no;
            }
            else{
                return result;
            }
        }
        else{
            return -1;
        }
    }
}

public class ex3 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Student("이재명", 2, 1, 80, 90, 80));
        list.add(new Student("윤석열", 2, 2, 60, 50, 40));
        list.add(new Student("안철수", 1, 3, 100, 100, 20));
        list.add(new Student("최우석", 1, 1, 90, 40, 80));
        list.add(new Student("정우석", 1, 2, 100, 80, 90));

        Collections.sort(list, new BanNoAscending());
        Iterator it = list.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}

 

 

 

 

 

▶ 예제4


- 번호(int)와, 광의여부(boolean)데이터를 가지고 있는 SutdaCard Class에 중복을 허용하지 않게 equals(), hashCode()를 오버라이딩하고 중복된 SutdaCard를 HashSet에 넣어 출력하시오.

 

 

 

▷ 해법


대부분의 경우 서로 다른 객체라도 클래스의 인스턴스변수 값이 같으면, 예를 들어 SutdaCar의 경우 num과 isKwang의 값이 같으면 같은 객체로 인식해야한다. 즉, equals() 의 결과가 true이어야하고, 두 객체의 해시코드(hashCode()를 호출한 결과)가 같아야 한 다. 그래서 equals()와 hashCode()를 적절히 오버라이딩 해줘야 한다.

 

때로는 equals()만 오버라이딩해줘도 되지만, 해시알고리즘을 사용하는 HashSet에 담을 때는 반드시 hashCode()도 오버라이딩해줘야 한다.

 

String클래스의 hashCode()는 객체의 주소가 아닌 문자열의 내용을 기반으로 해시코드를 생성하므로 문자열의 내용이 같으면 항상 같은 값의 해시코드를 반환한다.

SutdaCard의 toString()이 num과 isKwang의 값으로 문자열을 만들어 반환하기 때문에, toString()을 호출한 결과에 hashCode()를 호출함으로써 SutdaCard의 hashCode()를 간단 히 구현할 수 있었다.

 

class SutdaCard{
    int num;
    boolean isKwang;

    SutdaCard(){
        this(1, true);
    }
    SutdaCard(int num, boolean isKwang){
        this.num = num;
        this.isKwang = isKwang;
    }

    @Override
    public boolean equals(Object obj){
        if(obj instanceof SutdaCard){
            SutdaCard c = (SutdaCard)obj;
            return num == c.num && isKwang == c.isKwang;
        }
        else{
            return false;
        }
    }

    @Override
    public int hashCode(){
        return toString().hashCode();
        // return (int)((num) / 10000);
    }

    @Override
    public String toString(){
        return num + (isKwang ? "K" : "");
    }

    // 대부분의 경우 서로 다른 객체라도 클래스의 인스턴스변수 값이 같으면, 
    // 예를 들어 SutdaCard의 경우 num과 isKwang의 값이 같으면 같은 객체로 인식해야한다. 
    // 즉, equals() 의 결과가 true이어야하고, 두 객체의 해시코드(hashCode()를 호출한 결과)가 같아야 한 다. 
    // 그래서 equals()와 hashCode()를 적절히 오버라이딩 해줘야 한다.
    // 때로는 equals()만 오버라이딩해줘도 되지만, 
    // 해시알고리즘을 사용하는 HashSet에 담을 때는 반드시 hashCode()도 오버라이딩해줘야 한다.

    // String클래스의 hashCode()는 객체의 주소가 아닌 문자열의 내용을 기반으로 해시코드를 생성하므로 
    // 문자열의 내용이 같으면 항상 같은 값의 해시코드를 반환한다.
    // SutdaCard의 toString()이 num과 isKwang의 값으로 문자열을 만들어 반환하기 때문에, 
    // toString()을 호출한 결과에 hashCode()를 호출함으로써 SutdaCard의 hashCode()를 간단히 구현할 수 있었다.
}

public class ex4 {
    public static void main(String[] args) {
        SutdaCard c1 = new SutdaCard(3, true);
        SutdaCard c2 = new SutdaCard(3, true);
        SutdaCard c3 = new SutdaCard(1, true);

        HashSet set = new HashSet();
        set.add(c1);
        set.add(c2);
        set.add(c3);

        System.out.println(set);

    }
}

 

 

 

 

 

 

 

▶ 예제5


아래의 코드는 빙고판으로 1~30의 숫자들로 만든것인데 숫자들의 위치가 잘 섞이지 않는 문제가 있다. 이러한 문제가 발생하는 이유와 이 문제를 개선하기 위한 방법을 설멍하고 이를 개선한 새로운 코드를 만드시오.

 

public class smple {
    public static void main(String[] args) {
        Set set = new HashSet();    // HashSet : 순서유지 안되고 중복허용 안됨.
        int[][] board = new int[5][5];

        // set의 사이즈가 25가 될 때 까지 1~30의 난수를 입력.
        // 중복허용안됨.
        for(int i = 0; set.size() < 25; i++){
            set.add((int)(Math.random() * 30) + 1 + "");
        }

        Iterator it = set.iterator();

        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[i].length; j++){
                board[i][j] = Integer.parseInt((String) it.next());     // Iterator를 이용하여 set의 다음 데이터를 Integer와 시켜 board에 넣는다.
                System.out.print((board[i][j] < 10 ? "  " : " " ) + board[i][j]);
            }
            System.out.println();
        }
    } //main
}

 

 

 

▷ 해법


이 문제의 원인은 HashSet이 중복을 허용하지 않고 순서를 유지하지 않기 때문인데 아무리 임의로 순서를 저장해도 Hashing Algorithm 특성상 한 숫자가 특정한 위치에 고정되어 저장되기 때문이다.이 문제를 해결하기 위해서는 저장순서를 유지하는 List와 Collections class를 이용해야한다.set에 저장한 데이터를 list에 옯겨 저장하고 Collections class의 shuffle()을 이용하여 순서를 섞는다.

 

 

public class Exercise11_6 {
    public static void main(String[] args) {
        Set set = new HashSet();    // HashSet : 순서유지 안되고 중복허용 안됨.
        int[][] board = new int[5][5];

        // set의 사이즈가 25가 될 때 까지 1~30의 난수를 입력.
        // 중복허용안됨.
        for(int i = 0; set.size() < 25; i++){
            set.add((int)(Math.random() * 30) + 1 + "");
        }

        List list = new ArrayList();
        list.addAll(set);
        Collections.shuffle(list);

        Iterator it = list.iterator();

        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[i].length; j++){
                board[i][j] = Integer.parseInt((String) it.next());     // Iterator를 이용하여 set의 다음 데이터를 Integer와 시켜 board에 넣는다.
                System.out.print((board[i][j] < 10 ? "  " : " " ) + board[i][j]);
            }
            System.out.println();
        }
    } //main
}
반응형

'JAVA' 카테고리의 다른 글

[Java] Generic Programming  (0) 2022.08.01
[Java] WildCard  (0) 2022.08.01
[Java] Collections Framework - Comparator & Comparable  (0) 2022.07.28
[Java] Collections Framework - Collections method  (0) 2022.07.26
[Java] Collections Framework - Map  (0) 2022.07.26