본문 바로가기
Java

index 가 필요해도 자바 고전 for 문 안쓰는 방법

by ybs 2023. 1. 14.
반응형

먼저 Product 는 item 리스트를 갖고 있다(Product 는 여러개일 수 있다).

@Value
@Builder
public class Product {

	List<Item> items;
}

 

item 은 id 필드만 존재한다.

@Value
@Builder
public class Item {

	String id;
}

 

이제 각 Product 안의 모든 Item id 를 검사하는 로직을 만들어보자. 그런데 2가지 조건이 있다.

1. 모든 Item 들을 다 검사하고, 실패하는 것들은 예외 리스트로 담아서 전달.

2. 예외 객체에 담을 때 item index 정보가 필요.

 

index 정보가 필요하니 가장 먼저 생각나는것은 고전 for문 방식이다. 이중 for문 으로 각 Product 안의 모든 Item 을 검사하고 예외가 발생하면 catch 에서 리스트로 담아 리턴하는 코드다. 간단하고 직관적이다(이 방식이 더 좋다고 느껴질때도 있다).

private static List<CheckException> method1(List<Product> products) {
	List<CheckException> exceptions = new ArrayList<>();
	for (Product eachProduct : products) {
		List<Item> items = eachProduct.getItems();
		for (int itemIndex = 0; itemIndex < items.size(); itemIndex++) {
			try {
				checkItem(items.get(itemIndex), itemIndex);
			} catch (CheckException ex) {
				exceptions.add(ex);
			}
		}
	}

	return exceptions;
}

private static void checkItem(Item item, int itemIndex) {
	if (item.getId().equals("")) {
		throw new CheckException(itemIndex);
	}
}

 

두번째 방법은 stream 을 활용한다. product 리스트 객체에서 stream 을 시작했으니 flatMap 을 사용해야 한다.

cf) 만약 map 을 사용하면 List<Stream<CheckException>> type 이 되버린다.

 

그리고 index 정보를 checkItem 메서드에 전달하기 위해 IntStream.range 를 사용한다. 또 mapToObj 안에서 검사를 정상통과하면 null을 리턴, 예외가 발생하면 예외객체를 리턴시키고 null 이 아닌것만 filter 시켜 리스트로 만든다.

private static List<CheckException> method2(List<Product> products) {
	return products
		.stream()
		.flatMap(eachProduct -> {
			List<Item> items = eachProduct.getItems();

			return IntStream.range(0, items.size())
				.mapToObj(itemIndex -> {
					try {
						checkItem(items.get(itemIndex), itemIndex);
						return null;
					} catch (CheckException ex) {
						return ex;
					}
				})
				.filter(Objects::nonNull);
		})
		.toList();
}

 

두번째 방법이 무조건 좋다고 생각하진 않지만, 다른 방법도 있다는걸 기록하는 차원에서 작성했다.

반응형