Java에서는 여러가지 자료구조를 제공하기 위해서
java.util을 통해 Collections라는 기본 인터페이스를 내장하고 있다.
여기에서 나오는 각종 자료구조들을 우리가 프로그래밍에서 사용하게 된다.
Collection을 상속받는 인터페이스는 크게 List, Set이 있으며
Collection을 상속받는 인터페이스는 아니지만 Map도 Collection으로 분류한다.
제일 상위에 있는 만큼
Collection은 상속할 인터페이스, 클래스에게 공통적으로 중요한 메소드를 정의한다.
그런데 이러한 메소드들을 살펴보면 상당히 특이한 부분이 있다.
이 메소드들은 진짜 너무나도 기초적인부분인데, 마치 수학에서의 집합과 매우 유사하다.
그리고 더 나아가서 생각해보면 이런 자료구조들은 수학에서의 집합과 다를바가 없다.
Collection 인터페이스를 살펴 보면서 엿볼 수 있는 수학적 철학을 살펴보고자 한다.
1. Iterable
먼저, Collection은 java.util의 Collection.java에서 다음과 같이 정의한다.
public interface Collection<E> extends Iterable<E> { ... }
Collection 보다 상위의 인터페이스인 Iterable이 존재하고, Iterable.java에서는 다음을 정의한다.
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
Iterable이 최상단 인터페이스이다. 여기서 Iterartor의 생성,
default method인 forEach와 Spliterator를 정의한다.
더 이상 깊게 파지는 않고, 간단히 이 부분을 설명하자면
Iterable은 각각 하나의 원소에 대해 실행 가능한 환경(forEach)을 구성하고
이 자료를 동일한 성질의 자료로 나누는 기능을 제공한다.
이를 수학적 개념으로 설명하자면
집합에서 하나의 원소를 다른 원소로 대응시키는 함수의 기본 골격을 만든 셈이라고 보면 되겠다.
에서 Y를 제외한 부분의 기본 골격을 구성한 것이라고 보면 될 것이다.
2. Collection
다시 원래대로 돌아와서 Collection이 가지고 있는 메서드들과 이에 대응하는 수학적 개념은 다음과 같다.
메서드 | 설명 | 유사한 수학적 개념 |
isEmpty() | 객체가 비어있는지 확인 | 집합이 공집합인지를 확인 |
contains(Object o) | o라는 객체가 있는지 확인 | a∈A 인지를 확인 |
add(), remove() | 객체에 추가, 혹은 삭제 | 합집합과 차집 |
size() | 객체에 있는 원소의 개수 반환 | |A| : 집합의 크기(기수) |
equals() | 두 객체가 동등한지 확인 | A=B인지를 확인한다. |
그 외에도 Array로 바꾸기 위한 toArray나 객체의 내용을 전부 없애는 clear과 같은 것이 정의되어 있다.
3 - 1. Collection - List interface에서
어떤 집합이 있을 때, 그것의 모든 원소의 순서를 정의할 수 있는 집합이 있다.
이를 totally ordered set, 전순서 집합이라고 하는데 실수 Field가 그 대표적인 예시다.
collection중에서도 마찬가지로 순서를 정의할 수 있는 인터페이스들이 있다.
List의 ArrayList, LinkedList, Vector와 같은 경우, 이러한 순서가 존재한다.
정확히는 우리가 순서를 임의로 정하는 것이지만, 그렇게 정한 index가 순서를 유지하기에 비슷하다 볼 수 있다.
여기서 메모리 접근 방식과 연결방식에 따라 저 세 가지 경우의 수로 나뉘게 되는 것이다.
3 - 2. Collection - Set interface에서
Set은 수학에서의 집합과 완전히 동일하다. Collection interface에서 정의한 add와 같은 메서드는
이 과정에서 중복될 경우 다시 추가하지 않는 방식으로 override된다.
4. Map
Map은 Collection과는 다른 범주의 자료구조 인터페이스이지만, Map에서는 어떤 원소를 저장할 때
key-value를 기반으로 받는 형식이다.
하나의 key값에 대해서는 하나의 value만을 구성할 수 있다.
달리 생각하자면, 하나의 key값에 대해 하나의 value만이 대응된다.
Map<Integer, Value> map = new HashMap<>();
map.put(1, "A");
map.put(1, "B");
System.out.println(map.get(1)); // "B"만이 출력
이는 key를 정의역의 원소, value를 공역의 원소라고 봤을 때
함수의 정의와 정확히 일치하는 내용이다.
그리고 Redis와 같은 NoSQL DB에서는 하나의 키에 단일 값만이 매핑된다.
이러한 경우, Java는 아니지만 이러한 구조를 명시하는 DB에서는 단사 함수적 성질을 가지게 되는 것이다.
출처 : java.util
https://docs.oracle.com/javase/7/docs/api/java/util/package-summary.html
https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
https://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html
https://docs.oracle.com/javase/7/docs/api/java/util/Map.html
'연재작 > 프로그래밍 언어' 카테고리의 다른 글
Java - Optional 뽀개기 (1) (0) | 2024.10.11 |
---|---|
Java - Stream 뽀개기 (2) (2) | 2024.10.06 |
Java - Stream 뽀개기 (1) (feat. 함수형 인터페이스) (0) | 2024.10.06 |
monad 패턴, optional, promise, stream (1) | 2024.10.05 |
수학적 철학을 가미한 함수형 프로그래밍 (1) | 2024.08.31 |