📖
Kyu9's Repo
  • Library of mameil
  • 이슈 경험
    • 20230220_트랜잭션
    • 20230306_캐싱이슈
    • 20230722_테스트코드에서 @Transactional
    • 20230807_deadlock
  • 인턴 스터디
    • Gradle
    • Stream, Optional, 람다식
    • JVM의 메모리 구조, Garbage Collector
    • RESTful API
    • Microservice Architecture
    • HTTP
    • 웹서버란 무엇인가
    • Git Branch
    • TDD
    • Redis을 이용한 캐시
    • Thymeleaf
    • 정리가 필요한 자료들
    • SpringBoot Management
    • 테스크 코드 분할
  • 동아리 스터디
    • 기본 SQL 공부
      • SQL의 기본 개념
      • SELECT 문장을 이용하여 원하는 데이터 출력하기
        • 집합 연산자 사용하기
        • where절에 비교 연산자를 사용해보기
        • SELECT_EX
        • 산술 연산자 사용해보기
      • 단일 행 함수 사용
        • lower/upper 함수 사용하기
        • length함수 사용하기
        • concat함수 사용
        • substr/mid/substring 함수 사용
        • instr함수 사용하기
        • lpad/rpad 함수 사용하기
        • trim/ltrim/rtrim 함수 사용하기
        • replace 함수 사용하기
        • round 함수 사용하기
        • truncate 함수 사용하기
        • mod함수 사용하기
        • ceil함수 사용하기
        • floor함수 사용하기
        • power 함수 사용하기
        • Date fn(날짜 함수)
        • 형 변환 함수
        • 일반함수란
    • a-ha 실습
    • 혼자서 만들어본 게시판
    • AWS 강의
  • 학교 나머지 공부 자료
    • 웹프레임워크(Spring)
      • Spring이란?
      • Webframework1-1
      • Webframework1-2
      • SpringBoot의 특징
      • SpringBoot 생성 방법
      • Spring Data JPA
      • SpringBoot Security
      • SpringBoot HATEOAS
  • 공부 자료들
  • WS 온라인 자바 스터디
    • Week1(JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.)
    • Week2(자바 데이터 타입, 변수 그리고 배열)
    • Week3(연산자)
    • Week4(제어문)
    • Week5(클래스)
    • Week6(상속)
    • Week7(패키지)
    • Week8(인터페이스)
    • Week9(예외처리)
    • Week10(멀티쓰레드 프로그래밍)
    • Week11(Enum)
    • Week12(Annotation)
    • Week13(I/O)
    • Week14(Generic)
    • Week15(람다식)
  • 백준문제
    • 입출력과 사칙연산
      • We love kriii(10718)
      • 고양이(10171)
      • 개(10172)
      • A+B(1000)
      • A-B(1001)
      • AxB(10998)
      • A/B(1008)
      • 사칙연산(10869)
      • 나머지(10430)
      • 곱셈(2588)
    • for문
      • 구구단(2739)
      • A+B - 3(10950)
      • 합(8393)
      • 빠른 A+B(15552)
      • N 찍기(2741)
      • 기찍 N(2742)
      • A+B - 7(11021)
      • A+B - 8(11022)
      • 별 찍기 - 1(2438)
      • 별 찍기 - 2(2439)
      • X보다 작은 수(10871)
    • if문
      • 두 수 비교하기(1330)
      • 시험 성적(9498)
      • 윤년(2753)
      • 사분면 고르기(14681)
      • 알람 시계(2884)
      • 오븐 시계(2525)
      • 주사위 세개(2480)
      • 영수증(25304)
    • While문
      • A+B - 5(10952)
      • A+B - 4(10951)
      • 더하기 사이클(1110)
    • 1차원 배열
      • 최소, 최대(10818)
      • 최댓값(2562)
      • 숫자의 개수(2577)
      • 나머지(3052)
      • 평균(1546)
      • OX퀴즈(8958)
      • 평균은 넘겠지(4344)
    • 함수
      • 정수N개의 합(15596)
      • 셀프 넘버(4673)
      • 한수(1065)
    • 문자열
      • 아스키코드(11654)
      • 숫자의 합(11720)
      • 알파벳 찾기(10809)
      • 문자열 반복(2675)
      • 단어 공부(1157)
      • 단어의 개수(1152)
      • 상수(2908)
      • 다이얼(5622)
      • 크로아티아 알파벳(2941)
      • 그룹 단어 체커(1316)
    • 기본수학-1
      • 손익분기점(1712)
      • 벌집(2292)
      • 분수찾기(1193)
      • 달팽이는 올라가고 싶다(2869)
      • ACM 호텔(10250)
      • 부녀회장이 될테야(2775)
      • 설탕 배달(2839)
      • 큰 수 A+B(10757)
      • Fly me to the Alpha Centauri(1011)
    • 기본수학-2
      • 소수 찾기(1978)
      • 소수(2581)
      • 소인수분해(11653)
      • 소수 구하기(1929)
      • 베르트와 공존(4948)
    • 재귀
      • 하노이 탑 이동 순서(11729)
      • 피보나치 수 5(10870)
      • 별 찍기(2447)
    • 브루트 포스
      • 블랙잭(2798)
      • 분해합(2231)
      • 덩치(7568)
      • 체스판 다시 칠하기(1018)
      • 영화감독 슘(1436)
    • 집합과 맵
      • 숫자 카드(10815)
      • 문자열 집합(14425)
      • 숫자 카드2(10816)
      • 듣보잡(1764)
      • 대칭 차집합(1269)
      • 서로 다른 부분 문자열 갯수(11478)
    • 정렬
      • 수 정렬하기(2750)
      • 수 정렬하기 2(2751)
      • 수 정렬하기 3(10989)
      • 통계학(2108)
      • 소트인사이드(1427)
      • 좌표 정렬하기(11650)
      • 좌표 정렬하기2(11651)
      • 단어 정렬(1181)
      • 나이순 정렬(10814)
      • 커트라인(25305)
      • 좌표압축(18870)
    • 백트래킹
      • N과 M - 1(15649)
      • N과 M - 2(15650)
      • N과 M - 3(15651)
      • N과 M - 4(15652)
      • N-Queen(9663)
      • 스도쿠(2580)
      • 연산자 끼워넣기(14888)
      • 스타트와 링크(14889)
    • 이분 탐색
      • 수 찾기(1920)
    • 동적계획법
      • 피보나치 함수(1003)
      • 신나는 함수 실행(9184)
      • 01타일(1904)
      • 파도반 수열(9461)
      • RGB거리(1149)
      • 정수 삼각형(1932)
      • 계단 오르기(2579)
      • 1로 만들기(1463)
      • 쉬운 계단 수(10844)
      • 포도주 시식(2156)
      • 가장 긴 증가하는 부분 수열(11053)
      • 가장 긴 바이토닉 부분 수열(11504)
      • 전깃줄(2565)
      • LCS(9251)
      • 연속합(1912)
      • 평범한 배낭(12865)
      • 더하기(9095)
    • DFS와 BFS
      • 미로탐색(2178)
      • 바이러스(2606)
      • DFS와 BFS(1260)
      • 단지번호붙이기(2667)
      • 전쟁 - 전투(1303)
      • 숨바꼭질(1697)
      • 데스 나이트(16948)
      • 나이트의 이동(7562)
      • 녹색 옷 입은 애가 젤다지?(4485)
      • 음식물 피하기(1743)
      • A->B (16953)
      • 숨바꼭질 3(13549)
      • 숨바꼭질 2(12851)
    • 구현
      • 치즈(2636)
  • 프로그래머스 문제
    • SQL
      • Animal Table - Oracle
      • Animal Table - MySQL
      • Animal Table2 - Oracle
      • Animal Table 3,4 - Oracle
    • Lv1
      • 두 개 뽑아서 더하기
      • 제일 작은 수 제거하기
      • 문자열 내 p와 y의 개수
      • 예산
      • 자릿수 더하기
      • 두 정수 사이의 합
      • 같은 숫자는 싫어
      • 가운데 글자 가져오기
      • 수박수박수박수박수박수?
      • 나누어 떨어지는 숫자 배열
      • 2016년
      • 폰캣몬
      • 서울에서 김서방 찾기
      • 문자열을 정수로 바꾸기
      • 소수 만들기
      • 문자열 다루기 기본
      • 소수 찾기(에라토스테네스의 체)
      • 숫자 문자열과 영단어
      • 이상한 문자 만들기
      • 없는 숫자 더하기
      • 문자열 내림차순으로 배치하기
      • 문자열 내 마음대로 정렬하기
      • 약수의 개수와 덧셈
      • 콜라츠 추측
      • 자연수 뒤집어 배열로 만들기
      • 신규 아이디 추천
      • 비밀지도
      • 크레인 인형뽑기 게임
      • 실패율
      • 로또의 최고 순위와 최저 순위
      • 키패드 누르기
      • 정수 내림차순으로 배치하기
    • Lv2
      • 행렬의 곱셈
      • 영어 끝말잇기
      • 영어 끝말잇기
      • N개의 최소 공배수
      • 피보나치 수
      • 124 나라의 숫자
      • 짝지어 제거하기
      • 프린터
      • 다음 큰 숫자
      • 최댓값과 최솟값
      • 최소값 만들기
      • 숫자의 표현
      • JadenCase 문자열 만들기
      • 오픈채팅방
      • 영어 끝말잇기
      • 멀쩡한 사각형
      • 올바른 괄호
      • 위장
      • 기능개발
      • 더 맵게
      • 스킬트리
    • 완전탐색
      • 모의고사(Lv1)
      • 카펫(Lv2)
      • 소수 찾기(Lv2)
    • 정렬(Sorting)
      • K번째 수(Lv1)
      • 가장 큰 수(Lv2)
      • H-Index(Lv2)
    • 해시(Hash)
      • 완주하지 못한 선수(Lv1)
      • 전화번호 목록(Lv2)
    • 탐욕법(Greedy)
      • 체육복(Lv1)
      • 큰 수 만들기(Lv2)
      • 구명보트(Lv2)
    • 동적계획법(DP)
      • 정수 삼각형(Lv3)
    • 깊이/너비 우선 탐색(DFS/BFS)
      • 타겟 넘버(Lv2)
      • 네트워크(Lv3)
      • 단어 변환(Lv3)
  • 스프링부트 책
    • Day 1
    • Day 2
    • Day 3
    • Day 4
    • Day 5
    • Day 6
    • Day 7
    • Day 8
    • Day 9
    • Day 10
    • Day 11
    • Day 12
    • Day 13
    • Day 14
    • Day 15
    • Day 16
    • Day 17
  • JPA 책
    • 프로젝트 세팅 및 기본설정
    • 영속성 관리 개념
    • 엔티티 매핑
      • 실습 예제
    • 연관관계 매핑 기초
      • 실습 예제
    • 다양한 연관관계 매핑
      • 다대일, 일대다 관계
      • 일대일, 다대다 관계
      • 실습 예제
    • 고급 매핑
      • 상속 관계 매핑
      • @MappedSuperclass
      • 복합 키와 식별 관계 매핑
      • 조인 테이블
    • 프록시와 연관관계 관리
      • 프록시
      • 즉시 로딩과 지연 로딩
      • 영속성 전이, 고아 객체
    • 값 타입
      • 임베디드 타입
      • 값 타입과 불변 객체
      • 값 타입의 비교, 컬렉션
    • 객체지향 쿼리 언어
      • JPQL part1
      • JPQL part2
      • JPQL part3
      • QueryDSL
      • NativeSQL
      • 객체지향 쿼리 심화
    • 응용 애플리케이션
      • 엔티티 설정
    • 스프링 데이터 JPA
      • 공통 인터페이스
  • Kotlin In Action
    • 코틀린의 특징
    • 코틀린의 기초
    • 함수 정의와 호출
    • 클래스, 객체, 인터페이스
    • 람다 방식
    • 코틀린 타입 시스템
    • 연산자 오버로딩과 기타 관례
    • 고차함수
    • 제네릭스
    • 애노테이션과 리플렉션
    • 코루틴
  • Oracle
    • Oracle 기본
    • Oracle 심화
  • SQL_연습
    • Revising the Select Query
    • Basic Select
    • Advanced Select
    • Basic Select 2
  • SQL 첫걸음(책)
    • Day 1
    • Day 2
    • Day 3
    • Day 4
    • Day 5
    • Day 6
    • Day 7
    • Day 8
    • Day 9
    • Day 10
    • Day 11
    • Day 12
    • Day 13
    • Day 14
    • Day 15
    • Day 16
    • Day 17
    • Day 18
    • Day 19
    • Day 20
    • Day 21
    • Day 22
    • Day 23
    • Day 24
    • Day 25
    • Day 26
    • Day 27
    • Day 28
    • Day 29
    • Day 30
  • 더 자바 코드를 조작하는 다양한 방법
    • JVM 이해하기
    • 바이트코드 조작
    • 리플렉션
    • 다이나믹 프록시
    • 애노테이션 프로세서
  • 더 자바, 애플리케이션을 테스트하는 다양한 방법
    • JUnit5
    • Mockito
    • 도커와 테스트
    • 성능, 운영이슈, 아키텍처 테스트
  • 이펙티브 자바
    • item1 - 생성자 대신 정적 팩토리 메소드를 고려하라
    • item2 - 생성자에 매개변수가 많다면 빌더를 고려하라
    • item3 - 생성자나 열거타입으로 싱글턴임을 보증하라
    • item4 - 인스턴스화를 막기 위해선 private 생성자를 사용하라
    • item5 - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
    • item6 - 불필요한 객체 생성을 피하라
    • item7 - 다 쓴 객체 참조를 해제하라
    • item8 - finalizer와 cleaner 사용을 피하라
    • item9 - try-finally 보다 try-with-resources을 사용하라
    • item10 - equals는 일반 규약을 지켜 재정의하라
    • item11 - equals을 재정의하려면 hashCode도 재정의하라
    • item12 - toString을 항상 재정의하라
    • item13 - clone 재정의는 주의해서 진행하라
    • item14 - Comparable을 구현할지 고민하라
  • Elastic Search
    • 강의 Summary
    • Elastic Summary 개념 정리
    • Elastic Summary 적용 정리
  • 토비의 스프링 강의
    • 스프링부트 살펴보기
    • 독립 실행형 서블릿 애플리케이션
  • k8s
    • minikube 설치
    • jenkins 추가
  • Article
    • Choosing the Right MessageBroker
Powered by GitBook
On this page
  • 람다 식의 문법
  • 컬렉션 함수형 메소드
  • 컬렉션 연산의 지연 계산
  • 자바 함수형 인터페이스 활용
  • 수신 객체 지정 람다

Was this helpful?

  1. Kotlin In Action

람다 방식

람다라는 의미는 기본적으로 다른 함수에 넘길 수 있는 작은 코드 조각을 의미한다

람다는 약간 논리?를 코드로 표현하기 위해 일련의 동작을 변수에 저장하거나 다른 함수에 넘겨야 하는 경우가 자주 있다 그래서 원래는 내부에서 익명클래스을 사용해서 코드를 함수에 넘기거나 변수에 담거나 이러한 과정을 거쳤었다 근데 함수형 프로그래밍에서는 함수를 값처럼 다루는 접근 방법을 사용해서 귀찮은 단계를 모두 해결해버렸다 클래스를 선언하고, 그 클래스의 인스턴스를 함수에 넘기는 대신 함수형 언어에서는 함수를 직접 다른 함수에 전달할 수 있다 람다를 사용하면 간결하게 함수를 선언하지 않고, 코드블록을 함수의 인자로 전달하는 것이 가능하다

람다 식의 문법

람다는 값처럼 여기저기 전달할 수 있는 동작의 모음이다. 람다를 따로 선언해서 변수에 저장하는 것도 가능하긴 하지만 일단은 함수에 인자로 넘기면서 바로 람다를 정의하는 경우가 대부분이다 람다의 구조는 이러하다 => {x: Int, y: Int -> x+y} 화살표를 기준으로 파라미터부분과 람다부분으로 나뉘게 된다 람다 식은 변수에 저장하는 것이 이런식으로 가능하다

val sum = {x: Int, y: Int -> x+y}
println(sum)

이렇게 람다를 변수에 직접 집어넣어서 사용하는 것이 아주 효율적이긴 하다 자바에서는 식을 만들고 그 식을 적용한 변수에 넣어주고 이렇게 2단계를 거쳐서 해야할 일을 이제는 단 한줄로 불필요한 단계들을 없앴다 그리고 람다를 만들고 바로 호출하는 것보다 람다 본문을 직접 실행하는 방법이 있다. 즉, 코드의 일부분을 블록으로 둘러싸서 실행할 필요가 있을 때는 run 이라는 키워드를 사용한다 run은 인자로 받은 람다를 실행해주는 라이브러리 함수이다 실행 시점에 코틀린 람다 호출에는 아무런 비용이들지 않는것도 특징이다 그래서 결과적으로 어떻게 사용하느냐, 방식은 간단하다 - 예를 들어서 콜렉션에서 최대값을 구하는 maxBy 라는 함수로 봐보자 람다로 어떤 값을 인자로 넘기는 케이스 people.maxBy({p: Person -> p.age}) 만약 어떤 함수의 파라미터가 하나인 경우에는 이렇게 중괄호를 빼서 사용한 케이스 people.maxBy() {p: Person -> p.age} 아니면 그냥 괄호는 없애도 가능한 케이스 people.maxBy {p: Person -> p.age} 사실 여기서 굳이 파라미터를 선언적으로 명시해줄 필요는 없다 people.maxBy {p -> p.age} 요렇게 파라미터의 타입을 생략해서 컴파일러가 알아서 추론하도록 하는 것도 가능하다 -> 뭐 당연하게 추론가능한 경우에는 이렇게 할 수 있다는 점은 상식적으로 이해할 수 있다 그리고 파라미터 중 일부의 타입은 저장하고 나머지 파라미터 타입을 지정하지 않고 이름만 남겨두는 것도 가능하다 파라미터 중 일부의 타입은 지정하고 나머지는 알아서 하도록 이름만 선언한 것도 가능하다는 점 그리고 람다의 파라미터 이름을 람다의 디폴트 이름인 it로 바꿔서 더욱 간단하게 할 수 있는데 요놈의 조건은 이하와 같다 우선 람다의 파라미터가 하나뿐이고, 그 타입을 컴파일러가 추론할 수 있는 경우에는 바로 it를 사용할 수 있다 사용방법은 이렇다 people.maxBy {it.age} 여기서 it란 자동으로 생성한 파라미터의 이름이다 근데 정말 간단하게 처리해주지만 값이 중첩되고 그러면 it가 어떤 파라미터를 의미하는지에 대한 애매모호함이 생길 수 있다고 생각하기 때문에 조심해야한다

자바에서 무명 클래스를 사용할때 메소드의 로컬변수를 내부 클래스 안에서 사용할 수 있었다. 람다에서도 같은 방식이 가능하다 즉, 람다를 함수 안에서 정의하면, 함수의 파라미터 뿐만아니라 람다 정의 앞에 선언된 로컬변수까지 람다에서 사용하는 것이 가능하다 자바에서는 람다내부에서만 있는 변수만 사용가능했었지만 코틀린에서는 람다 밖에서 선언한 바깥 변수를 변경하거나 접근하는 것이 가능하다 반대로 람다 내부에서 선언하고 사용한 변수는 기본적으로 변수의 생명주기가 함수가 종료될 때이다 근데 만약 내부에 있는 함수를 밖에서도 사용하고 싶다면 변수를 포획함을 통해서 변수의 생명주기를 변경하는 것이 가능하다 기본적으로 파이널인 변수를 포획한 경우에는 람다 코드를 변수 값과 함꼐 저장한다 파이널이 아닌 경우에는 변수를 특별한 래퍼로 감싸서 래퍼를 통해서 사용한다

멤버를 참조하는 방법은 자바에서의 메소드 레퍼런스와 같은 방식인 :: 을 통해서 참조한다 ::을 사용하는 식을 멤버 참조라고 부르는데, 멤버 참조는 프로퍼티나 메소드를 단 하나만 호출하는 함수 값을 만들어준다 val myAge = Person::age 요렇게 생긴 것인데 val myAge = {p: Person -> p.age} 이 람다 방식을 줄이는 방식이라고 볼 수 있다 추가로 굳이 클래스::멤버 이렇게 참조하지 않고 클래스 이름을 생략하고 ::으로 참조를 바로 시작하는 것도 가능하다 람다가 인자가 다양한 다른 함수에게 작업을 위임하는 경우 람다를 정의하지 않고 직접 위임함수에 대한 참조를 제공하면 편리하다

//이 람다를 통해서 sendEmail 함수에게 작업을 위임
val action = { p: Person, msg: String -> sendEmail(p, msg)}
//람다 대신 멤버 참조를 사용할 수 있다
val nextAction = ::sendEmail

또한 생성자 참조에서 이렇게 ::을 사용해서 진행하는데, 이렇게 사용하면 클래스 생성 작업을 연기하거나 저장하는 것이 가능하다

컬렉션 함수형 메소드

함수형 프로그래밍을 사용하게 되면 컬렉션을 사용하는데 있어서 아주 편리하다 그 중에서도 필수적인 함수 filter, map에 대해서 간단하게 보자 우선 filter함수는 컬렉션을 일일이 돌면서 주어진 람다에 각 원소를 넘겨서 람다의 식을 확인하는 그러한 함수이다 그래서 filter를 통해서 컬렉션 내부에 존재하는 원소들 중에서 원하지 않은, 즉 람다식에 부합하지 않는 원소는 제거된다 그리고 map 함수는 원소를 조작하는 것이 가능하다, 즉 주어진 람다를 컬렉션에 있는 각각의 원소에 적용해서 새로운 컬렉션을 만드는 것이다 사실근데 람다를 인자로 받는 함수에 람다를 넘기면 간단해 보일 수도 있지만 실제로는 정말 쉽지 않은 계산식이 될 수동 있기 떄문에 요부분은 항상 알아서 눈치것 사용하는 것이다 이외에도 map 의 경우에는 키와 값을 처리하는 함수가 따로 존재한다 filterKey, mapKey는 키를 걸러내거나 변환해주고, filterValues, mapValues는 값을 걸러내거나 변환해준다

이외에도 all, any, count, find 들이 잇다 all이나 any는 컬렉션에 대해 자주 수행하는 연산으로 컬렉션의 모든 원소가 어떤 조건을 만족하는지 판단하는 연산이다 count는 해당 조건에 만족하는 원소의 숫자를 반환해주는 연산이다 자바에서는 count가 아니라 size을 사용하는 경우가 있었는데 코틀린에서는 count가 있으니 요걸 사용하라.. size을 사용해서 처리하면 조건에 만족하는 모든 원소가 들어가는 중간 컬렉션이 생기지만 count은 조건을 만족하는 원소갯수만 추적하기 떄문에 더욱 효율적이다 그리고 find는 조건을 만족하는 첫 번째 원소를 반환해주는 연산이고 없으면 null을 반환해주는데, 이건 명시적으로 findOrNull 이렇게도 사용할 수 있다

또한 컬렉션에서 groupBy를 통해서 리스트를 여러 그룹으로 이루어진 맵으로 변경하는 것도 가능하다

        //이렇게 리스트를 만들고 
        val people = listOf(Person("Alice", "", 31), Person("Bob", "", 29), Person("Chailre", "", 29))
        println(people.groupBy {it.age})
        //이렇게 자동으로 원하는 특성으로 그룹화하는 것이 가능하다 

위에서의 println 의 결과는 {31=[Person(name=Alice, addr=, age=31)], 29=[Person(name=Bob, addr=, age=29), Person(name=Chailre, addr=, age=29)]} 이렇게 그룹화해서 보여준다 결과를 봐보면 Map<Int, List> 이 형태로 나오기 때문에 결과값을 가지고 mapKeys, mapValues 을 통해서 처리할 수 있다

그리고 중복된 컬렉션의 처리를 위한 flatMap, flatten도 존재한다 flatMap 함수는 리스트로 받은 놈들에 들어있던 모든 원소로 이루어진 단일 리스트를 반한다 "abc" + "def" => flatMap => (a,b,c,d,e,f) 이렇게 다양한 컬렉션에 관련된 함수가 있으니까 필요하면 사용하자

컬렉션 연산의 지연 계산

지금까지의 컬렉션 함수들은 즉시 다음 결과 컬렉션을 만들어서 생성한다 즉, 컬렉션 함수를 체이닝을 통해서 사용하면 매 단계마다 계산의 중간 결과를 새로운 컬렉션에 담는다는 의미이다 하지만 시퀀스를 사용하면 중간의 컬렉션을 통하는 단계를 건너띄고 컬렉션 연산이 가능하다 시퀀스의 사용 방법은 리스트.컬렉션함수~~ 이렇게 가 아니라 리스트.asSequence() 을 통해서 시퀀스 인터페이스를 시작으로 연산을 지정해야 한다 이렇게 지정하고 사용하면 중간 결과를 저장하는 컬렉션이 생성되지 않기 때문에 성능이 아주 좋아진다 코틀린 지연 계산 시퀀스는 시퀀스 인터페이스에서 시작한다. 이 인터페이스는 단지 한 번에 하나씩 열거될 수 있는 원소의 시퀀스를 표현하는 것이다 그리고 이 Sequence 안에는 iterator 라는 단 하나의 메소드를 통해 시퀀스로부터 원소 값을 얻는 것이 가능하다 Sequence의 강점은 그 인터페이스 위에 구현된 연산이 계산을 수행하는 방법 때문에 생긴다 그리고 시퀀스의 원소는 필요할 때 그때야 계산된다 근데 시퀀스를 사용하면 지연 계산하기 때문에 실제로 계산하는건 최종 시퀀스의 원소를 하나씩 iteration 하거나 최종 시퀀스를 리스트로 변환해야 한다

시퀀스의 연산에는 중간과 최종 연산이 있다 일단 중간 연산은 다른 시퀀스를 반환한다 그 시퀀스를 최조 시퀀스의 원소를 변환하는 방법을 안다 그리고 최종연산은 결과를 반환해준다 메소드 체이닝으로 연산을 막~~ 작업했을 때 일단 그냥 .filter.map~~ 이렇게만 해두면 계산작업이 진행되지 않고 아무런 작업이 없다가 toList을 붙혀주면 그제서야 최종결과를 반환해주는 것이다 시퀀스는 자바에서의 스트림과 같다는 점만 기억하고 있자 그리고 시퀀스를 만드는 방법은 asSequence()뿐만 아니라 generateSequence이라는 함수을 통해서도 만들 수 있다는 점

자바 함수형 인터페이스 활용

원래 자바에서 어떠한 인터페이스를 사용하고자 하면, 내부에서 새로 구현하도록 ide에서 자동으로 함수 내부에 인자만 들어가야하는데 내부에 주루루루룩 override 해야하는 함수들을 보여준다 코틀린에서는 무명 클래스 인스턴스 대신 람다를 넘길 수 있는데, 만약 인터페이스에서 내부 함수가 단 하나만 존재하는 경우에 그 함수에 넘기는 인자 -> 이러한 생김새로 람다방식으로 표현하는 것이 가능하다 이러한 인터페이스를 함수형 인터페이스라고 하고 SAM(Single Abstract Method) 인터페이스라고도 부른다 예시로 보면 이러하다

//자바
void postponeComputation(int delay, Runnable computation);

//코틀린에서는 위에서의 람다를 이 함수에 넘길 수 있고, 코틀린 컴파일러는 자동으로 람다를 runnable 인스턴스로 변환해준다
postponeComputation(1000) { println("This is Runnable") }

이렇게 실제로 컴파일러는 자동으로 그러한 무명 클래스와 인스턴스를 만들어준다 이때 그 무명 클래스에 있는 유일한 추상 메소드를 구현할 때 람다 본문을 메소드 본문으로써 활용한다 코틀린에서는 inline 키워드가 들어가 있는데 이 inline 함수는 람다식 내부의 실행문들을 컴파일 시, 람다를 호출하는 부분에 주입하는 방식이다 이렇게 자동으로 컴파일러가 변환을 진행해주는데, 수동으로 해야 하는 경우가 존재한다

SAM 생성자는 람다를 함수형 인터페이스의 인스턴스로 변환할 수 있게 컴파일러가 자동으로 생성한 함수이다 컴파일러가 자동으로 람다를 함수형 인터페이스 무명 클래스로 바꾸지 못하는 경우 SAM 생성자를 사용할 수 있다 람다로 생성한 함수형 인터페이스 인스턴스를 변수로 저장해야 하는 경우에도 SAM 생성자를 사용하는 것이 가능하다 만약에 여러가지 객체에 동일한 인터페이스를 적용하고 싶다면 함수형 인터페이스를 새롭게 객체에 구현해주고, 그 구현한 부분에서 각 객체에 대한 분기처리를 해주는 방식으로 적용할 수 있다

val listener = onClickListener{ view ->
    val text = when (view.id) {
        R.id.button1 -> "First Button"
        R.id.button2 -> "Second Button"
        else -> "No Button"
    }
    toast(text0
}
button1.setOnClickListener(listener)
button2.setOnClickListener(listener)

뭐 각각 onClickListener를 구현하는 객체 선언을 통해 리스너를 구현할 수도 있지만 SAM 생성자를 쓰는 게 더 좋다 뭐 이런식으로 수동으로도 작업하는 것도 가능하다는 점을 기억하자

수신 객체 지정 람다

apply, with 함수는 수신 객체를 명시하지 않고 람다의 본문 안에서 다른 객체의 메소드를 호출할 수 있게 해준다 그리고 이것을 수신 객체 지정 람다라고 부른다

with 함수는 어떠한 객체의 이름을 반복하지 않고도 그 객체에 대한 다양한 연산을 수행할 수 잇도록 해주는 라이브러리 함수이다

fun alphabat(): String{
        val result = StringBuilder()
        for(letter in 'A'..'Z'){
            result.append(letter)
        }
        result.append("\nNow I Know the Alphabat")
        return result.toString()
    }

여기서 보면 result를 매번 반복해서 사용했다 그래서 with을 통해서 다시 작성할 수 있다

fun alphabat(): String{
        val result = StringBuilder()
        return with(result){ //메소드를 호출하려는 수신 객체를 지정
            for(letter in 'A'..'Z'){
                this.append(letter) //this으로 명시해서 앞에서 지정한 수신 객체의 메소드를 호출
            }
            append("\nNow I know the alphabat") //this를 생략하고 메소드를 호출
            return this.toString() //람다에서 값을 반환
        }
    }

아니면 val result = with(stringBuilder, {...}) 이렇게도 사용하는 것이 가능하다 with 함수는 첫 번째 인자로 받은 객체를 두 번재 인자로 받은 람다의 수신객체로 만든다 그래서 인자로 받은 람다 에서는 this 키워드를 통해서 사용하는 것이 가능했다 그리고 this을 사용하지 않고 그냥 명시해서 사용하는 것도 가능하다 이렇게 with이 반환하는 값은 람다 코드를 실행한 결과이며 그 결과는 람다 식의 본문에 있는 마지막 식의 값이다

apply 함수는 람다의 결과가 결국 수신객체인 경우에 사용한다 즉 apply는 항상 자기에게 전달된 수신 객체를 반환한다 요놈은 apply는 확장 함수로 정의되어 있어서 apply 수신 객체가 전달받은 람다의 수신객체가 된다 위의 alphabat을 수정하면

fun alphabat() = StringBuilder().apply { 
        for( letter in 'A'..'Z'){
            append(letter)
        }
        append("\nNow i Know the alphabat")
    }.toString()

이렇게 apply는 객체의 인스턴스를 만들면서 즉시 프로퍼티의 일부분을 초기화해야하는 경우에 유용하다 자바에서는 빌더를 통해서 진행했었지만 코틀린에서는 기본적으로 지원해주기 때문에 apply를 활용하는 것이 가능하다

Previous클래스, 객체, 인터페이스Next코틀린 타입 시스템

Last updated 2 years ago

Was this helpful?