Back-End/백엔드 관련 정리

[자바][List] - 인터페이스 기반 프로그래밍

얄루몬 2022. 9. 17. 19:20


📖본 포스팅은 'think data structures'를 보고 포스팅 되었습니다.  

간단 정리

  1. Interface?

인터페이스는 메소드들의 집합으로 최소한의 설계만을 해서 나머지를 구현체가 채울 수 있도록 하는 것을 의미한다.

 

  1. List Interface?

리스트 인터페이스에는 ArrayList LinkedList 두 개의 List가 있다. (둘은 구현 클래스이다.)

필요한 경우가 아니라면 List 인터페이스를 사용해야하고 ArrayList나 LinkedList처럼 구현 클래스는 필요할 때만 사용해야 한다.

 

  1. 인터페이스 기반 프로그래밍?

특정 구현 클래스에 의존하는 것이 아닌 인터페이스에 의존해 구현 클래스가 바뀌어도 문제가 없게 프로그래밍 하는 방법을 인터페이스 기반 프로그래밍이라고 합니다.

 

실습

LinkedList를 ArrayList로 변경해보자

알고리즘 분석

  1. 알고리즘을 비교하기 위해서는 사전에 그것을 모두 구현해봐야 한다.
  2. 결과는 사용하는 컴퓨터 성능에 의존하고 한 알고리즘이 어떤 컴퓨터에서는 더 좋을 수 있지만 다른 알고리즘은 다른 컴퓨터에서 더 좋을 수 있다.
  3. 결과는 문제 크기나 입력으로 사용하는 데이터에 의존하기도 한다.

실습 2

list interface를 사용한 ArrayList 구현!

-> 이는 구현 클래스인 ArrayList 와는 다르게 본인이 직접 인터페이스를 사용해 메소드를 오버라이딩해서 사용!!




전체 코드

package list;

import java.util.*;

public class MyArrayList<T> implements List<T> {

    int size;
    private T[] array;



    public MyArrayList() {
        this.size = 0;
        this.array = (T[]) new Object[10]; //크기가 10인 array 생성
    }

    public static void main(String[] args) {
        MyArrayList<Integer> mal = new MyArrayList<Integer>();

        mal.add(1);
        mal.add(2);
        mal.add(3);
        System.out.println(Arrays.toString(mal.toArray())+ "size = " + mal.size);

        mal.remove(Integer.valueOf(2));
        System.out.println(Arrays.toString(mal.toArray())+ "size = " + mal.size);
    }

    @Override
    public int size() {
        return size;
    }



    @Override
    public boolean isEmpty() {
        return size ==0;
    }

    @Override
    public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

    @Override
    public Iterator<T> iterator() {
        T[] copy = Arrays.copyOf(array,size);
        return Arrays.asList(copy).iterator();
    }

    @Override
    public Object[] toArray() {
        return Arrays.copyOf(array,size);
    }

    @Override
    public <T1> T1[] toArray(T1[] a) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean add(T t) {
        if(size >= array.length){
            T[] bigger = (T[]) new Object[array.length*2];
            System.arraycopy(array,0,bigger,0,array.length);
            array = bigger;
        }
        array[size] = t;
        size++;

        return true;
    }

    @Override
    public boolean remove(Object o) {
        int index = indexOf(o);

        if(index == -1){
            return false;
        }
        remove(index);
        return true;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        for(Object element: c){
            if(!contains(element)){
                return false;
            }
        }
        return true;
    }
    @Override
    public boolean addAll(Collection<? extends T> c) {

        boolean flag = true;
        for (T element: c){
            flag &= add(element);
        }
        return flag;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean removeAll(Collection<?> c) {

        boolean flag = true;
        for(Object obj:c){
            flag &= remove(obj);
        }

        return flag;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void clear() {
        size = 0;
    }

    @Override
    public T get(int index) {
        if(index<0 || index>=size){
            throw new IndexOutOfBoundsException();
        }
        return array[index];
    }

    @Override
    public T set(int index, T element) {
        if(index<0 || index >= size){
            throw new IndexOutOfBoundsException();
        }

       return array[index] = element;
    }

    @Override
    public void add(int index, T element) {
        if(index < 0 || index > size){
            throw new IndexOutOfBoundsException();
        }
        add(element);

        //요소 옮기기..
        for(int i = size-1; i > index; i--){
            array[i] = array[i-1];
        }

        array[index] = element;
    }

    @Override
    public T remove(int index) {
        return null;
    }

    @Override
    public int indexOf(Object o) {
        return -1;
    }

    @Override
    public int lastIndexOf(Object target) {
        for(int i = size - 1; i>=0; i--){
            if(equals(target, array[i])){
                return i;
            }
        }
        return -1;
    }

    @Override
    public ListIterator<T> listIterator() {
        T[] copy = Arrays.copyOf(array,size);
        return Arrays.asList(copy).listIterator();
    }

    @Override
    public ListIterator<T> listIterator(int index) {
        T[] copy = Arrays.copyOf(array, size);
        // make a list and return an iterator
        return Arrays.asList(copy).listIterator(index);
    }

    @Override
    public List<T> subList(int fromIndex, int toIndex) {
        if (fromIndex < 0 || toIndex >= size || fromIndex > toIndex){
            throw new IndexOutOfBoundsException();
        }
        T[] copy = Arrays.copyOfRange(array,fromIndex, toIndex);
        return Arrays.asList(copy);
    }


    public boolean equals(Object target, Object element) {
        if(target == null){
            return element == null;
        } else{
            return target.equals(element);
        }

    }


}

ArrayList?

  • 자바에서 가장 기본적으로 많이 사용되는 클래스
  • 자바의 List 인터페이스를 구현한 클래스 중 하나다.
  • 일반 배열과 동일하게 연속된 메모리 공간을 사용하며 인덱스는 0부터 시작한다.
  • 배열과의 차이점은 배열의 크기는 고정인 반면에 ArrayList의 경우엔 크기가 가변적으로 변한다.
  • 내부적으로 저장이 가능한 메모리 용량이 있으며 현재 사용중인 공간의 크기가 있다.
  • 현재 가용량 이상을 저장하려한다면 더 큰 공간의 메모리를 새롭게 할당한다.