메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

독자가 풀어보는 "자바로 배우는 핵심 자료구조와 알고리즘" 1회

한빛미디어

|

2019-03-20

|

by 유동환, 이충일

1,902

안녕하세요, "자바로 배우는 핵심 자료구조와 알고리즘"의 역자 유동환입니다. 출간한지도 6개월이 넘었네요. 번역하는데 3개월 정도 걸렸는데 워낙 탄탄한 책이라 그 과정에서 저도 많이 배웠습니다. 

 

작년 12월 29일에는 한 독자(이충일 님)로부터 흥미로운 메일을 받았습니다. 그 일부를 공개합니다. 

 

20190217-1-575ea038-63f2-4733-8cf6-6bea9728195b.png

 

역자에게 "책을 실습하고 정리하고 싶다"라는 메일은 처음 받았거든요. 조금은 기특하기도 하고 선배 개발자로서 무언가 도움을 드리고 싶어서 "독자가 풀어보는.." 이라는 연재를 기획하게 되었습니다. 본서는 총 14개의 실습으로 이루어져 있습니다. 이중에서 의미가 있어보이는 몇 개의 문제를 "독자"가 직접 풀어보면서 그 의미를 되살려 보겠습니다. 

 

많은 관심을 부탁드립니다. 

 

이제 "1장 인터페이스"에 있는 실습1에 관한 이충일님의 풀이를 시작합니다. 

 

학습목표

앞으로 실습을 통해 다음의 3가지 학습 목표를 갖는다.

 

자료구조

- 자바 컬렉션 프레임워크Java Collection Framework, JFC 구조로 시작하여, List, Map, 과 같은 자료구조를 사용과 동작 방법

 

알고리즘 분석

- 코드를 분석하고 이 코드가 얼마나 빠른 동작을 하고 얼마나 많은 공간(메모리)를 필요한지 예측

 

정보 검색

- 자료구조와 알고리즘을 활용한 간단한 웹 검색 엔진을 만들어 봄

 

List Interface

앞으로 몇가지 실습을 통해 List Interface를 분석하고 학습하려 한다.

JFC(Java Framework Collection)는 List 라는 interface를 통해 ArrayList와 LinkedList라는 두 구현 클래스를 제공한다.

List interface를 구현하는 클래스는 약 20가지 메서드를 포함한 특정 메서드를 구현해야한다.

따라서 List Interface를 구현하는 ArrayList와 LinkedList는 모두 동일한 메서드를 제공하므로 상호 교환할 수 있다는 것이다.

그렇다면 이 두 클래스의 차이점은 무엇일까?

 

ArrayList vs LinkedList

 

 

두 클래스의 차이는 다음의 링크에 자세히 소개되고 있다. ArrayList와 LinkedList 차이

쉽게 정리하자면 다음과 같다.

 

 

하나의 건물(메모리)회사(List의 요소)가 입주해있다.

 

ArrayList

 

Array List는 그림과 같이 건물에 나란히 회사가 위치해있는 형태이다. 회사의 사무실이 이렇게 나란히 붙어있기 때문에 사무실의 위치를 찾기가 굉장히 수월하다.

하지만 이러한 방식은 빈 공간을 허용하지 않기 때문에, 중간의 하나의 사무실에 공실이 발생할 경우 전체 사무실이 빈 공간을 채우려 이동해야 한다.

 

LinkedList

 

이와달리 Linked List는 사무실이 산발적으로 연결(Linked)된 방식이다.

우리는 사무실의 위치를 찾기 위해 각각의 사무실을(예: 201호 - 304호 - 408호 등) 방문하여 다음 사무실이 어디인지를 물어봐야한다.

예를들면, 201호를 먼저 방문하여 직원에게 다음 사무실이 어딘지 물어봐야 다음 사무실이 304호라는 것을 알 수 있다는 것이다.

어떤가, 벌써 찾아가기가 번거롭다.

하지만 이 방식은 나란히 있는 것이 아니기 때문에 중간에 사무실에 공실이 발생하거나 추가되어도 전혀 상관없다. 

따라서 다음의 특징을 갖는다.

 

 

실습1

본론으로 돌아와 List Interface를 살펴보자.

 

List Interface 사용하기

 

ArrayList와 LinkedList는 List를 구현(implements)하여 사용하는 클래스이다.

따라서 다음과 같은 구조로 사용할 수 있다.

 

실습 코드

 

    public class ListClientExample {

    

        @SuppressWarnings("rawtypes")

        private List list;

    

        @SuppressWarnings("rawtypes")

        public ListClientExample() {

            list = new LinkedList();

        }

    

        @SuppressWarnings("rawtypes")

        public List getList() {

            return list;

        }

    

        public static void main(String[] args) {

            ListClientExample lce = new ListClientExample();

            @SuppressWarnings("rawtypes")

            List list = lce.getList();

            System.out.println(list);

        }

    }

 

테스트 코드

 

    public class ListClientExampleTest {

      /**

      * Test method for {@link ListClientExample}.

      */

      @Test

      public void testListClientExample() {

        ListClientExample lce = new ListClientExample();

        @SuppressWarnings("rawtypes")

        List list = lce.getList();

        assertThat(list, instanceOf(ArrayList.class) );

      }

    }

 

테스트 실행결과

 

1_tds_ch1_failed_test-fbf6dda9-b152-432b-a4eb-c5cd4504491f.png

 

첫번째 빨간불을 맛보았다.

 

오류 내용을 살펴보면, ArrayList의 instance를 기대했는데, But LinkedList 라는 것이다.

 

getList()로 부터 획득하는 리스트의 인스턴스가 문제가 있는 모양인데, 거슬러 올라가면 getList()의 리스트 인스턴스는

 

    @SuppressWarnings("rawtypes")

        public ListClientExample() {

            list = new LinkedList();

        }

 

이처럼 LinkedList()로 초기화된 모습이다.

 

테스트를 통과시키기 위해선 ArrayList가 필요하다. 이 초기화 작업만 바꾸어 주면 될 것 같다.

 

    @SuppressWarnings("rawtypes")

        public ListClientExample() {

            list = new ArrayList();

        }

 

1_tds_ch1_success-c145863f-ea69-4f11-896f-3dfaf98f668c.png

 

이 클래스의 구성은 유용하진 않지만, List를 캡슐화하는 클래스의 필수 요소를 가지고 있다.

 

위 클래스는 생성자를 통해서만 LinkedList를 초기화하고, getList를 통해 List객체애 대한 참조를 반환한다.

 

경우에 따라 ArrayList를 사용하고자 한다면, 생성자를 통한 초기화만 바꾸어주면 된다.

 

이와 같은 방식을 인터페이스 프로그래밍이라고 하는데, 필요한 경우가 아니라면 LinkedList나 ArrayList를 직접 구현하지 않고 생성자를 통해 구현함으로써, 필요에 따라 생성자의 초기화만 변경하여 유연한 대처를 할 수 있다.

 

여기서 말하는 '인터페이스'는  자바의 인터페이스가 아닌, 일반적인 의미의 인터페이스를 말한다.

 

첫 실습은 비교적 싱겁게(?) 끝났지만, 앞으로 다루게 될 List Interface에 대한 내용을 다루어 보았다.

 

이 장에서 기억해야 할 것은,

  • ArrayList와 LinkedList가 분명하게 컨셉이 다르다는 것
  • interface에 대한 개념(어떤 클래스를 초기화하느냐에 따라 유연하게 사용 가능)

그러면 다음 장에서 본격적으로 List에 대해서 파해쳐보자.

 

생각해보기

1. 앞선 ListClientExample 클래스 생성자에서 ArrayList 객체를 List 인터페이스로 교체하면 어떻게 될까?

- 생성자에서 인스턴스를 생성하지 않고, 인터페이스로만 선언한다면 List의 실체(인스턴스)가 없으므로 컴파일이 제대로 되지 않는다.

 

2. 왜 List 인터페이스로는 인스턴스가 생성되지 않을까?

- 자바의 interface는 인스턴스를 생성하는 객체로 사용되지 않는다. interface를 사용해서 어떠한 클래스를 디자인할 것인지 명세(또는 목차)만을 제공한다.

 

따라서 List가 interface로 설계된 이유 역시, List라는 전체 구조를 필요애 따라 구현(ArrayList or LinkedList)할 수 있도록 가이드라인만 제공해준 것이 아닐까.

 

참고

 

댓글 입력
자료실