프로그래밍/Java 정리

Java 13일차 - Collection Framework

윤도ri 2021. 12. 2. 21:53

>컬렉션 프레임워크(Collection Framework)

-많은 데이터들을 쉽고 효과적으로 관리할 수 있는 표준화된 방법을 제공하는 클래스 및 인터페이스의 집합
: 자료구조의 일종

                                Collection(I)

                          List(I)                  Set(I)            <--둘다 인터페이스(서로 상속)

구현 클래스 ArrayList HashSet      LinkedList TreeSet
                                             Vector 
(인터페이스를 구현해야하기 때문에 미리 구현되어있는 클래스이다)

 

>ArrayList 

-Array는 배열 이라는 뜻이고 List는 원소들의 나열된 묶음이다.

-ArrayList는 배열을 이용해서 원소들을 나열해 묶는 클래스이다.
-컬렉션 클래스들 중 가장 많이 사용되는 클래스이다. 

:인덱스를 이용해서 배열 요소에 빠르게 접근 가능하지만 크기를 늘리기 위해서(요소를 추가할 때) 새로운 배열을 생성하고 기존의 값들을 옮겨야 하므로 느리다. 

:배열은 처음에 몇칸을 할당할지 고정해야 했지만, ArrayList는 값을 넣는 만큼 자동으로 늘어난다.

 

 

1.ArrayList 클래스로 배열을 객체화한다.

1)ArrayList 를 치고 자동완성을 하면 import가 되며 어떤 타입의 객체가 들어오는지 모르기때문에 제네릭<E> 로 표시될것이다. E는 element라는 뜻으로 "원소의 타입을 넣어라"라는 의미이다.2)그 다음 객체명 작성후 생성자 호출하면 끗! 

 

2.ArrayList에 요소를 추가하고 싶을때 객체명. add(String e); 메소드를 쓰면 된다.

3.ArrayList 구조 간단히 판단하고 싶을때 :  syso(객체명);

 

4. i번째 방마다 있는 문자열 출력하고 싶을때 : for 문을 사용하자   1) 기본 배열처럼 length라는 메소드가 아닌 size를 쓴다.  2)i 번째 방에는 "hello"가 있다라고 하고싶으면 i번째방 객체를 데리고 와야 하는데 그때는    get 이라는 메소드를 쓴다. (의미는 ArrayList에서 요소 가져오기 라는 뜻이다.)          for(int i = 0, i < arData1.size();  i++ ){               syso(i + "번째 방에는 " + 객체명.get(i));                      } 

 

5.ArrayList의 요소 수정하기: set (); 메소드 사용 (의미: replace the element at the specified postion)-->객체명.set(int index, String element)(바꾸길 원하는 값의 인덱스를 적고 바꾸려는 값을 적어라
6.ArrayList의 요소 삭제하기(요소로, 인덱스로) *hard가 여러개가 있으면 앞에있는게 지워지며 없는것은 지우지도 않는다.  1) 요소로 삭제  : 객체명.remove(Object o); 

 -->자료형 타입으로 쓰면 저절로 업캐스팅 되어 object의 메소드를 쓰게 되어 삭제됨. 

 -->리턴타입: String or Integer 

 

* int 타입의 숫자는 이게 int인지 요소인지 알 수 없음. 그래서 그냥 숫자만 달랑 쓰면 

컴퓨터는 아 인덱스구나 하고 쓴 숫자에 담겨있는 값을 부를것임. 그래서 요소를 삭제하고 싶을 경우에는 

직접 박싱하여 넘겨주어야 한다. 

 

2)인덱스로 삭제 

:객체명.remove(int index);

--->리턴 : true/false (boolean 타입)

 

>이중 ArrayList

전에는 우리가 arData[][] 이런식으로 만들었었는데 이건 좀 다를 수 있다. ArrayList 안에 ArrayList가 있고 

안에 어떤 객체가 들어가 있을것이다. 근데 그 타입이 어떤건지는 모르므로 이때도 아 제네릭이 필요하겠구나

생각할 수 있다. 

1. 객체화하기

2.방(객체)를 만들어 주기 

아까 arraylist 같은 경우는 원소를 추가하면 저절로 방이 생겼는데 이 경우는 객체화만 했고 주소값만 있고 

방은 없을거라서 원하는 방의 갯수를 하나하나 가져와야 한다. 

 new ArrayList<E>()  <-- 이것 자체가 객체이므로

 

3.값을 추가하는 방법

 객체명.get( ).add( ); 

 

4,값 하나씩 출력하고 싶을때 

:for문 사용하기

1)객체 길이만큼 돌리는데 0번째방인경우 0번째에있는 값 다 추출 get(i).get(j)  이런식으로 돌려가게 끔 

이중 for문 써주기 .

>Wrapper 클래스말고 이번엔 정보가 들어있는 일반클래스의 경우

1.a 클래스에 변수랑 생성자를 만들어준다. 

 

2.a 클래스 타입의 ArrayList 클래스로 객체화한다.

3. 맞는 객체들을 하나씩 다 추가해준다. 

객체명.add(new a클래스( )); 

객체명.add(new a클래스( )); 

          .....

3.객체를 제거하고 싶을때 

-toString 재정의하기

객체명.remove(new a클래스 ( b) ); 하면 써져있는게 같으므로 삭제가 되는걸까? 

정답은 X이다.  ObJect 0에 들어가서 업캐스팅이 안되면 주소값을 비교하게 된다 .그러므로 toString 을 재정의하면 

재정의한 내용이 출력될것이다. 

 

4.객체를 출력하고 싶을때 

-동일객체임을 알아야 얘가 맞게 출력을 해줄것이다.그러므로 동위객체를 동일객체로 바꿔주기 위해 equals를 재정의해주어야 한다. 

1) 타입 비교 2) 다운캐스팅 3) 트루값 리턴

 

 

 

 

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

>HashSet

-Hash는 해쉬값 Set은 집합이라는 뜻이다. 
: 집합은 중복되는 원소(요소, 값)를 포함할 수 없다.
: 저장된 값들에는 인덱스가 없기 때문에 저장 순서가 고정되어 있지 않다.
  (어디에 있는지가 중요한지 순서가 중요하지 않다) 
: 값의 포함 여부, 값의 유무 검사 목적이 있다. 

: Set은 검색의 목적이 있기 때문에 순서 정보를 관리할 필요가 없다. 


 따라서 데이터 크기에 상관없이 검색에 걸리는 시간이 매우 짧다. 
 반면 ArrayList는 인덱스를 관리해야하기 때문에 상대적으로시간이 오래 걸린다.기능적으로 HashSet 과 ArrayList로 
구현한 것이 차이가 없다면 HashSet을 이용한다. 

1.arraylist와 마찬가지로 객체화한다.

2.HashSet 에 요소 추가하기

set.add(int x );

반복되는 숫자는 출력이 안되는것을 알 수 있다.

3. 간단하게 구조 확인하기: syso( 객체명 );

4. 요소의 개수 확인하기: syso(객체명.size);

5. 요소 삭제하기 : 객체명.remove(원하는 값); <--오토박싱되어 알아서 업캐스팅됨.

6. hashSet은 인덱스가 없어서 다른값으로 대체할 수는 없다. 

---> iteraror()라는 메소드로 간접적으로 순서를 부여해 리턴해주는 메소드

 

>>.iterator() 

--순서모르므로 간접적으로 가져오는 방법
:순서가 없는 Set 타입의 요소에 순서를 부여해서 Iterator로 만든 후 리턴해주는 메소드이다.  리턴된 Iterator 객체는
순서가 부여되어 있기 때문에 안에 있는 요소들을 .next()라는 메소드를 통해서 하나씩 가져올 수 있게된다. 
  (102030 순서대로 나열하는것이아니다)

1. iterator 를 import 한다. 

2.어떤 값일지 모르므로 제네릭에으로 표시후 객체화 시킨다.(순서가 부여된 채로 만들어짐)

이제 하나씩 출력하고 싶은데 어떻게 출력할까?  객체명.next()  * 요소의 갯수 만큼을 쓰면 아마도 다 출력이 될것이다.

그러나 우리에게 hasNext()가 있다. 이것은 무엇일까?

>>.hasNext()

:iterator가 어떤 복잡한 과정을 통해 마음대로 나열해준다. 그래서 hasNext를 붙이면 next하면 옆으로 이동하면서 

하나씩 출력해준다.

**다시 5를 출력하고 싶을경우 

우리가 int data = 10; data= 5; 이렇게 재정의 하는것처럼 객체명= set.iterator(); 를 써서 다시 초기화? 한다. 

그리고 다시 출력하면 5가 출력되는 것을 알 수 있다.

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

>HashMap

 우리가 사전에서 찾을때 fly를 찾으면 날다를 알 수 있다. 마치 이것처럼 우리는 fly 를 통해 날다를 찾을 수 있다.

                      KEY                   VALUE
                      data                    10
ENTRY               fly                    날다 
ENTRY     식별자 역할(key)     직접사용하는것(value)

 

-Map구조는 key(키)와 value(값)이 쌍으로 저장되는 형태이다. 그러므로 검색에 용이하다. 

:KEY는 중복이 불가능하며 VALUE는 가능하다. 

:KEY는 Set 타입이고 VALUE 는 collection 타입이다.

 

-객체끼리 비교할때 equals와 hascode 재정의하기

 

Fly(set) 는        100번지에 있어~ 가보면 날다(인덱스 없이 collection)가 있다. 
                <---------------------->
                        HashTable 

               키 <-> 해쉬테이블 <-> 값

       ------>이걸 map 구조라고 한다. 

 

-HashMap 의 부족한 점을 채워줄 수 있는 메소드 3가지 

 1) .keySet( ) - key들만 모여있는 set

 2) .values( ) - value 들만 모여있는 collection 

 3) .entrySet( ) - 키, 값이 하나로 Entry로 모여있는 Set

 

위의 예제에 대한 해쉬 코드 재정의 이미 equals는 재정의 해놓았기 때문에 HashMap은 hashcode까지 비교해야한다.

>>컬렉션 사용시 주의할 점  
 컬렉션에서는 값들을 비교할 때 요소 타입의 equals 혹은 hashCode() 로 비교하기 때문에 우리가 만든 클래스에 그것들을 재정의하지 않는다면 주소값 비교로 같은 값을 찾아올 수가 없게된다. 따라서 비교하고자 하는 값을 올바르게 비교하도록 equals 를 재정의해서 사용해야 한다. 

 

 

>빠른 for문(향상된 for문, forEach문)

-단순하게 모든 값들을 순회할 때 사용하는 것이 좋다. 순서가 중요한 경우에는(몇번째에 어떤 값이 있는지 알 필요가 있는 경우) 기존의 for문을 이용하는 것이 좋다. 

          for(자료형 변수명: 반복자){
            변수가 안에 있는 요소들을 하나씩 꺼내오며 반복
                 }

예제1.ArrayList 빠른 for문

예제2. HashSet 빠른 for문

예제3.HashMap 빠른 for문