티스토리 뷰

Academy

[210217]자바 API

VIRGIL ABLOH 2021. 2. 24. 00:59
반응형

- 학습 목표 달성 확인 목록

- [] ArrayList 클래스를 사용할 수 있는가?

public class Exam0120 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("111");//순서대로 데이터삽입
        list.add("222");
        list.add("333");
        list.add("444");
        list.add("555");
        System.out.println("1." + list);

        System.out.println("2." + list.get(2));//해당 인덱스 데이터 call

        list.add(1, "1212");//해당 인덱스를 1212를 삽입(이렇게 되면 중간에 끼어든다)

        list.set(3, "123123");//해당 인덱스를 123123으로 교체
        System.out.println("3." + list);

        list.remove(1);//해당 인덱스를 삭제
        System.out.println("4." + list);

        list.remove("222");//해당 데이터를 삭제
        System.out.println("5." + list);

        list.clear();//배열전체 삭제
        System.out.println("6." + list);
    }

//결과
1.[111, 222, 333, 444, 555]
2.333
3.[111, 1212, 222, 123123, 444, 555]
4.[111, 222, 123123, 444, 555]
5.[111, 123123, 444, 555]
6.[]

 

- [] LinkedList 클래스를 사용할 수 있는가?

public class Exam0110 {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        list.add("a");//순서대로 데이터삽입
        list.add("b");
        list.add("c");
        System.out.println("1." + list);

        System.out.println(list.get(1));//해당 인덱스 데이터 call
        
        list.add(1, "d");//해당 인덱스에 데이터 삽입(중간에 끼어든다)
        System.out.println("2." + list);

        list.remove(1);//해당 인덱스 데이터 삭제
        System.out.println("3." + list);

        list.clear();//전체 삭제
        System.out.println("4." + list);

    }
}

//결과
1.[a, b, c]
b
2.[a, d, b, c]
3.[a, b, c]
4.[]

 

- [] ArrayList와 LinkedList의 차이점을 설명할 수 있는가?

-메모리 측면

[ArrayList]

일반 배열처럼 고정 크기를 갖는다.

그래서 크기를 초과하면 새로운 배열을 만들고 복사하기때문에 GC가 발생하여 메모리낭비가 생긴다.

[LinkedList]

값을 넣을때 마다 새 메모리가 추가되는 가변 크기의 형태이며 ArrayList보다 메모리 낭비가 덜하다.

-속도 측면

[ArrayList]

배열 특성처럼 인덱스를 이용하여 특정 항목을 찾기때문에 속도가 빠르다

삭제할 때 이전 항목을 당겨오기때문에 속도가 느리다

삽입할때 현재 항목을 다음 항목으로 밀리기때문에 속도가 느리다

[LinkedList]

인덱스를 이용하여 특정 항목을 찾을 때는 리스트의 처음부터 찾아야하기 때문에 속도가 느리다

삭제할 때 이전 항목과 다음 항목을 바로 연결하면 되기때문에 속도가 빠르다

삽입할 때 현재 항목과 다음 항목을 새 항목과 연결하면 되기 때문에 속도가 빠르다

 

- [] HashSet 클래스를 사용할 수 있는가?

public class Exam0110 {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();

        // Set에 값 추가하기
        set.add("aaa");
        set.add("bbb");
        set.add("ccc");
        System.out.println(set);

        // Set은 집합의 특성을 따른다.
        // 같은 값을 중복해서 넣을 수 없다.
        set.add("aaa");
        set.add("bbb");
        System.out.println(set);

        // null을 넣을 수 있다. 단 중복해서 넣을 수 없다.
        set.add(null);
        set.add(null);

        System.out.println(set);
        //출력하면 입력한 순서대로가 아닌 이유는
        //저장할 때 각 인스턴스의 hashCode() 리턴 값으로 위치를 정하기 때문이다.
    }
}

 

- [] Hash 알고리즘에 따라 데이터를 저장하는 방법을 아는가?

HashSet과 사용자 정의 데이터 타입

public class Exam0310 {
    static class Member {
        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 +
                    '}';
        }
    }

    public static void main(String[] args) {
        Member m1 = new Member("오", 10);
        Member m2 = new Member("은", 20);
        Member m3 = new Member("석", 30);
        Member m4 = new Member("옹", 40);

        Member m5 = new Member("오", 10);

        HashSet<Member> set = new HashSet<>();
        set.add(m1);
        set.add(m2);
        set.add(m3);
        set.add(m4);

        set.add(m5);//m1과 같은 값을 저장한다
        /*
        하지만 출력해보면 저장되는것을 확인할수 있다
        그 이유는 기본적인 hashCode()와 equals()의 리턴값으로 판단하는데 
        여기서 오버라이딩을 하지 않았기에 필터링을 하지 못한 것이다.
        Object의 hashCode()는 인스턴스가 다르면 무조건 다른 해시값을 리턴한다
        Object의 equals()는 인스턴스의 주소가 같은지 검사한다
        그래서 m1과 m5가 같은 데이터인데도 인스턴스가 다르기 때문에 같은 값으로 간주하지 않는것이다.
         */
        System.out.println(set);
    }
}

//결과
[Member{name='은', age=20}, Member{name='옹', age=40}, Member{name='석', age=30}, Member{name='오', age=10}, Member{name='오', age=10}]

hachCode()와 equals() 오버라이딩 후

public class Exam0340 {
    static class Member {
        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 boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Member member = (Member) o;
            return age == member.age && Objects.equals(name, member.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    }

    public static void main(String[] args) {
        Member m1 = new Member("오", 10);
        Member m2 = new Member("은", 20);
        Member m3 = new Member("석", 30);
        Member m4 = new Member("옹", 40);

        Member m5 = new Member("오", 10);

        HashSet<Member> set = new HashSet<>();
        set.add(m1);
        set.add(m2);
        set.add(m3);
        set.add(m4);

        set.add(m5);//m1과 같은 값을 저장하지만 equals()과 hashCode() 오버라이딩을 하였기에 필터링되어 저장되지 않는다

        System.out.println(set);
    }
}

//결과
[Member{name='석', age=30}, Member{name='옹', age=40}, Member{name='은', age=20}, Member{name='오', age=10}]

 

- [] HashSet에 저장할 객체는 반드시 hashCode()와 equals()를 오버라이딩 해야 하는 이유를 아는가?

HashSet이 중복 여부를 검사할 때 hashCode()와 equals()의 리턴값으로 판단한다.

하지만 오버라이딩을 하지 않았기 때문에 기본적인 알고리즘으로

일단 hashCode()는 인스턴스가 다르면 무조건 다른 해시값을 리턴하고

equals()는 인스턴스 주소가 같은지 검사한다

그래서 데이터가 같더라도 인스턴스가 다르기때문에 같은값으로 간주하지 않은것이다.

 

 

- [] HashSet의 값 목록을 조회할 수 있는가?

//해쉬셋 값 목록 조회?

 

- [] HashMap 클래스를 사용할 수 있는가?

public class Exam0111 {
    public static void main(String[] args) {
        HashMap<Integer, Member> map = new HashMap<>();

        //여기서 100,200은 key의 역할을 한다 어떠한 객체도 가능하다
        map.put(100, new Member("오", 20));
        map.put(200, new Member("은", 30));
        map.put(300, new Member("석", 40));
        map.put(400, new Member("옹", 50));
        //그렇지만 key는 객체가 아니다
        //그러나 auto-boxing을 통해 Integer 객체로 변환된다.

        System.out.println(map.get(100));
        System.out.println(map.get(200));
        System.out.println(map.get(300));
        System.out.println(map.get(400));
       
    }
}

//결과
Member{name='오', age=20}
Member{name='은', age=30}
Member{name='석', age=40}
Member{name='옹', age=50}

 

- [] HashMap의 key 목록을 다룰 수 있는가?

public class Exam0120 {
    public static void main(String[] args) {
        class MyKey {
            String major;
            int no;

            public MyKey(String major, int no) {
                this.major = major;
                this.no = no;
            }

            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (o == null || getClass() != o.getClass()) return false;
                MyKey myKey = (MyKey) o;
                return no == myKey.no && Objects.equals(major, myKey.major);
            }

            @Override
            public int hashCode() {
                return Objects.hash(major, no);
            }

            @Override
            public String toString() {
                return "MyKey{" +
                        "major='" + major + '\'' +
                        ", no=" + no +
                        '}';
            }
        }

        MyKey k1 = new MyKey("컴공", 1);
        MyKey k2 = new MyKey("컴공", 2);
        MyKey k3 = new MyKey("컴공", 3);
        MyKey k4 = new MyKey("컴공", 4);
        MyKey k5 = new MyKey("컴공", 5);

        HashMap<MyKey, Member> map = new HashMap<>();

        map.put(k1, new Member("홍길동", 20));
        map.put(k2, new Member("임꺽정", 30));
        map.put(k3, new Member("유관순", 16));
        map.put(k4, new Member("안중근", 30));
        map.put(k5, new Member("윤봉길", 25));

        System.out.println(map.get(k1));
        System.out.println(map.get(k2));
        System.out.println(map.get(k3));
        System.out.println(map.get(k4));
        System.out.println(map.get(k5));
        System.out.println("-------------------------");

        MyKey k6 = new MyKey("컴공", 3);
        System.out.println(k3 == k6);
        System.out.printf("equals(): %b\n", k3.equals(k6));//같은 해쉬코드의 값인지 확인
        System.out.printf("hashCode(): %d, %d\n", k3.hashCode(), k6.hashCode());//확인해보니 다르다
        System.out.println("-----------------------------------");

        System.out.println(map.get(k6));
        // k6로 값을 찾으면 없다고 나온다.
        // 이유?
        // - 값을 저장할 때,
        //   key 객체의 hashCode() 리턴 값으로 위치를 계산하여 저장한다.
        // - 값을 꺼낼 때,
        //   key 객체의 equals()의 리턴 값으로 같은 Key 인지 검사한다.
        //   key 객체의 hashCode() 리턴 값으로 위치를 계산한다.
        // - 따라서 hashCode()의 리턴 값과
        //   equals()의 비교 결과가 다르다고 나오면
        //   같은 key가 아니기 때문에 값을 꺼낼 수 없다.
        // - 우리가 사용한 MyKey 클래스는 hashCode()와 equals()를
        //   오버라이딩 하지 않았기 때문에,
        //   인스턴스 필드의 값이 같더라도 인스턴스가 다르면
        //   hashCode()의 리턴 값이 다르게 나온다.
        //   equals() 또한 false를 리턴한다.
        //
        // 해결책?
        // - 인스턴스가 다르더라도 인스턴스 필드의 값이 같을 때는
        //   hashCode()의 리턴 값이 같게 오버라이딩 하라!
        //   또한 equals()의 리턴 값이 true가 되게 오버라이딩 하라!
    }
}

//결과
Member{name='홍길동', age=20}
Member{name='임꺽정', age=30}
Member{name='유관순', age=16}
Member{name='안중근', age=30}
Member{name='윤봉길', age=25}
-------------------------
false
equals(): true
hashCode(): 52287331, 52287331
-----------------------------------
Member{name='유관순', age=16}

 

- [] HashMap의 value 목록을 다룰 수 있는가?

public class Exam0220 {
    public static void main(String[] args) {
        HashMap<String, Member> map = new HashMap<>();
        map.put("s01", new Member("홍길동", 20));
        map.put("s02", new Member("임꺽정", 30));
        map.put("s03", new Member("유관순", 16));
        map.put("s04", new Member("안중근", 20));
        map.put("s05", new Member("윤봉길", 30));

        // key 객체는 중복되어서는 안되기 때문에
        // key 객체 목록은 Set 에 담아서 리턴한다.
        // value 객체는 중복 저장될 수 있기 때문에
        // value 객체 목록은 Collection 에 담아서 리턴한다.
        Collection<Member> values = map.values();
        for (Member value : values) {
            System.out.println(value);
        }
    }
}

//결과
Member{name='임꺽정', age=30}
Member{name='홍길동', age=20}
Member{name='안중근', age=20}
Member{name='유관순', age=16}
Member{name='윤봉길', age=30}

 

- [] HashMap과 Hashtable의 차이점을 설명할 수 있는가?

HashMap HashTable
null을 key로 사용가능 null을 key로 사용불가능
null을 value로 사용가능 null을 value로 사용불가능
동기화 지원하지 않는다 동기화 지원한다.
멀티스레드가 동시에 사용할 때 문제가 발생할수 있지만
실행속도가 빠르다
 
key과 value에 null을 사용하고 싶다면 HashMap key과 value에 null을 사용하고 싶지않다면 HashTable

 

- [] List와 Set, Map의 차이점을 설명할 수 있는가?

반응형

'Academy' 카테고리의 다른 글

[210219]제네릭  (0) 2021.02.25
[210218]Command Design Pattern  (0) 2021.02.24
[210216]제네릭  (0) 2021.02.23
[210215]인터페이스/추상클래스  (0) 2021.02.16
[210210]추상클래스와 인터페이스  (0) 2021.02.12
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함