Code.presso Java 웹 개발 트랙 체험단 활동 2주차 두번째 코스로, 지난 시간에 이어 패키지와 컬렉션 프레임워크인 List에 대해 학습한 내용을 정리해보려고 한다!

강의 제목은 "Java Programming 초급" 으로, 자세한 정보는 👇🏻아래👇🏻 링크를 통해 확인할 수 있다.

📌 Java Programming 초급 - 강의 정보

✋🏻 포스팅 내 사용된 사진 파일들의 저작권은 모두 코드프레소에 있으며, 강의자료 공유 및 업로드는 불가능합니다.


🏷 패키지

✔️ 패키지란?

패키지관련있는 클래스를 한 데 묶어 놓은 그룹을 의미한다.

패키지는 클래스를 구분하는 일종의 디렉토리하위 계층 구조를 가질 수 있다.


✔️ 패키지명의 작성

패키지명은 소문자로만 작성하고 클래스들의 묶음을 표현하는 의미 있는 이름으로 작성해야 한다.
패키지는 계층 구조를 가지며 일반적으로 1차도메인.회사명 으로 시작된다.

  • com.회사명.프로젝트명.모듈명.서브모듈명
  • org.회사명(-조직명).프로젝트명.모듈명.서브모듈명
  • 예) ➡️ com.codepresso.newtube.user

또한 패키지를 생성하면 실제 디렉토리도 실제 생성되는데, 이때 패키지의 이름과 구조는 실제 OS의 디렉토리 구조와 매핑된다.

패키지명은 사진과 같이 계층 구조의 전체 이름을 모두 포함하고 하위 계층 구조는 점(.)을 통해 구분할 수 있다.

📌 FQCN (Fully Qualified Class Name)
클래스의 FQCN은 패키지 명을 모두 포함한다
➡️ 패키지명 + 클래스명


✔️ 패키지의 선언

모든 클래스는 반드시 하나 이상의 패키지에 속한다.

클래스 생성시 패기지를 선언하지 않으면, 이름 없는 패키지(Unnamed Package)에 포함되고,
패키지를 선언하지 않은 모든 클래스들은 모두 동일한 패키지에 속한다.

패키지를 선언한다는 것해당 클래스가 어떤 패키지에 있다고 명시하는 것이다.
package 키워드를 통해 패키지명을 선언할 수 있고, 이 선언문은 .java 파일의 가장 첫번째 라인에 작성한다.
모든 클래스에 단 한번만 패키지를 선언할 수 있다.

Intellj 에서 위와 같은 방법으로 패키지를 생성할 수 있다.

패키지를 생성한 후 패키지 안에 User 라는 클래스를 생성해보자.

클래스를 생성하게 되면 클래스 파일에 위와 같이 자동으로 선언문이 생긴 것을 확인할 수 있다.


✔️ 다른 패키지의 클래스 사용하기 - import

다른 패키지에 속한 클래스를 사용할 때에는 클래스의 FQCN을 사용해야 한다.
FQCN의 반복을 피하기 위해 import 문을 선언한다.

UserManager 클래스에서 User 클래스를 사용하기 위해서는 UserManager 소스코드 상단에 import 문을 이용하여 선언문을 추가해야 한다.

만약 특정 패키지 내의 모든 클래스 사용하는 경우에는 FQCN 대신 패키지명.* 으로 특정 패키지 내의 모든 클래스를 사용 가능하다.


✔️ default 접근 제어자

접근 제어자를 명시하지 않으면, default 접근 제어자가 자동으로 적용된다.

같은 패키지 내에서는 접근 가능하지만, 다른 패키지에서는 접근이 불가능하다.
패키지에서만 사용 가능하게 하고 다른 패키지에서는 접근을 못하게 하고 싶다면, public으로 두지 말고 default를 사용하는 것이 좋다.


✔️ protected 접근 제어자

protected 접근 제어자같은 패키지 간에는 접근이 가능하다.

또한 상속 관계에서, 부모 클래스의 패키지가 달라도 자식 클래스에서 부모 클래스의 멤버에 접근이 가능하다는 특징이 있다.

protected 접근 제어자는 모든 자식 클래스에서의 접근을 가능하게 한다.
외부 패키지에 있는 자식 클래스라도 접근이 가능하다.
사진을 봤을 때, 다른 패키지에 존재하지만 User 클래스를 상속하고 있는 PaidUser 클래스에서는 접근이 가능하다.
그러나 패키지가 다르면서 상속관계도 아닌 UserManager 에서는 접근이 불가능하다!


🏷 컬렉션 프레임워크의 개념

✔️ 컬렉션 프레임워크(collection framework)란?

여러 건의 데이터를 다루기 위해서는 Array 와 같은 데이터를 다루기 위한 자료구조의 구현체가 필요하다.

컬렉션 프레임워크란, 다양한 자료구조의 구현을 위한 클래스와 인터페이스의 집합이다.

자바의 컬렉션 프레임워크에서는 각각의 특성에 알맞은 클래스 라이브러리를 제공하고 있다!

  • java.util.ArrayList<E>
  • java.util.HashSet<E>
  • java.util.HashMap<K,V>

이 세가지 각각에 대해서는 바로 다음 강의부터 자세히 학습할 수 있다!


✔️ 컬렉션 프레임워크 클래스와 Array

Array 는 데이터 개수의 변경이 불가능했지만, ArrayList데이터 개수의 동적인 변경이 가능하다.

또한 Array 의 데이터 타입은 객체는 물론 Primitive type 값을 가질 수가 있었지만, ArrayList객체만을 원소로 가진다.


✔️ 컬렉션 프레임워크의 주요 인터페이스

컬렉션 프레임워크에는 다양한 자료구조를 제공하기 위해서 위와 같은 총 3개의 주요 인터페이스를 제공한다.

List Set 인터페이스가 한 그룹, Map 인터페이스를 한 그룹으로 나누는데 그 이유는 상속받는 인터페이스가 다르기 때문이다!

java.util.Collection<E> 인터페이스 그룹

  • List Set 인터페이스는 모두 Collection 인터페이스를 상속받는다.
  • 여러개의 원소를 위치 순서에 따라 가진다.

java.util.Map<K,V> 인터페이스 그룹

  • Map 인터페이스는 구조상의 차이로 Collection 인터페이스를 상속받지 않고 독립적으로 정의되어 있다.

✔️ 주요 인터페이스들 특징

  1. java.util.List<E> 인터페이스

java.util 이라는 패키지에 구현체가 존재하게 된다.

  • 순서가 존재하는 데이터의 집합이다
  • 데이터의 중복을 허용한다.
  • List 인터페이스를 구현한 ArrayList LinkedList Stack 클래스들 또한 동일한 특징을 가진다.

  1. java.util.Set<E> 인터페이스

java.util 이라는 패키지에 구현체가 존재하게 된다.

  • 순서가 없는 데이터의 집합이다
  • 데이터의 중복을 허용하지 않는다.
  • Set 인터페이스를 구현한 HashSet TreeSet 클래스들 또한 동일한 특징을 가진다.

  1. java.util.Map<K,V> 인터페이스

java.util 이라는 패키지에 구현체가 존재하게 된다.

  • KeyValue 로 이루어진 pair를 가지는 데이터의 집합이다.
  • 데이터들 간의 순서가 없다.
  • Key 는 중복을 허용하지 않고, Value 는 중복을 허용한다.
  • Map 인터페이스를 구현한 HashMap TreeMap 클래스들 또한 동일한 특징을 가진다.

🏷 제네릭과 컬렉션 프레임워크

제네릭(Generic) 이란 데이터의 타입을 일반화(Generalize)한다는 의미이다.
클래스나 메소드에서 사용할 데이터의 타입을 컴파일 시 type check 하여 런타임 시의 안정성이 보장된다.


✔️ 제네릭의 사용

1. 제네릭을 사용한 클래스 정의 문법
➡️ class [ClassName]<T>

  • <T> : 클래스 내부에서 사용될 임의의 데이터 타입을 T 라는 타입 변수로 지정한다.
  • 타입 변수 T 를 이용해 클래스 내부 변수 생성 및 메소드 인자, 반환 값의 타입 지정이 가능하다.
  • T 는 임의 값으로 지정이 가능하다.

2. 제네릭을 사용한 클래스 객체 생성 문법
➡️ [ClassName]<[Type-Class]> [object-name] = new [ClassName]<>();

  • ClassName : 생성하고자 하는 클래스 지정
  • Type-Class
    • 클래스 정의 시 지정한 타입 변수에 사용할 실제 데이터 유형 클래스이다.
    • Primitive Type 데이터의 경우 Wrapper Class를 사용한다.
      (int➡️Integer, float➡️Float, double➡️Double...)

✔️ 제네릭의 장점

가장 큰 장점은 바로 클래스 내 임의의 변수를 매번 다른 데이터 타입으로 지정하여 객체 생성이 가능하다는 것이다.

int 로도 쓰고, String 으로도 쓰는 범용성을 제네릭으로부터 얻어낼 수 있다.

📌 Object 는 최상위 클래스이므로 제네릭과 같은 범용성 확보가 가능하다.

그러나 이 경우, 컴파일 시 타입 체크가 되지 않는다!


🏷 List 자료구조 컬렉션 클래스

✔️ List 자료구조 데이터

List 자료 구조 데이터로 매분 마다 수집 된 하루치 주식 가격 데이터를 예로 들 수 있다.

이는 여러 건의 데이터를 하나로 묶어서 관리한다는 특징이 있다.
또한 이 데이터들은 순서가 존재하고, 중복되는 데이터가 존재할 수 있다!


✔️ List<E> 인터페이스에 대한 이해

이제부터 List<E> 인터페이스에 대한 이해를 조금 더 높여보자😃❗️

List<E> 인터페이스는 Collection<E> 인터페이스를 상속하여 정의된 인터페이스이다.

그렇다보니, 위와 같이 Collection<E> 인터페이스에서 정의된 메소드에 List 자료구조에 필요한 메소드가 추가로 정의되어 있다!

대표적인 List 자료구조의 컬렉션 클래스로는 ArrayList<E> 가 있다.

💡 ArrayList<E> 클래스 특징

  • Array 와 가장 유사한 컬렉션 클래스이다.
  • Array 처럼 객체 내부 데이터에 접근하기 위한 인덱스가 존재한다.
  • Array 와 다르게 생성된 객체에서 데이터의 추가과 삭제가 자유롭게 가능하다.
  • java.util 패키지에 존재한다.

✔️ ArrayList<E> 객체의 생성과 데이터 추가

1️⃣ ArrayList<E> 객체 생성

객체 생성 문법은, 앞서 배웠던 제네릭한 type variable을 포함하는 클래스 객체를 생성하는 방법과 동일하다.

ArrayList 클래스는 java.util 패키지에 존재하기 때문에, 이를 가져오기 위해서는 클래스가 존재하는 전체 path 정보를 넣어주어야 한다.
➡️ import java.util.ArrayList


2️⃣ ArrayList<E> 객체의 데이터 추가

  1. boolean add(E e)
  • 객체 생성 시 정의한 데이터 타입을 인자로 전달하여, 마지막 위치에 추가한다.
  • 수행 결과로 boolean 타입의 값을 반환한다.

📌 Class 객체를 데이터로 추가할 수도 있다


  1. void add(int index, E e)
  • 객체 생성 시 정의한 데이터의 타입과, 추가하고자 하는 위치의 인덱스 정보를 인자로 전달하여 해당 위치에 데이터를 추가한다.

  1. boolean addAll(Collection<? extends E> C)
  • 인자로 전달한 Collection 객체의 데이터들을 모두 추가한다.
  • 단, ArrayList 객체 생성 시 정의한 데이터 타입을 원소로 가지는 Collection 객체여야 한다.

  1. boolean addAll(int index, Collection<? extends E> C)
  • 원하는 위치에 인자로 전달받은 Collection 객체의 데이터들을 추가한다.

✔️ ArrayList<E> 객체의 데이터 탐색과 변경

1️⃣ ArrayList<E> 객체의 데이터 탐색

  1. E get(int index)
  • 전달받은 인덱스 위치에 저장되어 있는 데이터를 반환한다.

  1. int indexOf(Object o)
  • 전달받은 데이터가 저장되어 있는 인덱스 번호를 반환한다.
  • 데이터가 존재하지 않는 경우, -1 을 반환한다.

  1. boolean contains(Object o)
  • 전달받은 데이터의 객체 포함여부를 확인하여 boolean 타입으로 결과를 반환한다.

  1. int size()
  • 객체에 저장되어 있는 데이터의 개수를 조회한다.

2️⃣ ArrayList<E> 객체의 데이터 변경

  1. void clear()
  • [ArrayList 객체 이름].clear()
  • 객체 내의 모든 데이터를 제거한다.

  1. E remove(int index)
  • 전달받은 인덱스 위치의 데이터를 제거하고 해당 데이터를 반환한다.

  1. boolean remove(Object o)
  • 전달받은 데이터를 객체에서 제거하고 수행 결과를 boolean 타입으로 반환한다.

  1. boolean removeAll(Collection<?> c)
  • 인자로 전달한 Collection 객체가 가지고 있는 데이터들을 모두 제거한다.

  1. E set(int index, E e)
    - 전달받은 인덱스 위치의 데이터를 수정하고, 기존의 데이터를 반환한다.

✔️ ArrayList<E> 객체의 데이터 정렬

1️⃣ ArrayList<E> 객체의 데이터 정렬

  1. void java.util.Collections.sort(List<T> list)
  • java.util.Collections 클래스의 static sort 메소드를 사용해 데이터를 오름차순으로 정렬한다.
  • 인자로 정렬하고자 하는 List<T> 인터페이스 구현 클래스의 객체를 전달한다.

  1. void java.util.Collections.reverse(List<T> list)
  • java.util.Collections 클래스의 static sort 메소드를 사용해 데이터를 내림차순으로 정렬한다.
  • 인자로 정렬하고자 하는 List<T> 인터페이스 구현 클래스의 객체를 전달한다.

✔️ Array 객체를 이용한 ArrayList 객체 생성

현재까지는 ArrayList 객체를 생성할 때 비어있는 ArrayList 를 생성하고 add() 와 같은 메소드를 통해 데이터를 넣어주었다.

그러나 실제 프로그래밍을 할 때는 Array 객체를 이용하는 경우가 더 많다!

java.util.Arrays 클래스의 static asList() 메소드를 사용하여 객체를 간단히 생성할 수 있는데, 여기서 주의할 점은 이 클래스가 jav.util.ArrayList 클래스와는 다르다는 것이다!

사진과 같이 ArrayList 를 만들기 위해 필요한 데이터들을 data 라는 배열으로 만들어주고, 이를 Arrays 라는 클래스에 존재하는 asList() 메소드의 인자로 넣어준다.


코드프레소 홈페이지(https://www.codepresso.kr/)에는 오늘 포스팅한 패키지와 List 관련 강의뿐만 아니라 다양한 강의들이 개설되어 있으니 모두 한번 씩 살펴보고 수강해보면 좋을 것 같다😃

profile
Backend Developer

0개의 댓글