본문 바로가기
2023 활동 - 4학년/[1월 ~ 4월] sw 아카데미 백엔드 과정

[2023.01.12 / CNU SW 아카데미] JAVA Collection 이야기

by 은행장 노씨 2023. 1. 12.

 

 

프레임워크를 위한 JAVA

Collection 이야기

- Collection은 개발할 때, 가장 많이 사용한다. 

- 여러 데이터의 묶음

- 컬렉션은 추상체이다. 

- 구상체 ) List -> LinkedList, ArrayList, Vector, Stack

- 구상체 ) Set -> HashSet

 

 

예제 1) List를 만들어서 요소를 전부 print하자. 

import java.util.*;
import java.util.function.Consumer;

class MyCollection<T> {
    private final List<T> list;
    public MyCollection(List<T> list){
        this.list = list;
    }
    public void foreach(Consumer<T> consumer) {
        for(int i = 0; i < list.size(); i++) {
            // TODO
            T data = list.get(i);
            consumer.accept(data);
        }
    }
}

class Main {
    public static void main(String[] args) {
        new MyCollection<Integer>(Arrays.asList(1,2,3,4,5))
                .foreach(System.out::println);
    }
}

 

예제 2) List를 형변환하는 함수를 만들어보자. 

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;

class MyCollection<T> {
    private final List<T> list;
    public MyCollection(List<T> list){
        this.list = list;
    }
    public void foreach(Consumer<T> consumer) {
        for(int i = 0; i < list.size(); i++) {
            // TODO
            T data = list.get(i);
            consumer.accept(data);
        }
    }
    public <U> MyCollection<U> map(Function<T, U> function) {
        List<U> newList = new ArrayList<>();
        foreach(d -> newList.add(function.apply(d)));
        return new MyCollection<>(newList);
    }
}

class Main {
    public static void main(String[] args) {
        new MyCollection<>(Arrays.asList("A", "BB", "CCC", "DDDD", "EEEEE"))
        	.map(String::length);
        	.foreach(System.out::println);        // 1 2 3 4 5
    }
}

 

예제 3) 조건에 맞게 filter 하는 메소드를 구현해보자. 

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

class MyCollection<T> {
    private final List<T> list;
    public MyCollection(List<T> list){
        this.list = list;
    }
    public void foreach(Consumer<T> consumer) {
        for(int i = 0; i < list.size(); i++) {
            // TODO
            T data = list.get(i);
            consumer.accept(data);
        }
    }

    public MyCollection<T> filter(Predicate<T> predicate) {
        List<T> newList = new ArrayList<>();
        foreach(d -> {
            if (predicate.test(d)) newList.add(d);
        });
        return new MyCollection<>(newList);
    }
    public <U> MyCollection<U> map(Function<T, U> function) {
        List<U> newList = new ArrayList<>();
        foreach(d -> newList.add(function.apply(d)));
        return new MyCollection<>(newList);
    }
}

class Main {
    public static void main(String[] args) {
        new MyCollection<>(Arrays.asList("A", "BB", "CCC", "DDDD", "EEEEE"))
                .map(String::length)
                .filter(i -> i % 2 == 0)
                .foreach(System.out::println);        // 1 2 3 4 5
    }
}

 

메소드들끼리 연결되는 형식 -> method chaining 형식

- 범용적인 형태의 collections을 만들 수 있다. 

- 여러개의 데이터를 한꺼번에 묶어서 다룰 수 있다. 

- collection은 데이터의 묶음이다. 

 

모두 묶여 있는 하나의 데이터 덩어리를 내보낸다. 

 


2. Iterator

  • 여러 데이터의 묶음을 풀어서 하나씩 처리할 수 있는 수단을 제공합니다.
  • next()를 통해서 다음 데이터를 조회할 수 있습니다.
  • 역으로 움직일 수 없습니다. (이전데이터를 조회할 수는 없습니다.)

 


3. Stream

  • Java 8 이상에서 부터 사용 가능합니다.
  • 데이터의 연속입니다.
  • (System.in / System.out 이것도 스트림 입니다. 이미 우리가 쓰고 있던 겁니다.)
  • Collections.stream() 을 제공해줍니다. (Java8)
  • filter, map, forEach 같은 고차함수(함수를 인자로 받는 함수)가 제공이 됩니다.
  • Stream을 만들때는 Stream.generate 과 Stream.iterate 으로 만들 수 있습니다.
  • 스트림을 사용하면 연속된 데이터에 대해서 풍부한 고차함수들을 사용하여 강력한 기능을 간결하게 표현할 수 있습니다.
  • 익숙해지면 굉장히 편리해 집니다.
  • 자주 사용해보다보면 익숙해 집니다.

 

- 0부터 200까지 랜덤으로 뽑은 후에 정렬해서 출력하라. 

class Main {
    public static void main(String[] args) {
        Random r = new Random();
       int[] arr = Stream.generate(() -> r.nextInt(200) )
               .limit(5)
               .sorted(Comparator.reverseOrder())
               .mapToInt(i -> i)
               .toArray();

        System.out.println(Arrays.toString(arr));
    }
}

 


4. Optional

- NPE : Null Pointer Exception (가장 많이 발생하는 에러 중 하나)

- 자바에서는 (거의) 모든 것이 레퍼런스 ==> (거의) 모든 것이 null 이 될 수 있다. 

- 항상 null을 확인할 필요가 있다. 

- 이제부터 null을 쓰지마! => 서로 약속! : 계약을 하고 프로그래밍 한다. 

 

(1) EMPTY 객체를 사용하는 방법

(2) Optional을 사용한다. 

 

Optional은 null이 될 수 있는 값을 운반시킬 수 있는 캐리어다. 

 

- Optional 사용 예시

class Main {
    public static void main(String[] args) {
        Optional<User> optionalUser = Optional.empty();
        optionalUser = Optional.of(new User(1, "2"));

        optionalUser.isEmpty();         // 값이 없으면 true
        optionalUser.isPresent();       // 값이 있으면 true
    }
}

 

Optional 코드 작성하기

  • null 데이터 : Optional.empty()
  • 데이터 : Optional.of(DATA)
  • 확인 : .empty() .isPresent()
optionalUser.ifPresent(user -> {
            // do consumer
        });
        
optionalUser.ifPresentOrElse(
        user -> {
            // do consumer
        },
        ()-> {
            // do Runnable
        });

 

되도록 null을 사용하지 않는다. 요즘 프로그래밍의 트랜드이다.