ArrayList란 무엇일까?

ArrayList에서 선언된 가장 중요한 함수를 통해 

개념을 이해해볼 것이다.



List - ArrayList

    - null 값을 저장할 수 있다.

    - 값을 중복 저장할 수 없다.

    - 값을 넣는 순서대로 저장한다.

      그래서 값을 꺼낼 때도 넣은 순서대로 꺼낼 수 있다.

    - 값을 꺼낼 때 숫자 인덱스를 사용하여 꺼낸다.



1)

ArraList 1. Object[] 배열 생성 코드를 작성한다.


public class ArrayList_ex1 {

 
  // Object 배열을 생성할 때, 기본적으로 생성해줘야 하는 사이즈(DEFAULT_SIZE)를 지정해준다.
  public static final int DEFAULT_SIZE = 10;
  // Object 배열에 값을 넣어줄 때, 추가로 생성해주고 싶은 사이즈(GROW_SIZE)를 지정해준다.
  public static final int GROW_SIZE = 3;
 
  Object[] list;
 
  // ArrayList_ex1 인스턴스를 생성하자마자, 호출되는 생성자 함수에서
  // 자동적으로 Object 배열의 빈 값을 10개 생성해주도록 한다.
  public ArrayList_ex1() {
   list = new Object[10];
  } 

}



2)

ArrayList 2. new ArrayList_ex1(숫자); 작성시 호출되는 

Object[] 배열 생성자 코드를 작성한다.


 // 기본 사이즈나 추가 사이즈보다 작은 수가 넘어오면 기본 사이즈로 배열을 생성한다.
public ArrayList_ex1(int capacity) {
 if (capacity < DEFAULT_SIZE || capacity < GROW_SIZE) {
   list = new Object[DEFAULT_SIZE];
 } else { // 그 외에는 입력받은 숫자대로 배열을 생성한다.
   list = new Object[capacity];
 }
}




3)

ArrayList 3. 배열의 길이를 증가시키는 increaseList() 

메서드 코드를 작성한다.


// 배열의 길이를 증가시키는 메서드. 내부 메서드이기 때문에 private을 사용한다
private void increaseList() {
  // 생성된 배열의 길이에 GROW_SIZE를 더 한 만큼 배열을 추가로 생성한다.
  Object[] newList = new Object[list.length + GROW_SIZE];
 
  // 반복문을 통해, 새롭게 생성되었던 newList 배열의 각 인덱스 값에 list 배열 값들을 저장한다.
  for (int i = 0; i < list.length; i++) {
   newList[i] = list[i];
  }
 
  // list 변수에 newList 배열의 주소를 할당해주면 된다.
  list = newList;

}




4)

ArrayList 4. 배열에 값을 넣어주는 add() 메서드를 추가한다.


// 배열에 값을 넣어주는 메서드
public void add(Object obj) {
  // add 메서드가 호출될 때마다 length 값을 하나씩 증가시키면서 obj 값을 list 배열에 삽입한다.
  list[length++] = obj;
 
  // length와 배열의 길이가 일치하면 배열의 길이를 증가시킨다.
  if (length == list.length) {
    increaseList();
  }

}




5)

ArrayList 5. 배열에 저장된 값을 꺼내는 get() 메서드를 추가한다.


// 배열에 저장된 값을 꺼내는 get() 메서드를 추가한다.
public Object get(int index) {
 
  // index 값이 배열의 길이보다 많거나 0보다 작다면 에러처리를 해준다.
  if (index < 0 || index >= length) {
    throw new RuntimeException("배열 인덱스의 범위를 벗어났습니다.");
  }
 
  // 그외에는 list 배열에서 해당 인덱스에 저장된 값을 리턴한다
  return list[index];

}




6)

ArrayList 6. 배열에서 특정 인덱스를 제거하는 remove() 메서드를 추가한다.


// 배열에서 특정 인덱스를 제거하는 remove() 메서드를 추가한다.
public void remove(int index) {
 
  //index 값이 배열의 길이보다 많거나 0보다 작다면 에러처리를 해준다.
  if (index < 0 || index >= length) {
    throw new RuntimeException("배열 인덱스의 범위를 벗어났습니다.");
  }
 
  // 입력받은 index 값부터 list 배열에 있는 값들을 하나씩 당겨서 저장한다.
  // (덮어씌어 지면서 기존 값이 지워지는 것)
  for (int i = index; i < list.length - 1; i ++) {
    list[i] = list[i+1];
  }
 
  // 배열의 길이를 하나 줄인다.
  length--;

}






7)

ArrayList 7. 배열에서 특정 인덱스에 값을 저장하는 set() 메서드를 추가한다.


// 배열에서 특정 인덱스에 값을 저장하는 set() 메서드를 추가한다.
public void set(int index, Object obj) {
 
  //index 값이 배열의 길이보다 많거나 0보다 작다면 에러처리를 해준다.
  if (index < 0 || index >= length) {
    throw new RuntimeException("배열 인덱스의 범위를 벗어났습니다.");
  }
 
  // list[index]에 값을 저장시킨다.
  list[index] = obj;

}





main() 메서드 예제


import java.sql.Date;
public class Test_ArrayList{
  public static void main(String[] args) {
   ArrayList_ex1 dateList = new ArrayList_ex1();
   
    dateList.add(Date.valueOf("2017-3-1"));
    dateList.add(Date.valueOf("2017-5-3"));
    dateList.add(Date.valueOf("2017-5-5"));
    dateList.add(Date.valueOf("2017-5-9"));
    dateList.add(Date.valueOf("2017-6-6"));
    for (int i = 0; i < dateList.length(); i++) {
      System.out.println(dateList.get(i));
    }
    System.out.println("-------------------------");   
   
    dateList.remove(3);
    dateList.set(1, Date.valueOf("2017-5-4"));
   
    for (int i = 0; i < dateList.length(); i++) {
      System.out.println(dateList.get(i));
    }
       
  }

}


- 실행 결과 : 

2017-03-01

2017-05-03

2017-05-05

2017-05-09

2017-06-06

-------------------------

2017-03-01

2017-05-04

2017-05-05

2017-06-06




블로그 이미지

필로그래머

,

[Java] 자바 컬렉션 - [Map] HashMap(java.util.HashMap)


컬렉션 클래스 : Map

- 값을 저장할 때 key 개체의 해시 값(hash value)을 사용하여 저장한다.

- 값을 꺼낼 때도 key 객체의 해시 값을 사용하여 꺼낸다.

- 값을 중복 저장할 수 없다.

- 순서대로 저장하고 순서대로 꺼낼 수 없다.

- 보통 문자열 라벨을 사용하여 값을 저장하고 꺼낼 때 주로 사용한다.

- 예)

   HashMap :

    - key나 value로 null을 허용한다.

    - 동기화를 지원하지 않는다.

       => 여러 스레드가 동시에 접근하여 값을 변경하는 것을 막지 않는다.

       => 데이터의 입출력 속도가 빠르다.

       => 대신 여러 스레드가 동시에 값을 바꿀 수 있기 때문에 

               멀티 스레드 상황에서 사용할 때 주의해야 한다.

    Hashtable : 

     - key나 value로 null을 허용하지 않는다.

     - 동기화를 지원한다.

       => 여러 스레드가 동시에 접근하더라도 그 중 한개의 스레드만이 접근할 수 있다.

        => 데이터의 입출력 속도가 느리다.

        => 대신 여러 스레드가 동시에 값을 바꿀 수 없기 때문에

             멀티 스레드 상황에서 안전하게 사용할 수 있다.


put(key, value)

- key 객체 : 

  1) key 객체의 hashCode() 리턴 값을 사용하여

      value를 저장할 때 사용할 위치를 계산한다.

  2) 그래서 key 객체는 같은 값을 가진 객체인 경우

      같은 hashCode()를 리턴하는 클래스를 사용한다.

      예) String, 랩퍼 클래스(Byte, Short, Integer, Long, Float, Double, Boolean 등)

- value 객체: Map 컬렉션에 보관될 값



Map에서 값을 꺼내는 방법 I

- 값을 저장할 때 사용한 key를 통해 꺼낸다.

- 반드시 같은 인스턴스일 필요는 없다.

  저장할 때 사용한 key의 hashCode() 리턴 값과 

  같은 hash value를 가진다면 값을 꺼내는 key로 사용할 수 있다.

  물론 equals()의 결과도 true여야 한다.



값을 저장할 BooK class 예제


static class Book {
    String title;
    String press;
    int page;
   
    public Book(String title, String press, int page) {
      this.title = title;
      this.press = press;
      this.page = page;
    }
   
    public String toString() {
      return String.format("%s, %s, %d", title, press, page);
    }

  }




Map에서 값을 꺼내는 호출 코드


public static void main(String[] args) {

    HashMap map = new HashMap();
    
    map.put(new String("key1"), new Book("aaaa", "유리출판사", 100));
    map.put("key2", new Book("bbbb", "유리출판사", 200));
    map.put(3, new Book("cccc", "유리출판사", 300));
    
    System.out.println(map.get(new String("key1")));
    System.out.println(map.get(3));
  }

}

- 실행 결과 : 

aaaa, 유리출판사, 100

cccc, 유리출판사, 300



* 참고 :

  key 값에 올 수 있는 건 인스턴스 뿐인데 어째서 key 값으로 숫자 1을 넣어줄 수 있는 것인가? 

  => 랩퍼 클래스(wrapper class)는 오토 박싱 (auto-boxing) 기능을 가지고

     있어서 인스턴스를 요구하는 명령어가 있을 경우, key 값으로 써준 숫자 1을

     자동적으로 new Integer(1)로 만들어 준다.

      

** 참고 :

   map.get(key)메서드가 리턴하는 것은 key 값에 해당되는 인스턴스의

   toString() 메서드 리턴 값이다.




Map에서 값을 꺼내는 방법 II


- 값 목록을 리턴 받아 꺼낸다.


 Collection valueList map.values();
    // 값이 들어 있는 컬렉션에서 값을 한 개씩 꺼내줄 도구를 얻는다.
 Iterator iterator = valueList.iterator();
   
 while(iterator.hasNext()) {
   System.out.println(iterator.next());

 }





Map에서 값을 꺼내는 방법 III


- key 목록을 리턴 받아 꺼낸다


Set KeySet = map.KeySet();
Object[] keyArray = keySet.toArray();
 for (int i = 0; i < keyArray.length; i++) {
   System.out.println(map.get(keyArray[i]));

 }





Map에서 값을 꺼내는 방법 V


- key와 value를 한쌍으로 하는 목록을 리턴 받는다.


Set entrySet = map.entrySet();
    for (Object object : entrySet) {
      Entry entry = (Entry)object;
      System.out.printf("%s=%s\n", entry.getKey(), entry.getValue());

    }











블로그 이미지

필로그래머

,

[Java] 자바 컬렉션 클래스 - [Set] HashSet (java.util.Hashset)


컬렉션 클래스 : HashSet (java.util.HashSet)

 - 저장하려는 객체에 대해 hashCode()를 호출하여

   그 리턴 값을 가지고 저장할 위치를 계산한다.

 - null 값을 저장할 수 있다.

 - 값을 중복 저장할 수 없다.

   이유 -> '집합'이기 때문

 - 값을 넣을 때 인스턴스의 해시값을 기준으로 저장하기 때문에

   순서대로 저장되지 않는다.

   그래서 값을 꺼낼 때도 순서대로 꺼낼 수 없다.

 - 값을 꺼낼 때 숫자 인덱스로 꺼낼 수 없다.

 - 예) HashSet



Set 컬렉션에서 값을 꺼내는 방법


 1) 배열을 리턴 받는다. (입력 순서대로 리턴 받을 수 없다.)

     - toArray()


Object[] valueList = dateSet.toArray();


for (int i = 0; i < valueList.length; i++) {
  System.out.println(valueList[i]);

}


 2) 값을 꺼내주는 메서드를 이용한다.

     - iterator()


Iterator iterator = dateSet.iterator();
 
while (iterator.hasNext()) { // hasNext() -> 꺼낼 데이터가 있는가?
  System.out.println(iterator.next());

}






* 주의!
  HashSet 컬렉션에 값을 저장할 때,
  인스턴스의 주소가 영향을 끼치는 것이 아니라

  hashCode()의 리턴 값이 영향을 끼친다.



HashSet과 hashCode() 메서드 예제


public static void main(String[] args) {
    HashSet set = new HashSet();
    
    set.add(new String("홍길동"));
    set.add(new String("임꺽정"));
    set.add(new String("유관순"));
    set.add(new String("윤봉길"));
    set.add(new String("안중근"));
    set.add(new String("김구"));
    set.add(new String("김구"));
    /* "김구" 문자열인 경우엔 서로 다른 인스턴스 임에도 불구하고 중복되지 않는다.
     *  왜?
     *  => Set은 객체(의 주소)를 저장할 때 그 객체에 대해 hashCode() 메소드를 호출한 후
     *     그 리턴 값을 위치를 계산한다.
     *  => String 클래스는 같은 값을 갖는 경우 같은 hash value를 리턴하도록
     *     hashCode()를 오버라이딩 하였다.
     *     즉 위의 두 개의 "김구" String 객체는 비록 인스턴스는 다르지만
     *     값이 같기 때문에 hashCode()의 리턴값도 같다.
     *     그래서 위치를 계산한 값도 같다.
     *     위치 계산 값이 같아서 같은 값으로 간주하기 때문에 중복 저장되지 않는다.
     */
   
    // 증명! -> 값이 다 똑같이 출력된다.
    System.out.println(new String("김구").hashCode());
    System.out.println(new String("김구").hashCode());
    System.out.println(new String("김구").hashCode());
     
   
    /* 결론!
     * HashSet 컬렉션에 값을 저장할 때,
     * 인스턴스의 주소가 영향을 끼치는 것이 아니라
     * hashCode()의 리턴 값이 영향을 끼친다.
     */
   
    Iterator iterator = set.iterator();
    while (iterator.hasNext()) { // 꺼낼 데이터가 있는가?
      System.out.println(iterator.next());
    }
}


블로그 이미지

필로그래머

,