ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JAVA 8 핵심만 정리했다
    JAVA 2019. 2. 22. 22:27
    반응형
    들어가며
    JAVA 12 가 나오는 마당에 아직도 어쩔수 없이(?) JAVA 8을 사용하지 못하는 사람들을 위해 JAVA 8 의 기본 사항만 짧게 정리해 봤다. 

    이런 강좌(?) 같은 글을 처음 써 보기 때문에 확신할 수 는 없지만, 대략, 자바 초보부터 전문가 까지 두루두루 읽고 이해할 수 있게 작성하는 것이 목표다.


    새로운 기능
    JAVA 8 은 JAVA 의 중요한 릴리즈 버전 중 하나를 말한다. 2014년에 최초 릴리즈 되었으며, 다음의 기능을 지원한다. 

    • Lambda expression - 자바에서 Functional 프로그래밍이 일정 부분 가능해졌다.
    • Method reference - 함수를 파라메터로 사용할 수 있다.
    • Default method - 인터페이스에서 기본 메소드를 구현할 수 있다.
    • New tools - 새로운 컴파일러 도구와 유틸리티가 추가 되었다. (이건 잘 모름)
    • Stream API - 자바에서 파이프라인 처리가 가능하다.
    • Date Time API - 드디어… 날짜 시간 함수가 쓰레드에서 안전해졌다.
    • Optional - null 값 처리에 대한 자바 나름대로의 표준을 제공한다.
    • Nashorn, Javascript Engine - 자바스크립트 코드를 자바에서 실행 한다. (이건 잘 모름)


    설치
    이건… 알아서 하자…



    Lambda expression
    Syntax
    람다의 표현식은 다음과 같다. 
    parameter -> expression body

    특징
    • 람다는 파라메터의 타입을 선언할 필요가 없다. 컴파일러가 파라메터의 값을 보고 판단한다. 
    • 파라메터가 한개인 경우는 괄호로 감싸지 않아도 된다. 단, 두개 이상인 경우라면 괄호로 감싸야 한다.
    • expression body 가 단일 명령어 행이면, 중괄호({})를 생략해도 된다. 단일 명령어 행이 아니면, 중괄호를 꼭 써야 한다. 
    • 중괄호의 존재 여부에 따라 return 구문을 생략할 수 있다. 

    // 타입 선언
    (int a, int b) -> a + b;

    // 타입 선언 생략
    (a, b) -> a + b;

    // return 구문사용 (중괄호 필요)
    (a, b) -> { return a * b; };

    정리하면
    • 람다는 단일 메소드만을 가진 인터페이스를 정의하는 데 주로 사용한다. 
    • 람다 표현은 익명 클래스의 필요성을 제거하고, 매우 간단하게 funtional 프로그래밍을 할 수 있게 한다. 


    Method reference
    Syntax
    메소드 참조의 표현식은 다음과 같다. 
    Class::new

    메소드 참조는 다음의 경우에 사용한다. 
    • 정적 메소드 호출
    • 인스턴스 메소드 호출
    • new 연산자를 사용한 객체 생성

    Sample Code
    List names = new ArrayList();

    names.add(“지우”);
    names.add(“호준”);
    names.add(“연석”);
    names.add(“세종”);

    names.forEach(System.out::println);



    Default method
    Java 8은 인터페이스에서 기본 메소드라는 새로운 개념을 도입했다. 

    Syntax
    public interface vehicle {

        default void print() {
            System.out.println("I am a vehicle!");
        }

    }

    Multiple Default
    인터페이스의 기본 메소드를 사용하면, 두개의 인터페이스를 구현하는 클래스에서 어떠한 기본 메소드를 사용해야 할지 정해야 한다. 
    public interface vehicle {

        default void print() {
            System.out.println("I am a vehicle!");
        }

    }


    public interface fourWheeler {

        default void print() {
            System.out.println("I am a four wheeler!");
        }

    }


    public class car implements vehicle, fourWheeler {

    }

    첫번째 방법으로는 기본 메소드를 재 정의 한다. 
    public class car implements vehicle, fourWheeler {
        
        public void print() {
            System.out.println(“I am a four wheel vehicle”);
        }

    }

    두번째 방법으로는 super 연산자를 사용하여 지정한다.
    public class car implements vehicle, fourWheeler {

        default void print() {
            vehicle.super.print();
        }

    }

    정적 기본 메소드
    Java 8 의 인터페이스는 정적 기본 메소드도 가능하다.
    public interface vehicle {

        default void print() {
            System.out.println("I am a vehicle!");
        }
            
        static void blowHorn() {
            System.out.println("Blowing horn!!!");
        }

    }



    Stream API
    Stream 은 Java 8 에서 새로 도입된 추상 레이어다. Stream 을 사용하면, SQL 과 비슷한 선언적 방식으로 데이터를 처리 할 수 있다. 

    Java 8은 두가지의 Stream 을 생성하는 메소드를 가지고 있다. 
    • stream - 순차 처리
    • parallelStream - 병렬 처리
    List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    List<String> filtered = strings.stream()
                                   .filter(string -> !string.isEmpty())
                                   .collect(Collectors.toList());

    forEach
    Stream 은 forEach 메소드를 제공하여 각 요소를 반복 한다. 아래 코드는 forEach 를 사용하여 10개의 난수를 출력하는 방법을 보여준다.
    Random random = new Random();
    random.ints()
          .limit(10)
          .forEach(System.out::println);

    Map
    map 은 각 요소를 결과에 맵핑하는데 사용한다. 아래 코드는 map 을 사용하여 고유한 정사각형을 출력한다.
    List<Integer> numbers = Arrays.asList(1,2,3,4,3,5,2,1,2,3,5,3);
    List<Integer> squaresList = numbers.stream()
                                       .map( i -> i * i )
                                       .distinct()
                                       .collect(Collectors.toList());

    Filter
    filter 는 기준에 맞지 않는 요소를 제거하는데 사용한다. 
    List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    int count = strings.stream()
                       .filter(string -> string.isEmpty())
                       .count();

    Limit
    limit 은 스트림의 크기를 줄이기 위해 사용한다.
    Random random = new Random();
    random.ints()
          .limit(10)
          .forEach(System.out::println);

    Sorted
    sorted 는 스트림을 정렬하는데 사용한다.
    Random random = new Random();
    random.ints()
          .limit(10)
          .sorted()
          .forEach(System.out::println);

    ParallelStream
    parallelStream 은 병렬처리를 위해 사용한다. 
    List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    long count = strings.parallelStream()
                        .filter(string -> string.isEmpty())
                        .count();

    Collect
    스트림의 처리 결과를 결합하는데 사용한다. 
    List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");

    List<String> filtered = strings.stream()
                                   .filter(string -> !string.isEmpty())
                                   .collect(Collectors.toList());
    System.out.println("Filtered List: " + filtered);

    String mergedString = strings.stream()
                                 .filter(string -> !string.isEmpty())
                                 .collect(Collectors.joining(", "));
    System.out.println("Merged String: " + mergedString);

    Statistics
    Java 8 에서는 스트림 처리가 완료될 때 모든 통계를 계산하기 위한 통계 처리기가 도입되었다. 
    List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

    IntSummaryStatistics stats = numbers.stream()
                                        .mapToInt((x) -> x)
                                        .summaryStatistics();

    System.out.println("Highest number in List : " + stats.getMax());
    System.out.println("Lowest number in List : " + stats.getMin());
    System.out.println("Sum of all numbers : " + stats.getSum());
    System.out.println("Average of all numbers : " + stats.getAverage());



    Date Time API
    Java 8 에서는 새로운 Date, Time API 가 도입되어 아래와 같은 기존의 Date, Time API 의 단점을 보완한다.
    • 쓰레드로 부터 안전하지 않음. - java.util.Date 는 쓰레드로 부터 안전하지 않아, 개발자가 동시성 문제를 해결해야 했다. 
    • 이상한 디자인 - java.util.Date 는 1900 년 부터 시작하고, 월은 1에서 시작하지만, 날짜는 0에서 시작하는 등 일관성이 없었다. 또한 날짜 조작에 대한 메소드가 적었다. 
    • 어려운 시간대 처리 - 시간대 문제를 해결하기 위해 개발자가 많은 노력을 기울여야 했다. 

    import java.time.LocalDate;
    import java.time.LocalTime;
    import java.time.LocalDateTime;
    import java.time.Month;

    public class Java8Test {

       public static void main(String args[]) {
          Java8Test java8test = new Java8Test();
          java8test.testLocalDateTime();
       }
            
       public void testLocalDateTime() {

          LocalDateTime currentTime = LocalDateTime.now();
          System.out.println("Current DateTime: " + currentTime);
                    
          LocalDate date1 = currentTime.toLocalDate();
          System.out.println("date1: " + date1);
                    
          Month month = currentTime.getMonth();
          int day = currentTime.getDayOfMonth();
          int seconds = currentTime.getSecond();
                    
          System.out.println("Month: " + month +"day: " + day +"seconds: " + seconds);
                    
          LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
          System.out.println("date2: " + date2);
                    
          LocalDate date3 = LocalDate.of(2019, Month.DECEMBER, 12);
          System.out.println("date3: " + date3);
                    
          LocalTime date4 = LocalTime.of(22, 15);
          System.out.println("date4: " + date4);
                    
          LocalTime date5 = LocalTime.parse("20:15:30");
          System.out.println("date5: " + date5);
       }
    }



    Optional
    optional 은 null 이 아닌 객체를 포함하는데 사용하는 컨테이너 객체다. 
    Guava 의 Optional 과 유사하다. 


    반응형
Designed by Tistory.