![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/xo5AA/btq7DoG78IA/LhBDCX1GjeeiqK9wvVUEW1/img.png)
Java8 이전에는 원소를 반환하는 타입을 결정하는 것이 어렵지 않았다. 그런데 Java8에 스트림이 등장하면서 이 선택이 복잡한 일이 되어버렸다. 스트림이 반복(iteration)을 지원하지 않기 때문이다. Stream 인터페이스는 Iterable 인터페이스의 추상 메서드를 모두 포함하고 정의한 방식대로 동작하지만 Iterable 인터페이스를 확장하지 않았다. 그래서 for-each로 스트림을 반복할 수 없다. 스트림을 반복하기 위한 방법 어댑터 메서드 Stream를 Iterable로 중개해주는 어댑터를 생성해서 사용한다. // Stream를 Iterable로 중개해주는 어댑터 public static Iterable iterableOf(Stream stream){ return stream::itera..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/Kw3Vx/btq7CHt6mPR/NffUrHaFBk4qd6bmLdhzck/img.png)
스트림을 처음 접하면 이해하기 어렵거나 어떤 장점이 있는지 공감하기 힘들 수 있다. 스트림은 그저 또 하나의 API가 아닌, 함수형 프로그래밍에 기초한 패러다임이기 때문이다. 스트림 패러다임의 핵심은 계산을 일련의 변환으로 재구성하는 것이다. 이때 각 변환 단계는 이전 단계의 결과를 받아 처리하는 순수 함수여야 한다. 순수 함수란? 오직 입력만이 결과에 영향을 주는 함수를 말한다. 순수 함수는 다른 가변 상태를 참조하지 않고, 함수 스스로 다른 상태를 변경하지 않는다. 이렇듯 스트림 연산에 전달되는 함수 객체는 모두 부작용(Side Effect)가 없어야 한다. 스트림 제대로 활용하기 forEach 아래 예제는 스트림 API의 이점을 잘 살리지 못한, 스트림 코드를 가장한 반복 코드이다. Map freq..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/cQ8OPJ/btq66kx9WE1/gc57o7C3uGugzlvvPBwc3k/img.png)
Java8에 추가된 스트림 API는 다량의 데이터 처리를 돕고자 만들어졌다. 스트림 API가 제공하는 핵심 추상 개념은 스트림과 스트림 파이프라인 이렇게 두 가지다. 스트림 API 핵심 추상 개념 1. 스트림 데이터 원소의 유한 또는 무한 시퀀스를 나타낸다. 2. 스트림 파이프라인 원소들로 수행하는 연산 단계를 표현하는 개념이다. 대표적인 스트림 소스로는 컬렉션, 배열, 파일, 정규표현식 패턴 매처, 난수 생성기 등이 있다. 컬렉션 배열 파일 정규표현식 패턴 매처 난수 생성기 무한 스트림 or 유한 스트림 기본 스트림 - IntStream, LongStream, DoubleStream 스트림 파이프라인 특징 스트림 파이프라인은 소스 스트림으로 시작해 종단 연산으로 끝나며, 그 사이에 중간 연산이 들어갈 ..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/eKsd8q/btq6V4BTODN/XTMbLIPKFm7ShouB2Ds791/img.png)
자바가 람다를 지원하면서 API를 작성하는 모범 사례도 바뀌었다. 대표적으로 상위 클래스의 기본 메서드를 재정의해 원하는 동작을 구현하는 템플릿 메서드 패턴을 예로 들 수 있다. 모던 자바에서는 템플릿 메서드 패턴 대신 함수 객체를 받는 정적 팩터리나 생성자를 제공하는 방식을 해법으로 제시하고 있다. 이 말은 함수 객체를 매개변수로 받는 생성자와 메서드를 더 많이 만들어야 한다는 뜻이다. 이 경우에는 함수형 매개변수 타입을 올바르게 선택해야 한다. 이미 자바 표준 라이브러리에는 다양한 용도의 표준 함수형 인터페이스를 제공하고 있다. 따라서 용도에 맞는 게 있다면, 직접 구현하기보다는 표준 함수형 인터페이스를 활용하자. 표준 함수형 인터페이스 java.util.function은 총 43개의 함수형 인터페이..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/bbp3kn/btq6DCyu7Sc/Rm6TKLQgE3gwxt1SD6tUYK/img.png)
람다는 익명 클래스보다 간결하다는 장점이 있다. 그런데 함수 객체를 람다보다 더 간결하게 만드는 방법이 있다. 바로 메서드 참조(Method Reference)다. 메서드 참조의 장점 메서드 참조는 람다의 거추장스러운 코드를 명확하고 간결하게 만들어준다. 다음 예제는 Map에 Key가 있다면 기존 매핑 값을 증가시키는 코드다. //람다 map.merge(key,1,(count,incr)-> count + incr); count와 incr는 크게 하는 일 없이 공간을 차지한다. 이를 메서드 참조로 개선하면 똑같은 결과를 더 보기 좋게 표현할 수 있다. //정적 메서드 참조 map.merge(key,1,Integer::sum); 메서드 참조를 사용하면 매개변수의 수가 늘어날수록 제거할 수 있는 코드가 많아진..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/pc7Q3/btq6AdzHuyL/UXtmUPpSnW9hbP8kST7Juk/img.png)
예전에는 함수 객체를 만드는 주요 수단으로 익명 클래스를 많이 사용했다. 함수 객체 추상 메서드를 하나만 담은 인터페이스의 인스턴스 // 익명 클래스를 함수 객체로 사용 - 낡은 기법이다. Collections.sort(words, new Comparator() { public int compare(String s1, String s2){ return Integer.compare(s1.length(), s2.length()); } }); 하지만 이 방식은 낡은 기법이고 코드가 너무 길어서 함수형 프로그래밍에 적합하지 않다. Java8부터는 추상 메서드가 하나인 인터페이스는 특별한 대우를 받게 되었다. 지금은 함수형 인터페이스로 부르는 이 인터페이스를 람다 표현식으로 만들 수 있게 된 것이다. // 람다식..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/cyip48/btq6erSzDqE/sDm1kN5NT9CFCkAK3GK651/img.png)
1. 웹은 HTTP로 나타낸다. 웹 브라우저에서 URL을 입력하고 웹 페이지가 보여지기까지 클라이언트의 요청과 서버의 응답이라는 과정을 거친다. 클라이언트에서 서버까지 일련의 흐름을 결정하고 있는 것은 웹에서 HTTP(HyperText Transfer Protocol)이라 불린다. 웹은 HTTP라는 약속을 사용한 통신으로 이루어져 있다. 2. 네트워크의 기본 TCP/IP HTTP를 이해하기 위해서는 TCP/IP의 개념을 알아야 한다. 인터넷을 포함해 우리가 일반적으로 사용하는 네트워크는 TCP/IP라는 프로토콜에서 움직이고 있다. TCP/IP는 인터넷에 관련된 다양한 프로토콜 집합의 총칭이며, HTTP도 그중 하나이다. 2.1 IP(Internet Protocol) 인터넷 쇼핑을 할 때 주소를 입력해야 ..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/beNvzA/btq54VsHBfO/USRGAemfEMzSuwggs3ULT1/img.png)
아무 메서드도 담고 있지 않고 단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 인터페이스를 마커 인터페이스라 한다. 대표적으로 Serializeable 인터페이스를 예로 들 수 있다. Serializeable은 자신을 구현한 클래스의 인스턴스는 직렬화할 수 있음을 알려주는 역할을 한다. 마커 애너테이션이 등장하면서 마커 인터페이스가 더 이상 쓸모없게 느껴질 수 있겠지만, 사실 마커 인터페이스는 두 가지 측면에서 마커 애너테이션보다 더 나은 점이 있다. 마커 애너테이션 VS 마커 인터페이스 마커 인터페이스가 가지는 강점 1. 마커 인터페이스는 이를 구현한 클래스의 인스턴스를 구분하는 타입으로 사용할 수 있다. 마커 애너테이션과는 다르게 마커 인터페이스는 타입이기 때문에 마커 애너테이션을 사용했..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/d9j5Fj/btq54VlmrqC/BDSudOwAJ1HIqYN1PLECg0/img.png)
@Override 애너테이션은 상위 타입의 메서드를 재정의했음을 나타낸다. 메서드 선언에만 달 수 있으며, 일관되게 사용하면 여러 가지 버그들을 예방할 수 있다. @Override는 의도를 명확히 나타낸다. @Override 애너테이션을 달아줌으로써 '재정의한다.'라는 의도를 명확히 나타낼 수 있다. 또한, 코드를 잘못 작성(Overriding이 아닌 Overloading)했을 경우 컴파일러가 잘못된 부분을 명확히 알려준다. @Override를 달지 않아도 되는 단 하나의 예외 구체 클래스에서 상위 클래스의 추상 메서드를 재정의할 때는 @Override를 달지 않아도 된다. 구체 클래스인데 아직 구현하지 않은 추상 메서드가 있다면 컴파일러가 이를 알려주기 때문이다. 하지만 @Override를 일괄적으로 ..