반응형

본 글은 책 자바의 정석을 ref 하여 요약한 것입니다.


https://komas.tistory.com/68

 

[JAVA]자바 익명 클래스와 람다식 정리

익명 클래스는 말 그대로 클래스의 이름이 없다는 말이다. 이름이 없으므로 생성자를 가질 수 없다. 익명 클래스를 정의하려면 상속을 받거나 인터페이스로 구현해야한다. 참조 변수에 넣어두

komas.tistory.com

 

https://komas.tistory.com/69

 

[JAVA] 자바 메소드 참조

메서드 참조란 말 그대로 다른 클래스의 메소드를 참조하여 사용한다입니다. 빌려쓴다고 이해하시면 편합니다. (호출이 아닌 구현부를 빌림) 코드로 설명하겠습니다. public class ProviderClass { public

komas.tistory.com

 

 

 

 


 

스트림

자바 8부터 추가된 함수적 스타일 처리

중간처리는 지연되고, 최종 처리가 시작되면 처리를 시작한다.

 

✔ 스트림의 종류

Stream, IntStream, LongStream, DoubleStream

 


 

✔ 스트림 만들기

List<Integer> list = Arrays.asList(1,2,5,3);
Stream<Integer> slist= list.stream();

long[] arr = {1,2,10,5,3,4,3};
LongStream sarr = Arrays.stream(arr);

 

컬렉션 프레임워크는 Stream<T>  로 변환된다.

mapToXXX()로 변환하면 IntStream, LongStream, DoubleStream로 변경할 수 있다.

 

기본형 배열은 type에 맞게  IntStream, LongStream, DoubleStream 로 변환된다.

객체 배열일 경우 Stream<T> 로 변환된다.

 

 

객체는 Stream<T>

기본형 배열은 IntStream, LongStream, DoubleStream

 

 


 

✔ 중간 처리 함수

매핑, 필터링, 정렬

 

 

skip(n)

개수만큼 건너뛴다.

 

 

limit(n)

개수만큼 제한한다.

 

 

peek(Consumer)

forEach와 비슷한 역할을 하는 중간 연산이라고 보면 된다.

보통 단순히 중간 조회를 위해 사용됨

 

 

distinct()

중복을 제거한다. equals() 값이 같으면 제거, IntStream, LongStream, DoubleStream 일 경우 값이 같으면 제거

 

 

filter(Predicate)

true인 값만 남기고 제거한다.

 

 

map(Function)

요소를 대체하는 새로운 요소로 구성된 스트림을 만든다. (보통 type변환, 일괄 연산 등)

 

map() -> (객체 -> 객체), (기본형 -> 기본형), 값 변환

mapToInt -> IntStream으로 변환

mapToLong -> LongStream으로 변환

mapToDouble -> LongStream으로 변환

mapToObj -> 객체로 변환

type 변환과 값 변경도 가능

 

List<Integer> list = Arrays.asList(1,2,5,3);
Stream<Integer> slist= list.stream();
IntStream is = slist.mapToInt(e->e);

long[] arr = {1,2,10,5,3,4,3};
LongStream sarr = Arrays.stream(arr);
Stream<Integer> bs = sarr.mapToObj(e -> (int) e);

 

flatMap()

스트림의 요소가 배열일때  flatten Stream을 만들 때 사용한다.

 

 

boxed()

IntStream, LongStream, DoubleStream  ---->   Stream<T>

 

 

sorted(Comparator)

정렬을 제공한다.

Comparable이 제공된 객체를 사용하거나, Comparator를 제공해주면 된다.

* IntStream, LongStream, DoubleStream 일 경우 인수를 제공하지 않으면 오름차순으로 정렬, 내림차순을 원할 경우 Comparator.reverseOrder()

 

* thenComparing() - 정렬 추가가 가능

* reversed() - 내림차순 가능

 

List<Student> students = Arrays.asList(
                new Student("Lee", 1),
                new Student("Lee", 2),
                new Student("Park",1),
                new Student("Park",2),
                new Student("Kim",2)
        );

       List<Student> sortedList= students.stream().sorted(
               Comparator.comparing(Student::getName)
               .thenComparing(Student::getNumber)
               .reversed()
               ).collect(Collectors.toList());

        System.out.println(sortedList);
        
//        [Student{name='Park', number=2}, Student{name='Park', number=1}, 
//        Student{name='Lee', number=2}, Student{name='Lee', number=1}, Student{name='Kim', number=2}]

 


 

✔ 최종 처리 함수

반복, 카운팅, 평균, 총합

최종 처리 함수의 반환 타입은 기본형이거나 OptionalXXX

 

 

forEach(Consumer)

요소를 하나하나씩 처리한다.

 

 

sum() - IntStream, LongStream, DoubleStream

반환 타입

타입에 맞는 기본형

 

 

count() - IntStream, LongStream, DoubleStream

반환 타입

long

 

 

max(), min() - IntStream, LongStream, DoubleStream

Stream<T> 일 경우 인수로 Comparator 필요

IntStream, LongStream, DoubleStream 일 경우 필요하지 않다.

반환 타입

Stream<T>일 경우 Optional<T>

IntStream, LongStream, DoubleStream 일 경우 OptionalXXX

 

 

average() - IntStream, LongStream, DoubleStream

반환 타입

OptionalDouble

 

 

findFirst()

반환 타입

Stream<T>일 경우 Optional<T>

IntStream, LongStream, DoubleStream 일 경우 OptionalXXX

 

 

reduce(identify, BinaryOperator)

identify는 요소가 없을 때 반환하는 값(Default)

BinaryOperator에 요소 하나하나씩 누적해가며 계산한다.

반환 타입

identify를 지정하면 기본형으로 반환

지정하지 않으면 OptionalXXX로 반환

 

 

allMatch(Predicate)

모든 요소가 일치하면 true 반환

anyMatch(Predicate)

하나의 요소라도 true라면 true 반환

noneMatch(Predicate)

모든 요소가 false라면 true 반환

 


 

✔ collect(Collector)

collect 함수는 내부에 수집기를 정의해줘야 한다.

보통 Collectors(수집기 구현체)에 구현된 메서드들을 활용한다.

 

Student[] students = {new Student("Lee",23), new Student("Park",26), new Student("Kim",26)};

List<Integer> ageList = Arrays.stream(students)
        .map(e-> e.age)
        .collect(Collectors.toList());
System.out.println("ageList " + ageList);

Set<Integer> ageSet = Arrays.stream(students)
        .map(e-> e.age)
        .collect(Collectors.toSet());
System.out.println("ageSet " + ageSet);

TreeSet<Integer> ageTreeSet = Arrays.stream(students)
        .map(e -> e.age)
        .collect(Collectors.toCollection(()-> new TreeSet<Integer>())); // TreeSet::new
System.out.println("ageTreeSet " + ageTreeSet.higher(23));

 

 

 

collect() 사용자 직접 정의

Collector(수집기) 인터페이스를 구현하기 위해선 대략 3가지의 요소가 필요하다.

 

supplier

 - 수집된 데이터를 담을 구현체 생성 (싱글 스레드는 하나, 멀티 스레드는 여러개가 생성)

accumalator

 - 생성된 객체에 원하는 요소 수집

combiner

 - 병렬 처리된 각 컨테이너 객체들을 결합 지정

 

List<Student> students = Arrays.asList(
        new Student("Lee", 1),
        new Student("Park",1),
        new Student("Kim",2),
        new Student("Cha",2)
);

List<Student> ls = students.stream().
        filter((s)-> s.getNumber() == 1).
        collect(ArrayList::new, List::add, List::addAll);

System.out.println(ls);
// [Student{name='Lee', number=1}, Student{name='Park', number=1}]

 

 

 

collect() 그룹핑

Collectors.groupingBy()

- 내부에서 key, Collector(수집기)를 지정한다.

 

Collectors.mapping(Function, Collector)

- 매핑한 후 Collector(수집기)를 사용한다.

 

List<Student> students = Arrays.asList(
        new Student("Lee", 1),
        new Student("Park",1),
        new Student("Kim",2),
        new Student("Cha",2)
);

Map<Integer, List<Student>> m1 = students.stream()
        .collect(Collectors.groupingBy(Student::getNumber)); // key
System.out.println(m1);
// {1=[Student{name='Lee', number=1}, Student{name='Park', number=1}], 2=[Student{name='Kim', number=2}, Student{name='Cha', number=2}]}


Map<Integer,List<String>> m2 = students.stream()
                .collect(Collectors.groupingBy(
                        Student::getNumber, // key
                        Collectors.mapping(Student::getName, Collectors.toList()))); // value
System.out.println(m2);
// {1=[Lee, Park], 2=[Kim, Cha]}


Map<Integer,List<String>> m3 = students.stream()
        .collect(Collectors.groupingBy(
                Student::getNumber, // key
                HashMap::new, // 구현체 지정 가능
                Collectors.mapping(Student::getName, Collectors.toList()))); // value
System.out.println(m3);
// {1=[Lee, Park], 2=[Kim, Cha]}

 

 

 

partioningBy(Predicate, Collector)

true인 것만 적용하여 분리

반환 타입은 <boolean>

 

 

Collectors 수집기 함수

averagingDouble() 

counting()

maxBy(Comparator)

minBy(Comparator)

summingInt, Long, Double()

 

reducing(identity, BinaryOperator

joining(구분자) - 문자열 결합

 

 

 

collect 개략도

collect( 수집기 )

collect( Collectors.groupingBy ( 키, 수집기 ) )

collect( Collectors.groupingBy ( 키, Collectors.mapping ( 매핑, 수집기 ) )

 

 

 


 

반응형
반응형

 

익명 클래스는 말 그대로 클래스의 이름이 없다.

익명 클래스는 설계도가 1회성이라는 말이다.

 

 

이름이 없으므로 생성자를 구현할 수 없다.

익명 클래스를 정의하려면 상속을 받거나 인터페이스로 구현해야한다.

 

 

참조 변수에 넣어두고 재사용할 수 있다.

상위 클래스의 생성자 지정, 오버 라이딩은 가능하다.

 

 

 


상속을 받은 익명 클래스

 

상속받아서 사용할 Outer 클래스

 

Outer 클래스를 익명 클래스로 활용

 

참조변수 o는 Outer를 상속받아서 1회성 구현부를 작성하고 인스턴스를 생성한 것과 같다.

 


인터페이스로 구현한 익명 클래스

 

 

추상메서드 2개를 갖는 인터페이스를 정의한 후

 

 

상속과 마찬가지로 인터페이스를 익명 클래스로 구현해서 사용할 수 있다.

 

참조변수 ti는 TestInterface의 추상메서드들을 구현하고 인스턴스를 생성한 것과 같다.

 

 


람다식(함수형 인터페이스)

 

위에서 본 익명클래스들의 생성을 코드 구현을 더 짧게 하고자 하는 것이 람다식이다.

 

마찬가지로 람다식은 단순히 함수를 구현하는 것 같지만 사실 객체의 생성이다.

인터페이스를 구현받아서 추상메서드를 작성하고 익명 객체를 생성한 것이다.

 

 

익명 클래스의 구현을 람다식으로 바꿔줄 수 있다.

(매개변수) -> 메서드 구현부

 

대신, 조건으로 인터페이스는 하나의 추상 메서드만을 갖고 있어야 한다.

하나의 추상 메서드만을 갖고 있는 인터페이스를 함수형 인터페이스라 한다.

 

람다식은 함수형 인터페이스를 이용해서 익명 객체로 구현하는 과정을 짧게 만든 것이다.

함수형 인터페이스가 갖고 있는 하나의 추상메서드의 1회성의 구현부를 만든 후 객체를 생성한 것

 

 


자바에는 이러한 함수형 인터페이스를 미리 만들어 둔 API가 있다.

https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/function/package-summary.html

 

java.util.function (Java SE 15 & JDK 15)

Functional interfaces provide target types for lambda expressions and method references. Each functional interface has a single abstract method, called the functional method for that functional interface, to which the lambda expression's parameter and retu

docs.oracle.com

 

 

 

 


 

반응형

+ Recent posts