반응형

자바 8에서 추가한 기본(default) 메소드로 인한 API 변화

Iterable의 기본 메소드

  • forEach()
  • spliterator()

 

Collection의 기본 메소드

  • stream() / parallelStream()
  • removeIf(Predicate)
  • spliterator()

 

Comparator의 기본 메소드 및 스태틱 메소드

  • reversed()
  • thenComparing()
  • static reverseOrder() / naturalOrder()
  • static nullsFirst() / nullsLast()
  • static comparing()

 

인터페이스 변경사항 활용 예제

public class Main {

    /**
     * 맵 key name의 값을 대문자로 변환한다.
     * @param map
     * @return
     */
    public static String getMapNameToUpperCase(Map<String, Object>  map){
        return map.get("name").toString().toUpperCase();
    }

    /**
     * 맵 생성 시간을 비교한다. 큰 값이 우선 출력
     * @param map1
     * @param map2
     * @return
     */
    public static int mapCreateTimeCompare(Map map1, Map map2) {
        return Integer.parseInt(map2.get("createTime").toString())-Integer.parseInt(map1.get("createTime").toString());
    }

    public static void main(String[] args){
      
        /* forEach(), spliterator() */
        List<Map<String, Object>> name = new ArrayList<>();
        name.add(Map.of("name", "history", "createTime", (int)System.currentTimeMillis()));
        name.add(Map.of("name", "devdev", "createTime", (int)System.currentTimeMillis()+1));
        name.add(Map.of("name", "appleapple", "createTime", (int)System.currentTimeMillis()+2));
        name.add(Map.of("name", "apple", "createTime", (int)System.currentTimeMillis()+3));
        name.add(Map.of("name", "HooHoo", "createTime", (int)System.currentTimeMillis()+4));
        name.add(Map.of("name", "HooHoo", "createTime", (int)System.currentTimeMillis()+5));
        name.add(Map.of("name", "HooHoo", "createTime", (int)System.currentTimeMillis()+6));
        name.add(Map.of("name", "barbar", "createTime", (int)System.currentTimeMillis()+7));
        name.forEach(System.out::println);
        System.out.println("###############");
        //쪼갤 수 있는 기능을 가진 Iterator. 기본적으로는 Iterator와 같다
        Spliterator<Map<String, Object>> originSpliterator = name.spliterator();
        Spliterator<Map<String, Object>> spliterator = name.spliterator();
        //쪼개는 기능. 원래 spliterator에서 가지고 있던 엘리먼트를 반으로 쪼개서 기존 spliterator에 넣어주고 나머지 반의 엘리먼트는 spliterator1에 넣어준다. 엘리먼트의 순서가 중요하지 않을 때 사용(병렬 처리).
        Spliterator<Map<String, Object>> spliterator1 = spliterator.trySplit();
        //hasNext() 대신 tryAdvance 사용. 다음 것이 있으면 true, 없으면 false 반환
        System.out.println("===originSpliterator(spliterator 반으로 나누기 전의 원본)===");
        while (originSpliterator.tryAdvance(System.out::println));
        System.out.println("###############");
        System.out.println("===spliterator===");
        while (spliterator.tryAdvance(System.out::println));
        System.out.println("===spliterator1===");
        while (spliterator1.tryAdvance(System.out::println));
        System.out.println("###############");
        /* //forEach(), spliterator() */

        /* stream() */
        long count = name.stream().map(Main::getMapNameToUpperCase)
                                .filter(s -> s.startsWith("H"))
                                .count();
        System.out.println(count);
        System.out.println("###############");
        /* //stream() */
        /* removeIf() */
        //조건을 만족하는 엘리먼트 삭제처리
        name.removeIf((s) -> s.get("name").toString().startsWith("d"));
        name.forEach(System.out::println);
        System.out.println("###############");
        /* //removeIf() */

        /* reversed(), thenComparing() */
        //문자순으로 정렬
        Comparator<Map<String, Object>> compareToIgnoreCase = (map1, map2) -> map1.get("name").toString().compareToIgnoreCase(map2.get("name").toString());
        name.sort(compareToIgnoreCase);
        System.out.println("===compareToIgnoreCase===");
        name.forEach(System.out::println);

        //문자역순으로 정렬
        name.sort(compareToIgnoreCase.reversed());
        System.out.println("===compareToIgnoreCase.reversed()===");
        name.forEach(System.out::println);

        //문자역순으로 정렬 후 추가적인 비교가 더 필요한 경우에 사용. 정렬 결과 중 같은 값에 대해서 정렬 수행
        //문자역순으로 정렬 후, 같은 값이 있다면 나중에 생성된 것이 우선적으로 표시되도록 정렬
        name.sort(compareToIgnoreCase.reversed().thenComparing(Main::mapCreateTimeCompare));
        System.out.println("===compareToIgnoreCase.reversed().thenComparingInt(Main::mapCreateTimeCompare)===");
        name.forEach(System.out::println);
        /* //reversed(), thenComparing() */
    }
}

 

자바8 인터페이스 구조 변화

자바8 이전의 인터페이스 구조
  • 인터페이스에서 기본적으로 메소드를 제공할 수 없던 자바8 이전의 버전에서는 인터페이스에 선언된 추상메소드를 모두 구현해야 했기 때문에 필요한 메소드만 사용할 수 있도록 하기 위해서 별도로 추상 클래스를 중간에 두어 메소드의 기본 동작에 대해 정의하고 사용자가 필요하다면 원하는 추상 메소드를 재정의하여 사용할 수 있도록 처리하였다.
  • 다만 이 방식은 클래스의 상속이 인터페이스에 의존되는 문제가 있다. 따라서 인터페이스를 사용하면 다른 원하는 클래스를 상속 받지 못하는 현상이 일어난다.

 

자바8 변경된 인터페이스 구조
  • 자바8의 등장으로 라이브러리 구조가 변경되었다. 인터페이스의 default 키워드를 통해서 인터페이스에서 메소드의 기본 동작을 정의할 수 있기 때문에 별도의 추상클래스가 없어도 사용자는 필요한 추상메소드만 구현해서 사용하거나 기존에 정의된 인터페이스의 default 메소드 재정의를 통해서 원하는 동작을 수행할 수 있도록 할 수 있다.
  • 자바8 이전 방식에서 발생했던 인터페이스에 의존적인 문제에서 벗어나 원하는 클래스의 상속이 가능해졌다.(비침투성)

[참고자료]

더 자바, Java 8, 백기선

Interface Spliterator<T>

Interface Iterable<T>

Interface Collection<E>

Interface Comparator<T>

반응형

+ Recent posts