럿고의 개발 노트

자바 8의 새로운 개념과 기능 본문

Java Note/모던 자바 인 액션(Modern Java in Action)

자바 8의 새로운 개념과 기능

KimSeYun 2020. 3. 7. 16:09

자바 8의 새로운 개념과 기능

  • 멀티코어 CPU가 대중화 되면서 자바는 병렬 실행에 대해서 고민하게 되었다.
  • 그 전에는 나머지 코어를 활용할 수 있는 Thread가 있었지만, 관리와 사용이 너무 어렵다는 단점이 있었다.
  • 자바 8에서 병렬 실행을 새롭게 단순한 방식으로 접근할 수 있는 방법을 제공했으며 그것이 Stream이다.
  • 또한 자바 8에서는 간결한 코드와 멀티코어 프로세서의 쉬운 활용이라는 두 가지 요구사항을 기반으로 새로운 기능들이 나타났다.

1. 스트림 API

  • 스트림이란 한 번에 한 개씩 만들어지는 연속적인 데이터 항목의 모임이다.
  • 이론적으로 프로그래밍은 입력 스트림에서 한 개씩 읽고 출력 스트림에서 데이터를 한 개씩 기록한다.
  • 또한 어떤 프로그램의 출력 스트림은 다른 프로그램의 입력 스트림이 될 수도 있다.
  • 자바 8에서는 병렬로 지원하는 java.util.stream패키지를 추가하였다.
  • 기존에는 한 번에 한 항목씩 처리했지만, 위의 작업을 구수준으로 추상화해서 일련의 스트림으로 만들어 처리할 수 있는 것이다.
  • 스레드를 사용하지 않아도 병렬성을 얻을 수 있게 되었다.
  • 또한 컬렉션을 처리하면서 발생하는 모호함과 반복적인 코드 문제와 멀티코어 활용 어려움이라는 두가지 문제를 동시에 해결하게 되었다.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FilteringApples {
    private final static List<Apple> inventory = Arrays.asList(
            new Apple(80, "red"),
            new Apple(155, "green"),
            new Apple(120, "green")
    );

    // 순차 처리 방식
    final static List<Apple> heavyApples1 = inventory.stream().filter((Apple apple) -> apple.getWeight() > 150).collect(Collectors.toList());

    // 병렬 처리 방식
    final static List<Apple> heavyApples2 = inventory.parallelStream().filter((Apple apple) -> apple.getWeight() > 150).collect(Collectors.toList());
}    

2. 메서드 참조

  • 자바는 메서드나 클래스 등은 이급 시민이였다. 즉, 프로그램을 실행하는 동안 모든 구조체를 자유롭게 전달할수 없는 것이다.

  • 그래서 자바는 함수형 프로그래밍에서 제공하는 메서드를 일급값으로 사용할 수 있는 기능을 만들었다.

  • 예제 코드

    public class HiddenFiles{
      // java 8 이전 코드
      File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
          @Override
          public boolean accept(File file) {
               return file.isHidden();
          }
      });
    
      // java 8 메서드 참조 이용 코드
      File[] hiddenFiles = new File(".").listFiles((File)::isHidden);
    }
  • 이와 같이, 예전에 객체를 참조해서 객체를 이리저리 주고 받은 것 처럼, 메서드 참조를 이용해 메서드도 똑같은 기능을 할 수 있는 것이다.

3. 람다

  • 메스드를 일급값으로 취급할 뿐 아니라 람다(익명함수)를 포함하여 함수도 값으로 취급할 수 있게 되었다.
  • 람다 문법 형식으로 구현된 프로그램을 함수형 프로그래밍 즉, 함수를 일급값으로 넘겨주는 프로그래밍이라고 한다.
public class filter{
    public static List<Apple> filterGreenApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory){
            if("green".equals(apple.getColor())){
                result.add(apple);
            }
        }
        return result;
    }

    public static List<Apple> filterHeavyApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory){
            if(apple.getWeight() > 150){
                result.add(apple);
            }
        }
        return result;
    }
}
  • 자바 8 이전에는 이런식으로 비슷한 기능을 하는 메서드들을 중복코드가 보이도록 구현했어야 했다.
  • 그러나 자바 8에서는 중복 코드를 최소화 할 수 있게 되었다.
public class Apple {
    private int weight;
    private String color;

    public Apple(int weight, String color) {
        this.weight = weight;
        this.color = color;
    }

    public int getWeight() {
        return weight;
    }

    public String getColor() {
        return color;
    }


    public static boolean isGreenApple(Apple apple){
        return "green".equals(apple.getColor());
    }

    public static boolean isHeavyApple(Apple apple){
        return apple.getWeight() > 150;
    }
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class FilteringApples {
    private final static List<Apple> inventory = Arrays.asList(
            new Apple(80, "red"),
            new Apple(155, "green"),
            new Apple(120, "green")
    );

    public interface Predicate<T>{
        boolean test(T t);
    }

    static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p ){
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory){
            if(p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }

    public static void main(String[] args) {
        filterApples(inventory, (Apple apple) -> "green".equals(apple.getColor()));
        filterApples(inventory, (Apple apple) -> apple.getWeight() > 150);
    }
}
  • 이런식으로 Predicate를 이용해서 함수형 프로그래밍을 구현할 수 있다.
  • 아울러 한번만 사용할 메서드를 따로 구현할 필요가 없어졌다.
  • 그러나 람다가 길어진다면 가독성이 떨어지는 현상이 있기 떄문에, 이를 잘 설명하는 메서드명을 지정해서 메서드 참조를 하는 것이 더 좋다.

4. 인터페이스 디폴트 메서드

  • 디폴트 메서드는 구현 클래스에서 구현하지 않아도 되는 메서드를 인터페이스에 추가할 수 있는 기능을 제공한다. 메서드 본문은 클래스 구현이 아니라 인터페이스의 일부로 포함된다.- 인터페이스를 쉽게 변경할 수 있도록 디폴트 메서드를 지원하게 되었다.
  • 그러나 디폴트 메서드를 사용하는 상황은 흔치 않다. 미래를 위한 기능이기 떄문이다.

정리

  • 자바 8은 프로그램을 더 효과적이고 간결하게 구현할 수 있는 새로운 개념과 기능을 제공한다.
  • 스트림의 개념의 일부는 콜렉션에서 가져왔다. 스트림과 컬렉션을 적절하게 활용한다면 스트림의 인수를 병렬로 처리도 가능하며 가독성도 좋은 코드가 완성될 것이다
  • 책정보

'Java Note > 모던 자바 인 액션(Modern Java in Action)' 카테고리의 다른 글

동작 파라미터화  (0) 2020.03.11
Comments