일급 컬렉션

NNIIE·2022년 9월 27일
0

java

목록 보기
4/7
post-custom-banner

일급컬렉션이란?

CollectionWrapping하면서, WrappingCollection 외의 다른 멤버 변수가 없는 상태를 말한다.

HashMap<Integer, String> hashMap = new HashMap<>();
hashMap.put(1, "1번 학생");
hashMap.put(2, "2번 학생");
hashMap.put(3, "3번 학생");
public class Persons {
	private HashMap<Integer, String> students;
    
    public Persons(HashMap<Integer, String> students) {
    	this.students = students;
    }
}

다음과 같은 이점을 가진다.

  • 비지니스에 종속적인 자료구조
  • Collection의 불변성 보장
  • 상태와 행위를 한 곳에서 관리

비지니스에 종속적인 자료구조

1부터 10까지의 숫자를 만들어내는 기능을 구현해보면

public class Number {
	private static final int MAX_NUMBER = 10;
    
    public void createOfNumber() {
    	List<Integer> numbers = createNumbers();
        validationSize(numbers);
        validationDuplication(numbers);
    }
    
    private void validationSize(List<Integer> numbers) {
    	if (numbers.size() > MAX_NUMBER) {
        	throw new IllegalArgumentException("숫자는 10개 이하여야 합니다.");
        }   
    }
    
    private void validationDuplication(List<Integer> numbers) {
    	Set<Integer> nonDuplicationNumbers = new HashSet<>(numbers);
        if (nonDuplicationNumbers.size() != MAX_NUMBER) {
        	throw new IllegalArgumentException("숫자들은 중복될 수 없습니다.");
        }
    }
}

이럴경우 1부터 10까지의 숫자를 구하는 로직이 필요한 모든 장소에서 검증로직이 들어가야 한다.
이걸 방지하기 위해서는 해당 조건으로만 생성할수 있는 자료구조를 직접 만들면 된다.
그리고 이것이 일급컬렉션이다.

public class Number {
	private static final int MAX_NUMBER = 10;
    
    private final List<Integer> numbers;
    
    public OneToTenNumbers(List<Integer> numbers) {
    	validationSize(numbers);
        validationDuplication(numbers);
        this.numbers = numbers;
    }
    
    private void validationSize(List<Integer> numbers) {
    	if (numbers.size() > MAX_NUMBER) {
        	throw new IllegalArgumentException("숫자는 10개 이하여야 합니다.");
        }   
    }
    
    private void validationDuplication(List<Integer> numbers) {
    	Set<Integer> nonDuplicationNumbers = new HashSet<>(numbers);
        if (nonDuplicationNumbers.size() != MAX_NUMBER) {
        	throw new IllegalArgumentException("숫자들은 중복될 수 없습니다.");
        }
    }
}

이제 1부터 10까지의 숫자를 만들어내는 로직이 필요할 경우 이 일급컬렉션만 있으면 된다.

public class Number2 {
	
    public void createNumber() {
    	OneToTenNumbers oneToTenNumbers = new OneToTenNumbers(createNumbers());
    }
}

불변

일급컬렉션은 불변을 보장한다.
final도 불변을 막아주지 못한다.
final은 불변을 만들어주는 것이 아니고, 재할당만 금지하기 때문이다

public class Orders {
	private final List<Order> orders;
    
    public Orders(List<Order> orders) {
    	this.orders = orders;
    }
    
    public long getAmountSum() {
    	return orders.stream()
        		.mapToLong(Order::getAmount)
                .sum();
    }
}

이 클래스는 생성자와 getAmountSum() 이외의 다른 메서드가 없다
즉, 이 클래스의 사용법은 새로 만들거나 값을 가져오는 것 뿐이다
List라는 컬렉션에 접근할 수 있는 방법이 없기 때문에 값을 변경, 추가가 되지 않기 때문에
이렇게 일급 컬렉션을 사용하면, 불변 컬렉션을 만들수 있다.


상태와 행위를 한곳에서 관리

일급컬렉션은 값과 로직이 함께 존재한다.
여러 pay들이 모여 있고, 이중 네이버페이 금액의 합이 필요하다고 가정해보면

public class PayGroups {
    private List<Pay> pays;

    public PayGroups(List<Pay> pays) {
        this.pays = pays;
    }

    public Long getNaverPaySum() {
        return pays.stream()
                .filter(pay -> PayType.isNaverPay(pay.getPayType()))
                .mapToLong(Pay::getAmount)
                .sum();
    }
}

이런식으로 값과 로직이 한곳에 존재할 수 있게 된다.
만약 다른 결제수단들의 합이 필요하다면,
아래와 같이 변경, 추가 하면 된다

public class PayGroups {
    private List<Pay> pays;

    public PayGroups(List<Pay> pays) {
        this.pays = pays;
    }

    public Long getNaverPaySum() {
        return getFilteredPays(pay -> PayType.isNaverPay(pay.getPayType()));
    }

    public Long getKakaoPaySum() {
        return getFilteredPays(pay -> PayType.isKakaoPay(pay.getPayType()));
    }

    private Long getFilteredPays(Predicate<Pay> predicate) {
        return pays.stream()
                .filter(predicate)
                .mapToLong(Pay::getAmount)
                .sum();
    }
}
post-custom-banner

0개의 댓글