YOUNGJIN

자바의 정석 14장 (람다와 스트림) 본문

Study/Java

자바의 정석 14장 (람다와 스트림)

Youngjin Noh 2023. 1. 22. 21:30

람다식은 사실 익명 클래스의 객체이다.

 

함수형 인터페이스: 오직 하나의 추상 메서드만 정의되 있는 인터페이스

람다함수가 포함된 익명 클래스는 함수형 인터페이스의 구현체여야 한다.

 

람다식 사용 전

Collections.sort(list,new Comparator<String>(){
    public int compare(String s1,String s2){
    	return s2.compareTo(s1);
    }
});

람다식 사용 후

Collections.sort(list,(s1,s2)->s2.compareTo(s1));

여기서 Comparator는 당연히 함수형 인터페이스이다.

 

외부변수를 참조하는 람다식

@FunctionalInterface
interface MyFunction{
    void myMethod();
}

class Outer{
    int val=10;
    
    class Inner{
        int val=20;
        void method(int i){ //final int i
            int val=30; //final int val=30;
            i=10; //에러. 상수의 값을 변경할 수 없음.
            MyFunction f=()->{
            	System.out.println("i:"+i); //변경불가능
                System.out.println("val:"+val); //변경불가능
                System.out.println("this.val:"+ ++this.val); //변경가능
                System.out.println("Outer.this.val"+ ++Outer.this.val); //변경가능
            };
            f.myMethod();
        }
    }
}

 

 

미리 정의되있는 함수형 인터페이스

함수형 인터페이스 메서드
Runnable void run()
Supplier<T> T get()
Consumer<T> void accept(T t)
Function<T,R> R apply(T t)
Predicate<T> boolean test(T t)
UnaryOperator<T> T apply(T t)
BinaryOperator<T> T apply(T t,T t)

 

Function의 합성

Function<String,Integer> f=(s)->Integer.parseInt(s,16);
Function<Integer,String> g=(i)->Integer.toBinaryString(i);
Function<String,String> h=f.andThen(g);

 

Predicate의 결합

Predicate<Integer> p=i->i<100;
Predicate<Integer> q=i->i<200;
Predicate<Integer> r=i->i%2==0;
Predicate<Integer> notP=p.negate();
Predicate<Integer> all=notP.and(q).or(r);
System.out.println(all.test(150)); //true

 

메서드 참조

람다식이 하나의 메서드만 호출하는 경우에는 메서드 참조로 람다식을 간략히 할 수 있다.

종류 람다 메서드 참조
static메서드 참조 (...x)->ClassName.method(...x) ClassName::method
인스턴드메서드 참조 (obj, ...x)->obj.method(...x) ClassName::method
특정 객체 인스턴스메서드 참조 (...x)->obj.method(...x) obj::method(x)

 

생성자의 메서드 참조

Supplier<Myclass> s=MyClass::new; //()->new MyClass();
Function<Integer,int[]> f=int[]::new; //x->new int[x];

 

 

스트림 만들기

//컬렉션
List<Integer> list=Arrays.asList(1,2,3,4,5);
Stream<Integer> stream1=list.stream();

//가변인자
Stream<Integer> stream2=Stream.of(1,2,3);

//배열
int[] arr={1,2,3};
IntStream stream3=Arrays.stream(arr);
Stream<Integer> stream4=stream3.boxed();

//특정 범위의 정수
IntStream stream5=IntStream.range(1,5);

 

스트림의 중간연산

스트림의 최종연산

 

Comparator.comparing과 Comparator.thenComparing

myStream.sorted(Comparator.comparing(Student::getBan)
	.thenComparing(Comparator.naturalOrder())
    	.forEach(System.out::println);

 

Optional

Optional<String> opt1=Optional.of("abc");
Optional<String> opt2=Optional.ofNullable(null); //null일 가능성이 있을 때는 ofNullable 이용

String str1=opt1.get(); //null이면 예외발생
String str2=opt2.orElse(""); //null이면 ""가져옴

Optional.ofNullable("abc").ifPresent(System.out::println);

 

분할과 그룹화

//partitioningBy
Map<Boolean, List<Student>> stuBySex=stuStream
	.collect(partitioningBy(Student::isMale));
List<Student> maleStudent=stuBySex.get(true);
LIst<Student> femaleStudent=stuBySex.get(false);

//groupingBy
Map<Integer,List<Student>> stuByBan=stuStream
	.collect(groupingBy(Student::getBan));

 

스트림의 변환

 

Comments