요깨비's LAB

[Modern Java] Chapter 5. Stream API - 시작하기 전에 본문

Java/모던 자바

[Modern Java] Chapter 5. Stream API - 시작하기 전에

요깨비 2020. 1. 20. 18:01

1. 함수

1.x1 -> R1
2.x2 -> R2 / x3 -> R2 이 경우에는 서로 다른 입력 값이 같은 결과를 갖는 경우도 있습니다.

하지만, 하나의 입력값으로 두개 이상의 결과는 가질 수 없습니다. 2번의 예를 하나 들어보겠습니다.

public class StreamPrelude {
	public static void main(String[] args ) {
		// 입력값 -1과 1의 결과값은 같다.
		final int abs1 = Math.abs(-1);
		final int abs2 = Math.abs(1);
		
		System.out.println("abs1: " + abs1); // 1
		System.out.println("abs2: " + abs2); // 1
		System.out.println("abs1 == abs2 is " + (abs1 == abs2)); // True
        
		// abs 함수는 Functional에서 말하는 함수의 조건을 충족시켜주지는 못한다.
		final int minInt = Math.abs(Integer.MIN_VALUE);
		final int maxInt = Math.abs(Integer.MAX_VALUE);
        
		// minInt는 2의 32승 * -1 maxInt는 2의 32승-1
		// 따라서 abs(minInt) != abs(maxInt)
		System.out.println("minInt: " + minInt);
		System.out.println("maxInt: " + maxInt);
	}
}

 

2. Identity Function

T -> T 어떠한 값을 입력받아서 그대로 돌려주는 함수인데 '굳이 받아서 그대로 돌려줄 거면 왜 사용하나?'라고 생각할 수 있습니다.

예를하나 들어보겠습니다.

public class StreamPrelude {
	public static void main(String[] args) {
		final int abs1 = Math.abs(-1);
		final int abs2 = Math.abs(1);

		System.out.println("abs1: " + abs1);
		System.out.println("abs2: " + abs2);
		System.out.println("abs1 == abs2 is " + (abs1 == abs2));

		final int minInt = Math.abs(Integer.MIN_VALUE);
		System.out.println("minInt: " + minInt);

		final List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
		System.out.println(map(numbers, i -> i * 2));
		// 만약 아무것도 하고 싶지 않을때?
		// null pointer exception이 발생하므로 map 메서드를 수정하자.
		// [] 리스트가 반환됨...
		System.out.println("mapOld(numbers, null)");
		System.out.println(map(numbers, null));
		
		System.out.println("");
		System.out.println("map(numbers, i->i*2)");
		System.out.println(map(numbers,i->i*2));
		
		System.out.println("");
		System.out.println("map(numbers, i->i)");
		System.out.println(map(numbers,i->i));
		
		System.out.println("");
		System.out.println("map(numbers, Function.identity()");
		System.out.println(map(numbers,Function.identity()));
	}

	private static <T, R> List<R> map(final List<T> list, final Function<T, R> mapper) {
		final List<R> result = new ArrayList<>();
		for (final T t : list) {
			result.add(mapper.apply(t));
		}

		return result;
	}

	private static <T, R> List<R> mapOld(List<T> list, Function<T, R> mapper) {
		final List<R> result;

		if (mapper != null) {
			result = new ArrayList<>();
		} else {
			result = new ArrayList<>((List<R>) list);
		}

		if (result.isEmpty()) { // 이게 무슨 의미지?
			for (final T t : list) {
				result.add(mapper.apply(t));
			}
		}
		// 코드를 이해하기도 어렵고 유지보수하기도 어려움...

		return result;
	}
}

mapOld에 비해 훨씬 이해하기 쉽고 유지보수에 용이하며, bad smell이 나지 않는 코드가 되었습니다.

Comments