제네릭

제네릭은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다.
제네릭스는 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일시의 타입체크를 해주는 기능이다.

사용해야 하는 이유

잘못된 타입이 될 수 있는 문제를 컴파일 과정에서 제거할수 있다. 자바 컴파일러는 코드에서 잘못 사용된 타입 때문에 발생하는 문제점을 제거하기 위해 제네릭 코드에 대한 강한 타입 체크를 한다.
실행 시 타입에러가 나는 것보다는 컴파일 시에 미리 타입을 강하게 체크해서 에러를 사전에 방지하는 것이 좋다. 또 제네릭 코드를 사용하면 타입을 국한하기 때문에 요소를 찾아올 때 타입 변환을 할 필요가 없어 프로그램 성능이 향상되는 효과를 얻을 수 있다.
예시

ArrayList list = new ArrayList(); //제네릭을 사용하지 않을경우
list.add("test");
String temp = (String) list.get(0); //타입변환이 필요함
        
ArrayList<String> list2 = new ArrayList(); //제네릭을 사용할 경우
list2.add("test");
temp = list2.get(0); //타입변환이 필요없음

사용법

제네릭 타입은 타입을 파라미터로 가지는 클래스와 인터페이스이다. 제네릭 타입은 클래스 또는 인터페이스 이름 뒤에 < >를 쓰고 사이에 타입 파라미터가 위치한다.

public class 클래스명<T> {...}
public interface 인터페이스명<T> {...}

타입인자

타입인자 설명
T Type
E Element
K Key
N Number
V Value
R Result

Comment and share

ListIterator

ListIterator인터페이스는 Iterator인터페이스를 상속받아 여러 기능을 추가한 인터페이스이다.
Iterator인터페이스는 컬렉션의 요소에 접근할 때 한 방향으로만 이동할 수 있다.
Listiterator 인터페이스는 컬렉션 요소의 대체, 추가 그리고 인덱스 검색 등을 위한 작업에서 양방향으로 이동하는 것을 지원한다.
단, Listeriterator인터페이스는 List인터페이스를 구현한 List컬렉션 클래스에서만 Listiterator()메소드를 통해 사용할 수 있다.
예제

LinkedList<Integer> lnkList = new LinkedList<Integer>();

lnkList.add(4);
lnkList.add(2);
lnkList.add(3);
lnkList.add(1);

ListIterator<Integer> iter = lnkList.listIterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " ");
}

while (iter.hasPrevious()) {
    System.out.print(iter.previous() + " ");
}

결과값

4 3 2 1
1 3 2 4

Comment and share

오름차순 정렬

Arrays.sort()메서드의 매개값으로 기본 타입 배열이나 String배열을 지정해주면 자동으로 오름차순 정렬이 된다.
예제

import java.util.Arrays;

public class Sort{
    public static void main(String[] args)  {
        int arr[] = {4,23,33,15,17,19};
        Arrays.sort(arr);
        
        for (int i : arr) {
            System.out.print("["+i+"]");
        }
    }
}

결과값

[4][15][17][19][23][33]

내림차순 정렬

배열을 내림차순으로 정렬할 때는 Collections 클래스의 reverseOrder() 함수를 사용하면 된다. 만약 기본 타입 배열을 내림차순으로 정렬하고 싶다면 기본 타입의 배열을 래퍼클래스로 만들어 Comparator를 두번째 인자에 넣어주어야 역순으로 정렬할 수 있다.

import java.util.Arrays;

public class Sort{
    public static void main(String[] args)  {
        Integer arr[] = {4,23,33,15,17,19};
        Arrays.sort(arr,Collections.reverseOrder());
        
        for (int i : arr) {
            System.out.print("["+i+"]");
        }
    }
}

결과값

[33][23][19][17][15][4]

배열 일부분만 정렬

Arrays.sort()메서드의 매개값으로 배열, 시작 index, 끝 index를 넣어주면 일부분만 정렬할 수 있다.

import java.util.Arrays;

public class Main{
public static void main(String[] args)  {
        int arr[] = {4,23,33,15,17,19};

        Arrays.sort(arr, 0, 4); // 0,1,2,3 요소만 정렬
        
        for (int i : arr) {
            System.out.print("["+i+"]");
        }
    }
}

결과값

[4][15][23][33][17][19]

Comment and share

Stack과 Queue

Stack은 LIFO(Last in first out) Queue는 FIFO(First in first out)으로 되어있다.

Stack의 메서드

메서드 설명
boolean empty( ) Stack 이 비어있는지 알려줌
Object peek( ) Stack 의 맨 위에 저장된 객체를 반환pop( ) 과 달리 Stack 에서 객체를 꺼내지 않음(비었을 때는 EmptyStackException 발생)
Object pop( ) Stack 의 맨 위에 저장된 객체를 꺼냄(비었을 때는 EmptyStackException 발생)
Object push(Object item) Stack 에 객체( item )를 저장
int search(Object o) Stack 에서 주어진 객체( o )를 찾아서 그 위치를 반환, 못 찾으면 -1 을 반환(배열과 달리 위치가 1부터 시작)

Queue의 메서드

메서드 설 명
boolean add(Object o) 지정된 객체를 Queue 에 추가 성공하면 true를 반환, 저장공간이 부족하면 IllegalStateException 발생
Object remove( ) Queue 에서 객체를 꺼내 반환. 비어있으면 NoSuchElementException 발생
Object element( ) 삭제없이 요소를 읽어옴 peek 와 달리 Queue 가 비었을때 NoSuchElementException 발생
boolean offer(Object o) Queue 에 객체를 저장 성공하면 true, 실패하면 false를 반환
Object poll( ) Queue 에서 객체를 꺼내서 반환. 비어있으면 null을 반환
Object peek( ) 삭제없이 요소를 읽어온다. Queue가 비어있으면 null을 반환
예제
package Example;

import java.util.*;

public class Example {
    public static void main(String[] args) {
        Stack st = new Stack();
        Queue q = new LinkedList();    //Queue의 인터페이스 구현체인 LinkedList를 사용
        
        st.push("0");
        st.push("1");
        st.push("2");
        
        q.offer("0");
        q.offer("1");
        q.offer("2");
        
        System.out.println("=== Stack ===");
        while(!st.isEmpty()) {
            System.out.println(st.pop());
        }
        
        System.out.println("=== Queue ===");
        while(!q.isEmpty()) {
            System.out.println(q.poll());
        }
    }
}

결과값

===Stack===
2
1
0
===Queue===
0
1
2

자베에서는 스택을 Stack클래스로 구현하여 제공하지만 큐는 Queue인터페이스만 있고 별도의 클래스가 없다. 그래서 Queue인터페이스를 구현한 클래스들을 사용해야 한다.

Comment and share

HashMap

  • Map의 일종으로 key와 value의 쌍으로 이루어진 데이터를 보관한다.
  • null key와 null value를 모두 허용한다.
  • 내부적을 데이터에 접근할 때 동기화를 보장하지 않는다.
  • 데이터의 순서를 보장하지 않는다.
  • 중복된 key값을 허용하진 않지만, 중복된 값은 가질 수 있다.

Comment and share

hashtable

hashtable은 Map을 상속받아 key,value 형태를 가지게 된다.
key,value는 한쌍으로 사용되며 key로 식별용 값, value는 사용할 값을 넣는 식이다.

HashMap과 상당히 비슷한데 완전 똑같은 것은 아니므로 비교해 보자면

  1. HashTable은 동기화가 되어 있으나, HashMap은 동기화 되어있지 않다.

  2. HashTable은 key, value에 null값을 허용하지 않지만 HashMap은 허용한다.

     Hashtable 안에 값 넣기
     Hashtable.put(key, value);
    
     Hashtable 안의 값 가져오기
     Hashtable.get(key);
    
     Hashtable 안의 값 바꾸기
     Hashtable.replace(key, value);
    
     Hashtable 안의 내용 삭제하기
     Hashtable.remove(key);
    
     Hashtable의 크기 0인지 확인하기
     Hashtable.isEmpty();
     
     Hashtable 사이즈 확인하기
     Hashtable.size();
     
     Hashtable 안에 특정 Key, Value 들었는지 확인하기
     Hashtable.containsKey(key);
     Hashtable.containsValue(value);
    
     Hashtable 안에 들어있는 전체 Key 확인하기
     Hashtable.keySet();
     import java.util.Hashtable;
    

예제

public class HashTableExample {

    public static void main(String[] args) {
        Hashtable<Integer, String> ht = new Hashtable<Integer, String>();
        ht.put(0, "철수");
        ht.put(1, "영희");
        ht.put(2, "영수"); // Hashtable에 값 삽입
        ht.replace(2, "수철"); // Hashtable 값 바꾸기
        ht.remove(2); // Hashtable 값 삭제

        for(int i = 0; i<ht.size(); i++) {
            System.out.println(ht.get(i)); // Hashtable 값 출력
        }
        
        System.out.println("Hashtable 크기 : " + ht.size());
        System.out.println("Hashtable key 확인 : " + ht.containsKey(2));
        System.out.println("Hashtable value 확인 : " + ht.containsValue("수철"));
        System.out.println("Hashtable 크기 0인지 확인 : " + ht.isEmpty());
        System.out.println("Hashtable 전체 Key 확인 : " + ht.keySet());
        
    }

}
결과값
철수
영희
Hashtable 크기 : 2
Hashtable key 확인 : false
Hashtable value 확인 : false
Hashtable 크기 0인지 확인 : false
Hashtable 전체 key 확인 : [1, 0]    

Comment and share

new 연산자

클래스 객체변수 = new 클래스();

인스턴스를 생성할 때 사용하는 코드이며 객체 변수가 실제 데이터가 아닌 참조 값을 갖는다는 내용이 포함되어 있다.
new는 클래스 타입의 인스턴스를 생성해주는 역할을 담당한다.
new연산자를 통해 메모리(Heap 영역)에 데이터를 저장할 공간을 할당받고 그 공간의 참조값을 객체에게 반환하여 주고 이어서 생성자를 호출하게 된다. 인스턴스를 핸들하기 위해서는 new 연산자를 통해 참조값을 저장한 객체로만 접근이 가능하다.

클래스      객체변수    =    new        클래스();
자료형      참조값저장     메모리할당   생성자호출

Comment and share

VO(Value Object)

  • 불변성 - 수정자(Setter)가 없다.
  • 값 동등성 - 내부 값 동등성 검사
  • 자가 유효성 검사 - 생성자에서 validate

불변성

Value Object는 불변이다.
불변이라는 뜻은 한번 생성되면 이후 내부 값을 바꿀 수 없음을 의미한다. 즉 setter를 허용하지 않는다는 말이다.

Value Object는 코드의 다른 부분에서 수정되지 않기 때문에 Reference로 공유할 수 있다. 이것은 코드의 복잡성과 부하를 극적으로 감소시킨다. 또한 Multi-thread환경에서 그 이점이 뚜렷해진다.

# 생성된 이후에는, 수정자(setter)를 통해 수정되지 않습니다. 
final class Number{

        private int number;
        
        public Number(int number){
                this.number = number;
        }
}

값 동등성

‘동일성’ 식별자를 기반으로 객체가 같은지를 판단할 수 있는 성질
‘동등성’ 상태를 이용해 두 값이 같은지 판단할 수 있는 성질

자가 유효성 검사

생성자가 주입될 때 값의 유효성을 확인해야 한다. 유효하지 않으면 의미있는 에러를 표출한다. 이는 객체의 인스턴스에 더이상 if가 없음을 의미한다. 모든 유효성 검사는 생성 시간에 이루어진다.

이러한 강제 유효성 검사는 의미 있고 명시적인 방법으로 도메인 제약 조건을 표현하는데도 유용하다.

Comment and share

List 컬렉션

List 컬렉션은 배열과 비슷하게 객체를 인덱스로 관리한다. 배열과의 차이점은 저장용량이 자동으로 증가하며, 객체를 저장할 때 자동 인데그삭 부여된다는 것이다. 그리고 추가, 삭제, 검색을 위한 다양한 메소드들이 제공된다.

List 컬렉션은 객체 자체를 저장하는 것이 아니라 객체의 번지를 참조한다. 그렇기 때문에 동일한 객체를 중복 저장할 수 있는데, 이 경우 동일한 번지가 참조된다. null도 저장이 가능하며, 이 경우 해당 인덱스는 객체를 참조하지 않는다.

ArrayList 클래스

ArrayList클래스는 가장 많이 사용되는 컬렉션 클래스 중 하나이다.
내부적으로 배열을 이용하여 요소를 저장한다.

ArrayList클래스는 배열을 이용하기 때문에 인덱스를 이용해 배열요소에 빠르게 접근할 수 있다.
하지만 배열은 크기를 변경할 수 없는 인스턴스이므로, 크기를 늘리기 위해서는 새로운 배열을 생성하고 기존의 요소들을 옮겨야 하는 복잡한 과정을 거쳐야 한다.
물론 이 과정은 자동으로 수행되지만, 요소의 추가 및 삭제 작업에 걸리는 시간이 매우 길어지는 단점을 가지게 된다.

ArrayList<Integer> arrList = new ArrayList<Integer>();

// add() 메소드를 이용한 요소의 저장
arrList.add(40);
arrList.add(20);
arrList.add(30);
arrList.add(10);

// for 문과 get() 메소드를 이용한 요소의 출력
for (int i = 0; i < arrList.size(); i++) {
    System.out.print(arrList.get(i) + " ");
}

// remove() 메소드를 이용한 요소의 제거
arrList.remove(1);

// Enhanced for 문과 get() 메소드를 이용한 요소의 출력
for (int e : arrList) {
    System.out.print(e + " ");
}

// Collections.sort() 메소드를 이용한 요소의 정렬
Collections.sort(arrList);

// iterator() 메소드와 get() 메소드를 이용한 요소의 출력
Iterator<Integer> iter = arrList.iterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " ");
}

// set() 메소드를 이용한 요소의 변경
arrList.set(0, 20);

for (int e : arrList) {
    System.out.print(e + " ");
}

// size() 메소드를 이용한 요소의 총 개수
System.out.println("리스트의 크기 : " + arrList.size());

결과값

40 20 30 10 
40 30 10
10 30 40 
20 30 40
리스트의 크기 : 3

LinkedList 클래스

LinkedList클래스는 ArrayList클래스가 배열을 이용하여 요소를 저장함으로써 발생하는 단점을 극복하기 위해 고안되었다.
LinkedList클래스는 내부적으로 연결리스트를 통해 요소를 저장한다.

배열은 저장된 요소가 순차적으로 저장된다.
하지만 연결리스트는 저장된 요소가 비순차적으로 분포되며, 이러한 요소들 사이를 링크로 연결하여 구성한다.
다음 요소를 가리키는 참조만을 가지는 연결 리스트를 단일 연결리스트라고한다.

이러한 단일 연결리스트는 요소의 저장과 삭제 작업이 다음요소를 가리키는 참조만 변경하면 되므로, 아주 빠르게 처리된다.
하지만 단일 연결리스트는 현재 요소에서 이전요소로 접근하기가 매우 어렵다.

따라서 이전 요소를 가리키는 참조도 가지는 이중 연결 리스트가 좀더 많이 사용된다.

LinkedList클래스도 이중 연결 리스트를 내부적으로 구현한 것이다.
또한, LinkedList클래스 역시 List인터페이스를 구현하므로, ArrayList클래스와 사용할 수 있는 메소드가 거의 같다.

LinkedList<String> lnkList = new LinkedList<String>();

// add() 메소드를 이용한 요소의 저장
lnkList.add("넷");
lnkList.add("둘");
lnkList.add("셋");
lnkList.add("하나");

// for 문과 get() 메소드를 이용한 요소의 출력
for (int i = 0; i < lnkList.size(); i++) {
    System.out.print(lnkList.get(i) + " ");
}

// remove() 메소드를 이용한 요소의 제거
lnkList.remove(1);

// Enhanced for 문과 get() 메소드를 이용한 요소의 출력
for (String e : lnkList) {
    System.out.print(e + " ");
}

// set() 메소드를 이용한 요소의 변경
lnkList.set(2, "둘");

for (String e : lnkList) {
    System.out.print(e + " ");
}

// size() 메소드를 이용한 요소의 총 개수
System.out.println("리스트의 크기 : " + lnkList.size());

결과값
넷 둘 셋 하나
넷 셋 하나
넷 셋 둘
리스트의 크기 : 3

Vector 클래스

Vector 클래스는 ArrayList클래스와 같은 동작을 수행하는 클래스이다. 현재의 Vector클래스는 ArrayList클래스와 마찬가지로 List인터페이스를 상속받는다.
따라서 Vector클래스에서 사용할 수 있는 메소드는 ArrayList클래스에서 사용할 수 있는 메소드와 거의 같다.
하지만 현재 기존 코드와의 호환성을 위해서 남아있으므로, Vector클래스보다는 ArrayList클래스를 사용하는 것이 좋다.

Comment and share

Collection Framwork

자바에서 컬렉션 프레임워크란, 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미한다. 다시말해 데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓은 것이다.

이러한 컬렉션 프레임워크는 자바의 인터페이스를 사용하여 구현된다.

컬렉션 프레임워크긔 핵심 인터페이스

크게 3가지 타입으로 나누어 핵심이 되는 주요 인터페이스를 정의했다.

  1. List
  2. Set
  3. Map

여기서 List와 Set 인터페이스의 공통점을 뽑아내어 새로운 인터페이스인 Collection을 추가로 정의하였다. Map 인터페이스는 구조상의 차이로 인해 별도로 정의된다.
콜렉션 기본구조

Comment and share

Hyeon Soo Ahn

author.bio


author.job