[JAVA]객체지향(12): 제네릭과 컬렉션 프레임워크

ho's·2022년 4월 27일
1
post-custom-banner

무엇이든 담을 수 있는 상자를 만들어 보자.

public class ObjectBox {
	private Object object;
    
    public void set(Object obj){
    	this.object = obj;
    }
    
    public Object get(){
    	return this.object;
    }
}
  • private Object object;

Object 타입의 private한 필드를 갖고 있다.
get과 set을 통해 object를 얻는다.

다이아그램을 이용해 클래스의 정보를 알 수 도있다!

ObjectBox 클래스 실행시키기

ObjectBoxMain 클래스를 만들고 코드를 작성하자.

위와 같이 코드를 작성할 수 있지만, 형변환을 해줘야 하는 단점이 있다.

제네릭의 탄생

타입을 따로 지정하지 않고, 변수로 지정을 한다.(대부분 T를 이용해서 나타낸다)

GenericBox<String> , GenericBox<Object>와 같이 제레릭 객체를 생성할때 지정된 타입으로 원하는 결과 값을 나타낼 수 있다.

GenericBox

  • T는 제네릭과 관련된 부분이다.
  • 제네릭은 클래스이름 뒤나, 메소드의 리턴타입 앞에 붙을 수 있다.
  • 부분은 T라는 이름의 제네릭 타입을 선언한다는 것을 의미한다.
  • T는 Type의 약자기 때문에 많이 사용되는 문자이지 꼭 T를 쓸필요가 없다.
  • T가 아니라 E나 D등의 단어를 사용해도 된다.

장점

  • 정해진 타입만 사용할 수 있다.
  • 타입을 강제함으로써 컴파일할 때 잘못된 타입의 값이 지정되는 것을 막을 수 있다.

컬렉션 프레임 워크

  • Java Collections Framework 라고 불리워지는 Collections API는 Java2 부터 추가 된 자료구조 클래스 패키지를 말한다.
  • 자료(Data)를 다룰 때 반드시 필요한 클래스의 모음으로써 JAVA프로그래머라면 꼭 숙지하고 있어야만 한다.

CollectionFrameWork의 다이어그램

java.util.List 인터페이스

  • java.util.List 인터페이스는 순서가 중요한 자료를 다룰때 사용하는 인터페이스이다.

  • Collection을 상속받음으로써 Collection이 가지고 있는 add(), size(), iterator() 메소드를 사용할 수 있다.

  • 해당 인터페이스는 순서를 알고 있다고 가정하기 때문에 특정 순서로 저장된 자료를 꺼낼 수 있는 get(int) 메소드를 가지고 있다.

    java.util.Set 인터페이스

  • java.util.Set 인터페이스는 중복을 허용하지 않는 자료를 다룰 때 사용하는 인터페이스이다.

  • 중복을 허용하지 않는 다는 것은 같은 값을 저장할 수 없다는 것이다.

  • 같은 값을 여러번 추가하여도 마지막 값 하나만 저장됨을 의미한다.

  • Set인터페이스에 저장되는 객체들 Object가 가지고 있는 equals()메소드와 hashCode()메소드를 오버라이딩 해야한다.

    java.util.Iterator 인터페이스

  • java.util.Iterator 인터페이스는 자료 구조에서 자료를 꺼내기 위한 목적으로 사용되는 인터페이스이다.

  • Iterator 패턴을 구현하고 있다.

    java.util.Map 인터페이스

  • java.util.Map 인터페이스는 키(Key)와 값(Value)를 함께 저장하기 위한 목적으로 만들어진 인터페이스이다.

  • 같은 key값으론 하나의 값만 저장할 수 있다.

    제네릭을 사용하지 않고 ArrayList사용하기

    ArrayList의 공식문서를 살펴보자
    https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html

    ArrayList는 타입이 정해져있지 않은 것들을 List형태로 여러개 가질 수 있는것이다.

    1. 제네릭을 사용하지 않고 ArrayList 사용하기

    2. 제네릭을 사용하여 나타내 보자.

    Collection & Iterator

  • Collection<String> collection = new ArrayList<>();
    ArrayList객체 이지만, 참조 타입은 Collection이다.
    이렇게 쓸 수 있는 이유는 ArrayList클래스는 List인터페이스를 구현하고 있다.
    그리고 List인터페이스는 Collection을 상속받고 있다. 따라서 위와 같은 문법이 성립한다.

    Collection은 add메소드, size메소드를 구할 수 있다.

    실제 만들어지는 List는 ArrayList이지만, 참조하는 타입이 Collection이면 참조 타입의 메소드만 사용이 가능하다

    collection에 담겨있는 값을 꺼내고 싶으면, 아래의 코드
    Iterator<String> iter = collection.iterator(); 를 이용해서 꺼내야 한다.

    while(iter.hasNext()){
    	String str = iter.next();
    	System.out.println(str);
    }
  • iter에 값이 있다면 str에 iter.next();의 값이 담긴다.

  • str을 출력한다.

    결과 값은..

    위에서 collection은 순서가 없다고 했는데, 어떻게 순서대로 출력이 될까??

    그것은 바로 Collection을 구현하고 있는것이 ArrayList이기 때문이다.

만약 아래와 같이HashSet으로 구현이 되었다면,

다음과 같이 순서와 상관없이 출력이 된다.

Collection을 구현할 수 있는 객체는 어떤 것이 있을까?

API를 살펴보자!

보는 바와 같이 많이 있다!

다 외워야 할까?

자전거의 종류에는 여러 종류가 있다.

로드, MTB, 전기자전거 ...

하지만 자전거를 타는 방법만 알고 있다면 종류별로 자전거를 타는데에 큰 어려움을 겪지 않을 것이다.

즉 코드를 작성할 때 다음과 같은 형식을 따르도록 하자.

인터페이스의 Type = new (인터페이스를 구현하고있는 클래스(인스턴스))

이렇게 했을때, 더 나은 인스턴스가 있다면 이 부분만 변경을 하면 된다!

인터페이스를 먼저 선언하는 습관을 들이자!

  • 프로그램을 잘 짜려면, 인터페이스 부터 선언해라!

Set

Set<String> set = new HashSet<>();

HashSet은 클래스
Set은 인터페이스

set은 중복을 허락하지 않고, 순서를 상관하지 않기때문에 위와같이 출력이 된다.

Set 예제2

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SetExam2 {
    public static void main(String[] args) {
        Set<MyData> mySet = new HashSet<>();
        mySet.add(new MyData("kim", 500));
        mySet.add(new MyData("lee", 200));
        mySet.add(new MyData("hong", 800));
        
        Iterator<MyData> iterator = mySet.iterator();
        while(iterator.hasNext()){
            MyData myData = iterator.next();
            System.out.println(myData);
        }
    }
}

    class MyData{
        private String name;
        private int value;

        public MyData(String name, int value){
            this.name = name;
            this.value = value;
        }

        public String getName(){
            return name;
        }

        public int getValue(){
            return value;
        }
    }

위의 코드에 대한 결과값은..

이다.

이유는 toString()을 오버라이딩 하지 않았기 때문이다!

위와 같이 오버라이딩을 해주자!

HashSet

다음과 같이 HashSet에 데이터 A를 저장할 때 다음과 같은 일이 발생한다.

  • A라는 객체에서 hashCode()를 추출한다.

  • hashCode() 값이 라고 하면, 의 버킷을 생성한다.

    A,B,C 의 Data를 저장한다고 하자.

    위와 같이 어떤 Data를 HashSet에 저장 할 때, 2가지의 메소드가 사용된다.

  • hashCode()

  • equals()

    Set은 중복 data를 허용하지 않으므로, 넣으려는 Data가 해당 버킷에 같은 값이 있는지 equals 메소드를 통해 확인한다.

    HashSet을 사용해 보자.

  package totojava.com.example;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SetExam2 {
    public static void main(String[] args) {
        Set<MyData> mySet = new HashSet<>();
        mySet.add(new MyData("kim", 500));
        mySet.add(new MyData("lee", 200));
        mySet.add(new MyData("hong", 800));
        mySet.add(new MyData("hong", 800));

        Iterator<MyData> iterator = mySet.iterator();
        while(iterator.hasNext()){
            MyData myData = iterator.next();
            System.out.println(myData);
        }
    }
}
    class MyData{
        private String name;
        private int value;
        @Override
        public String toString() {
            return "MyData{" +
                    "name='" + name + '\'' +
                    ", value=" + value +
                    '}';
        }
        public MyData(String name, int value){
            this.name = name;
            this.value = value;
        }
        public String getName(){
            return name;
        }
        public int getValue(){
            return value;
        }
    }

위에 대한 결과 값은
이다. 중복을 허용하고 있다.

그 이유는 HashSet메소드인 hashCode(), equals()를 사용하지 않았기 때문이다.

위의 코드를 작성하지 않으면, MyData의 equals와 hashCode를 사용하게 되는데, 이는 쓸모가 없다.

따라서 아래와 같이 hashCode의 메소드를 실행 시켜주자.

Map

  • Map은 Key와 Value를 갖는다.

  • 같은 key값에 다른 value를 넣어주면, 새로운 값이 넣어진다.

    Map의 key, value값 꺼내기

    정렬하기

    Collections 클래스의 메소드를 이용해 정렬 할 수 있다.

    섞기

    Collections 클래스의 메소드를 이용해 섞을 수 있다.

profile
그래야만 한다
post-custom-banner

0개의 댓글