자바 8 특징

JAVA 2015. 8. 29. 15:58

자바 8의 특징은 무엇인가?

1) 람다식의 출현

람다식을 간략히 정리하면 변수에 로직을 대입하는 것을 말한다.


2) foreach 메소드의 등장

foreach는 자바스크립트에서 보았듯이 객체를 전달하여 index를 지정하여 iteration하는 것이 아니라 array나 list등을 전달하여 자동적으로 순회하게끔 하는 것이다. 



[참고]JIT컴파일러란 무엇인가?

Just In Time 컴파일러라는 뜻으로 인터프리터의 장점과 컴파일러의 장점을 모두 활용하여 사용하는 것입니다. 일부는 컴파일된 기계어를 만들고, 일부는 바이트 코드를 해석하는 것을 통해 번역속도와 실행속도의 장점을 취하는 방법입니다.

[참고] 컴파일러 vs 인터프리터

컴파일러는 번역속도가 느린 대신에 실행 속도가 빠르고 (전체를 기계어로 번역해놓기 때문에 실행속도가 빠름)

인터프리터는 번역속도가 빠른 대신에 실행 속도가 느리다.(번역한 코드를 한줄한줄 해석하여 실행하기 때문)


람다식

람다식은 무엇인가? 

변수에 로직을 대입할 수 있는 문법을 말한다. 기존의 익명함수의 사용을 보완하여 더 간결하고 가독성 좋은 코드를 만들 수 있다. 

람다식을 이해해보자.

참조 : http://jinson.tistory.com/208

위의 참조에서 좋은 글귀를 보고 나름대로 이해하고 해석해서 다시 재작성해본다. 

람다식이 필요한 이유를 다음과 같이 설명해주고 있다. 

우선 리스트와 리스트의 모든 원소를 이터레이션하는 코드를 작성해보자.

1
2
3
4
5
List<Integer> numbers = Arrays.asList(123456); 
 
for (int number : numbers) {
    System.out.println(number);
}
cs

우리는 이러한 리스트를 순회할 때 간단히 for문을 통해서 로직을 수행하는데 여기에 숨겨진 깊은 뜻이 있다고 한다. 

딸과 함께 거실에 떨어져있는 장난감을 주울려고 한다. 

나: "소피아, 장난감 정리하자. 땅에 어떤 장난감이 있지?"

소피아: "어. 공이 있네"

나: "그래. 공을 박스에 넣자. 땅에 또 뭐가 있지?"

소피아: "어. 인형이 있지"

나: "그래. 인형을 박스에 넣자. 땅에 또 뭐가 있지?"

소피아: "어. 책이 있네"

나: "그래. 책을 박스에 넣자. 땅에 또 뭐가 있지?"

소피아: "아니. 아무것도 없어"

나: "잘했네. 이제 다 했다"

사실 바닥에 있는 장난감을 주워라고 한 마디로도 이해하고 실행할 수 있는 것이 사람이지만 실제로 다음과 같은 과정이 가지고 오는 이점 또한 있다. 소피아는 양손에 장난감을 들어 박스에 넣을 수도 있고, 박스로부터 가벼운 것부터 나를 수도 있을 것이라는 것이다. 즉 내부 이터레이션을 수행 할 수 있다는 것이다. 즉 JIT컴파일러가 내부적으로 병렬화하여 원소 처리를 최적화해서 처리할 수도 있다는 말이다. 


다음의 예를 보자.

자바 8 이전에는 내부이터레이션을 사용하기 위해서는 이름 없는 내부클래스를 만들어야 했다. 

1
2
3
4
5
numbers.forEach(new Consumer<Integer>() {
    public void accept(Integer value) {
        System.out.println(value);
    }
});
cs

반복문을 순회하면서 새로이 만들어진 consumer객체의 accept를 정의하여 호출하고 있다.

위의 코드를 자바 8에서의 람다식을 이용해서는 다음과 같이 처리할 수 있다. 


1
numbers.forEach((Integer value) -> System.out.println(value));
cs


화살표의 왼쪽은 매개 변수 목록이고, 오른쪽은 몸체이다. 컴파일러는 내부적으로 람다식을 분석하여 Consumer클래스의 미구현된 메소드(즉, accept 메소드)와 동일한 타입인지 검사하여 람다식을 마치 consumer인터페이스를 구현한 클래스인 것처럼 활용한다. 

내부적으로 accept인지를 분석한다고 했으므로 컴파일러는 분석능력이 있는 것이다. 다음과 같이 인자를 생략해도 가능하다고 한다. 

1
numbers.forEach(value -> System.out.println(value));    // 식(1)
cs

이 문장 역시도 더 줄일 수 있다. 자바 8에서 새로이 등장할 메소드 참조(method reference)를 활용하면

더 간단하게 만들 수도 있다. 자바 8에서 도입될 :: 구문을 활용하여 다음과 같이 정적 메소드나 인스턴스 메소드를 참조할 수 있다. 

1
numbers.forEach(System.out::println);  // 식(2)

cs


람다식은 왜 필요한가?

간단히 말하면 익명함수를 사용할 것이라면, 복잡하지 않게 간결함을 제공해주겠다는 것이 그 필요 이유라고 할 수 있다.


Map의 HashCollision 처리 변화

Java 8에서도 역시 해시맵의 충돌을 Seperate Chaining 방식을 통해 해결한다. 하지만 이전과 다르게 해시충돌이 일어난 리스트의 개수가 8개 이상이 되면 링크드 리스트가 아닌 트리로 바꾼다. 그리고 6개까지 줄어들면 다시 링크드 리스트로 바꾼다.

왜 하나의 수를 경계로 삼지 않고 해시충돌의 수를 8개, 6개로 하는가 하면 데이터의 수가 하나를 경계로 왔다갔다할 때는 리스트에서 트리로 바꾸거나 트리에서 리스트로 바꾸는 오버헤드가 증가하기 때문에 이렇게 로직을 구성한다.








Posted by slender ankles
,