개발자일지/Java

자바의 정석 11장 ArrayList 부터

어쩌다한번 2022. 1. 27. 10:50

- ArrayList의 메서드

원하는 위치에 원하는 수 만큼 추가/제거/검색이 가능하다.

객체만 저장 가능하지만 전에 배웠던 박싱으로 변환되어 저장가능하다

remove(1)과 remove(new Integer(1))의 차이는 크다

전자는 index가 1인 객체를 삭제하고 후자는 값이 1인 객체를 삭제한다

 

- ArrayList에서 객체를 하나하나 삭제하기

반복문으로 객체를 하나씩 삭제하려고 할때 첫번째것 부터 삭제를 하려고 하면 몇가지 객체가 남게된다

삭제를 하면서 뒤의 객체들이 하나씩 앞으로 당겨오는데 이것때문에 삭제되지 않는 값들이 발생하기 때문이다.

이를 방지하기 위해서는 마지막 객체부터 역순으로 삭제를 하면 된다.

첫번째 부터 삭제하면 순서가 꼬여 남는것이 생긴다

 

- 배열ArrayList의 장단점과 LinkedList와 차이

배열은 데이터가 연속적인것이 특징이다. 따라서 접근이 쉬운데 처음 생성할때 정한 크기의 변경이 불가능 하기 때문에

크기를 늘리고 싶다면 새로운 배열을 만들어서 옮겨야한다. 또 연속적이기에 마지막에 데이터를 추가하거나 삭제하는 것은 쉽지만

중간에 데이터를 추가하고자 하면 이후 모든 배열의 순서를 옮겨야 해서 시간이 오래 걸린다.

 

 

LinkedList는 각 데이터들이 연결성을 갖게 해서 추가와 삭제가 편하다. 각 객체마다 다음 객체에 대한 정보를 가지고 있어서

이들만 수정하면 연속적인 데이터배열에 비해 추가와 삭제를 간편하게 할 수 있다.

하지만 다음 데이터에 대한 접근은 쉽지만 그 이상의 데이터에 접근하려면 그만큼 단계를 거쳐야해서 접근성이 나쁘다

그를 보완하기 위해 전 후 이중으로 연결하는 것이 doubly linked list이고 더욱 접근성을 향상시켜서 가장 마지막과 처음을 연결한

리스트도 존재한다.

  • Stack과 Queue의 메서드

스택은 프링글스, 큐는 선착순이다

스택은 마지막 데이터의 수정이 쉬운 배열과 잘 맞고 큐는 링크드리스트와 더 알맞다

/*Stack*/메서드

boolean empty() // 비었는지 확인

Object peek() // 맨 위의 객체를 반환한다. 꺼내는 것은 아니다

Object pop() // 맨 위에 있는 객체를 꺼낸다.

Object push(Object item) // 객체 추가

int search(Object o) // 객체 위치를 찾고 없다면 -1
/*Queue*/인터페이스

boolean add(Object o) // (저장공간이 부족하면 예외발생)

Object remove() // 객체를 꺼내서 반환(없으면 예외발생)
Object element() // 객체를 꺼내지 않고 반환(없으면 예외발생)

boolean offet(Object o) // 객체를 저장하고 실패하면 false반환

Object poll() // 객체를 꺼내서 반환(없으면 null반환)
Object peek() // 객체를 꺼내지 않고 반환(없으면 null반환)

스택은 클래스로 구현되어있지만 큐는 인터페이스이다

따라서 큐를 사용하려면 직접만들거나 LinkedList와 같이 구현시킨 것을 사용하면 된다.

Stack st = new Stack();
Queue q = new LinkedList();

st.push("0");
st.push("1");
st.push("2");

q.offer("0");
q.offer("1");
q.offer("2");

//일때

System.out.println(st.pop()); // 2

System.out.println(q.poll()); // 0

구조의 특징처럼 데이터를 가져오는 순서가 다르다.

 

  • Iterator

컬렉션에 저장된 데이터에 접근하는데 사용되는 인터페이스다

컬렉션 내에 다양한 방법으로 저장된 요소를 불러오는 방식을 표준화시킨 것이다

구버전이라고 할 수 있는 Enumeration과 접근성을 향상시킨 Listiterator가 있지만 잘 쓰진 않는다고 한다.

/*Iterator*/

boolean hasNext(); // 읽어 올 다음 요소가 있는지를 확인한다.
Object next(); // 다음 요소를 읽어온다.

//사용

List list = new ArrayList();
Iterator it = list.iterator();

while(it.hasNext()){
    System.out.println(it.next());
}

ilterator()메서드를 호출한 객체를 생성해서 사용한다.

 

객체를 생성하고 사용한 뒤 또 사용하려면 다시 또 만들어줘야한다

한번 사용 된 뒤에는 false를 반환해버리기 때문이다.

 

get메서드를 사용해서 반복문으로 요소들을 불러올 수도 있지만

Map의 경우에는 get메서드가 존재하지 않는다. 그렇기에 표준화된 방법을 쓰는 것이고

객체를 생성할 때도 타입을 부모타입으로 하는 것이 변경을 최소화 하기에 권장된다.

 

Map map = new HashMap();

Iterator it = map.entrySet().iterator();

 

Map에는 iterator()가 없다. 그래서 key를 가져오는 keyset이나 모두가져오는 entry등을 사용한 뒤 호출해야한다.