기존의 언어는 한 운영체제에 맞게 개발된 프로그램을 다른 종류의 운영체제에 적용하기 위한 노력이 필요하지만 자바에서는 JVM 에뮬레이터를 사용하기 때문에 이전과 같은 노력이 불필요함자바 운영프로그램은 운영체제나 하드웨어가 아닌 JVM 하고만 통신하고 JVM이 자바 응용
하나의 값을 저장할 수 있는 메모리 공간값(data)을 저장할 공간을 마련하기 위해서변수 타입 변수 이름;변수의 값이 필요한 곳에 변수의 이름을 적는다변수의 타입은 저장할 값의 타입에 의해 결정됨저장할 값의 타입과 일치하는 타입으로 변수를 선언\-> (int형 변수에
한 번만 값을 저장 가능한 변수값을 변경할 수 있는 변수와의 차이상수를 선언하는 방법은 변수명 앞에 final을 붙이는 것그 자체로 값을 의미함논리형false, true접미사 : 없음정수형123, 0b0101, 077, 0xFF, 100L접미사 : L (대소문자를 구분
논리형 : true와 false중 하나르 값으로 갖으며, 조건식과 논리적 계산에 사용문자형 : 문자를 저장하는데 사용되며, 변수 당 하나의 문자만을 저장할 수 있음정수형 : 정수 값을 저장하는데 사용. 주로 사용하는 것은 int와 long이며, byte는 이진 데이터를
println()의 단점 - 출력 형식 지정 불가실수의 자리수 조절 불가 - 소수점 n자리만 출력하려면?System.out.println(10.0/3); // 3.333333333......10진수로만 출력됨 - 8진수, 16진수로 출력하려면?System.out.pri
화면으로부터 데잉터를 입력받는 기능을 제공하는 클래스import문 추가import java.util.\*;Scanner 객체의 생성Scanner scanner = new Scanner System.in;Scanner 객체를 사용int num = scanner.nextI
대입과 단항 연산자를 제외하면 모두 왼쪽 -> 오른쪽3 + 4 - 5 -> 7 - 2x = y = 3 -> x = 3산술 > 비교 > 논리 > 대입 // 대입은 제일 마지막에 수행단항(1) > 이항(2) > 삼항(3) // 단항 연산자의 우선순위가 이항 연산자보다 높음
증가 연산자 (++) : 피연산자의 값을 1 증가시킴감소 연산자 (--) : 피연산자의 값을 1 감소시킴전위형 : 값이 참조되기 전에 증가시킴후위형 : 값이 참조된 후 증가시킴변수 또는 상수의 타입을 다른 타입으로 변경하는 것(타입)피연산자
int 와 int의 연산은 int 출력10 / 4 = 2 // 소수점 이하는 버려짐 (정확한 계산을 위해 int형을 float형으로 바꾸는 작업이 필요함)int와 float의 연산은 float 출력10 / 4.0f = 10.0f / 4.0f = 2.5f두 피 연산자의
실수를 소수점 첫 자리에서 반올림한 정수를 반환값에 알맞는 10의 n승값을 곱한 것을 round 계산 후 10의 n승으로 나누기오른쪽 피연산자로 나누고 남은 나머지를 반환int형만 가능
|| (OR결합) : 피연산자 중 한쪽이라도 true면 true&& (AND결합) : 피연산자 양쪽 모두 true여야 true조건식 ? 식1 : 식2조건이 참이면 식1, 거짓이면 식2
조건식이 참(true)일 때, 괄호 {} 안의 문장들을 수행둘 중 하나 -조건식이 참일때와 거짓일 때로 나눠서 처리switch문의 조건식 결과는 정수 또는 문자열이어야 함case문의 값은 정수 상수(문자 포함), 문자열만 가능하며, 중복되지 않아야 함case문 안에 b
특정 코드를 반복해서 실행할 때 사용 (일반적으로 반복 횟수가 명확할 때 사용)조건이 참인 동안 반복해서 특정 코드를 실행할 때 사용 조건식이 false가 되면 반복을 종료합니다.블럭{}을 최소 한 번 반복 (사용자 입력 받을 때 유용)
break나 continue는 하나의 반복문만 탈출할 수 있지만 반복문에 이름을 붙이면 중첩 루프에서도 원하는 루프까지 탈출할 수 있음반복문 이름을 지정하지 않았다면 j for문만 빠져나갔을텐데 반복문 이름을 지정한 덕분에 i for문까지 탈출함
: 각 요소에 자동으로 붙는 (일련)번호인덱스의 범위는 0 ~ '배열길이' - 1배열 이름.length (int형 상수)배열은 한번 생성하면 그 길이를 바꿀 수 없음왜? : 연속적으로 필요한 메모리 공간을 확보하지 못할 수 있음공간이 부족하면? : 새로운 배열 생성,
배열 이름으로 출력하면 안됨단 char 배열일때는 이름으로 출력해도 됨요소를 하나씩 출력하기 (반복문, Arrays.toString 메소드)
총합과 평균 최대와 최소
0번째와 n(0~9)번째 요소를 100번 교환6개의 번호 생성을 위해 6회 반복으로 i와 j번째 요소를 교환
String 배열을 이용한 간단한 가위바위보String 클래스는 char\[]와 메서드(기능)을 결합한 것String클래스는 내용을 변경할 수 없음 (read only)
1차원 배열 비교할 때는 equals 활용, 다차원 배열 비교는 deepEquals길이가 원본 배열보다 길면 나머지 부분은 0으로 채움
A행렬(m1, n1)과 B행렬(m2, n2)를 곱셈하기 위해서는 n1 = m2의 조건을 만족해야 함
클래스의 정의 : 객체를 정의해 놓은 것클래스의 용도 : 객체를 생성하는데 사용객체의 정의 : 실제로 존재하는 것. 사물 또는 개념객체의 용도 : 객체가 가지고 있는 기능과 속성에 따라 다름객체 : 모든 인스턴스를 대표하는 일반적 용어인스턴스 : 특정 클래스로부터 생성
클래스는 다음 세가지 관점으로 볼 수 있음설계도데이터와 함수의 결합사용자 정의 타입: 배열이 같은 종류의 여러 데이터를 하나로 지정할 수 있는 공간이라면, 구조체는 종류에 구애받지 않고 서로 연관된 여러 데이터를 하나로 저장할 수 있는 공간이다.클래스는 이러한 구조체(
변수는 선언 위치에 따라 3가지 종류 로 나뉜다. (인스턴스 변수, 클래스 변수, 지역 변수)클래스 영역에서 선언되는 변수 : IV (Instance Variable) , CV (Class Variable)메서드 영역에서 선언되는 변수 : LV (Local Variab
: 문장들을 묶어놓은 것프로그래밍에서는 코드의 중복을 기피하고자 함 -> 중복되는 내용을 메서드화 해서 사용값(입력)을 받아서 처리하고, 결과를 반환(출력)메서드는 클래스 안에 있어야 함배열을 출력하는 코드를 printArr이라는 이름의 메서드로 표현 -> 직접 한 줄
: 밑이 막힌 상자 (위에 차곡 차곡 쌓임)자세한 건 이후 자료 구조 포스팅 예정: 메서드 수행에 필요한 메모리가 제공되는 공간메서드가 호출되면 호출스택에 메모리 할당, 종료되면 해제그림 상 아래에 있는 메서드가 위에 있는 메서드를 호출 한 것임하나의 스택에서는 하나의
기본형 매개변수 : 변수의 값을 읽기만 할 수 있음 (read only)참조형 매개변수 : 변수의 값을 읽고 변경할 수 있음 (read & write)호출 스택에서 main 실행main 메서드에서 d.x = 10 저장main 메서드 위에 change 메서드 실행chan
인스턴스 생성 후, '참조변수.메서드이름()'으로 호출인스턴스 멤버(iv, im)와 관련된 작업을 하는 메서드메서드 내에서 인스턴스 변수(iv) 사용 가능객체생성 없이 '클래스이름.메서드이름()'으로 호출인스턴스 멤버(iv, im)와 관련없는 작업을 하는 메서드메서드
: 한 클래스 안에 같은 이름의 메서드 여러 개 정의하나의 메소드로 여러가지 동작을 수행할 수 있음메서드 이름이 같아야 함매개변수의 개수 또는 타입이 달라야 함반환 타입은 영향 없음위의 경우는 메서드 이름이 같지만 매개변수의 개수와 타입이 일치하기 때문에 오버로딩이라고
: 인스턴스가 생성될 때마다 호출되는 인스턴스 초기화 메서드위 과정을아래와 같이 단순화생성자의 이름은 클래스의 이름과 같아야 함반환값이 없어도 void 붙이지 않음모든 클래스는 반드시 하나 이상의 생성자를 가지고 있어야 함 !!매개변수가 없는 생성자생성자가 하나도 없을
생성자에서 다른 생성자 호출할 때 사용다른 생성자 호출시 첫 줄에서만 사용 가능인스턴스 자신을 가리키는 참조변수인스턴스 메서드(생성자 포함)에서 사용 가능지역변수(LV)와 인스턴스 변수(IV)를 구변할 때 사용위 코드에서는 this 생략 가능위 코드에서는 생성자의 매개
지역변수는 수동 초기화 해야함 (사용 전 꼭)멤버변수 (iv, cv)는 자동 초기화 됨명시적 초기화 (=, 간단한 초기화)참조형 변수는 null (기본값) 혹은 객체의 주소로 초기화 함초기화 블럭 (복잡한 초기화)인스턴스 초기화 블럭 : {}클래스 초기화 블럭 : st
기존의 클래스로 새로운 클래스를 작성 (코드의 재사용)두 클래스를 부모와 자식으로 관계를 맺어줌자손은 조상의 모든 멤버를 상속받음 (생성자, 초기화블럭 제외)자손의 멤버 개수는 조상보다 적을 수 없음 (같거나 많음)자식의 멤버는 1개 (상속받은 age 1개 + 자식 자
클래스의 멤버로 참조변수를 선언하는 것Circle과 Point는 포함관계가 됨 작은 클래스를 만들고, 이 들을 조합해서 클래스를 생성Car 클래스에서 모든 멤버들을 전부 선언하는 것 보다는 세부적인 클래스를 포함 하는 것이 복잡도면에서 유리함또한 Engine과 Door
상속받은 조상의 메서드를 자신에 맞게 변경하는 것Point3D에서는 상속받은 getLocation()을 그대로 쓸 수 없기 때문에 Point3D 역할에 맞는 동작으로 수정함 -> 오버라이딩선언부가 조상 클래스의 메서드와 일치해야 함접근 제어자를 조상 클래스의 메서드보다
객체 자신을 가리키는 참조변수. 인스턴스 메서드(생성자) 내에서만 존재조상의 멤버를 자신의 멤버와 구별할 때 사용조상의 생성자를 호출할 때 사용조상의 멤버는 조상의 생성자를 호출해서 초기화생성자의 첫 줄에 반드시 생성자를 호출해야 함그렇지 않으면 컴파일러가 생성자의 첫
서로 관련된 클래스의 묶음클래스는 클래스 파일(\*.class), 패키지는 폴더. 하위 패키지는 하위 폴더클래스의 실제 이름 (full name) 은 패키지를 포함. (java.lang.String)rt.jar는 클래스들을 압축한 파일 (JDK설치경로₩jre₩lib에
클래스를 사용할 때 패키지 이름을 생략할 수 있음컴파일러에게 클래스가 속한 패키지를 알려줌java.lang 패키지의 클래스는 import 하지 않고도 사용할 수 있음 (String, Object, Systsem, Thread ...}import 패키지명.클래스명;imp
클래스와 클래스의 멤버 (멤버 변수, 메서드)에 부가적인 의미 부여접근 제어자 : public, proteted, (default), private그 외 : static, final, abstract, native, transient, synchronized, vola
접근 제어자 (Access Modifier) private : 같은 클래스 내에서만 접근 가능 (default) : 같은 패키지 내에서만 접근 가능 protected : 같은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근 가능 public : 접근 제한이
외부로부터 데이터를 보호하기 위함외부에는 불필요한, 내부적으로만 사용되는 부분을 감추 위함변수는 private로 외부 접근을 차단public 메서드를 통해 간접 접근은 가능하도록 허용Time t = new Time(); 객체를 통한 hour에 대한 접근에서 hour가

컴파일 에러 : 컴파일 시에 발생하는 에러 (구문 등)런타임 에러 : 실행시에 발생하는 에러 (범위 등)논리적 에러 : 실행은 되지만, 의도와 다르게 동작 에러(error) : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류예외(exception) : 프로그램 코드
정의 : 프로그램 실행 시 발생할 수 있는 예외의 발생에 대바한 코드를 작성하는 것목적 : 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것(참고) try-catch문은 괄호 생략 불가능try 블럭 내에서 예외가 발생한 경우발생한 예외와 일치하는 catc
printStackTrace() : 예외발생 당시의 호출스택 (Call Stack)에 있었던 메서드의 정보와 예외 메세지를 화면에 출력getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메세지를 얻을 수 있음1, 2, 3 출력 후 0/0 연산에서 Arith

연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든 다음Exception e = new Exception("고의로 발생시켰음")키워드 throw를 이용해서 예외를 발생시킴throw e;위 코드 결과에러 메세지 : 고의로 발생시켰음java.lang.Excep
예외를 처리하는 방법 : 1. try-catch문, 2. 예외 선언하기메서드가 호출시 발생가능한 예외를 호출하는 쪽에 알리는 것!참고 : 예외를 발생시키는 키워드 throw와 예외를 메서드에 쓰이는 throws를 잘 구별할 것위 처럼 예외처리를 예외가 발생한 곳에서 할
사용자가 직접 예외 클래스를 정의함조상은 Exception과 RuntimeException 중에 선택 (가능하면 선택 처리가 가능한 RuntimeException을 조상으로 함)예외 처리한 후에 다시 예외를 발생시키는 것호출한 메서드와 호출된 메서드 양족 모두에서 예외
한 예외가 다른 예외를 발생시킬 수 있음예외 A가 에외 B를 발생시키면, A는 B의 원인 예외 (cause exception)초기값은 자기 자신을 원인 예외로 등록함이후 예외A를 인스턴스 변수 cause에 저장여러 예외를 하나로 묶어 다루기 위함checked 예외를 u
모든 클래스의 최고 조상. 오직 11개의 메서드만을 가지고 있음notify(), wait() 등은 쓰레드와 관련된 메서드임객체 자신(this)과 주어진 객체(obj)를 비교같으면 true 다르면 falseObject 클래스의 equals()는 객체의 주소를 비교(참조변
객체의 해시코드(hash code)를 반환하는 메서드Object클래스의 hashCode()는 객체의 주소를 int로 변환해서 반환객체의 지문 역할을 함equals()를 오버라이딩하면, hashCode()도 오버라이딩해야 함equals()의 결과가 true인 두 객체의
String 클래스 = 데이터(char\[]) + 메서드(문자열 관련)내용을 변경할 수 없는 불면(immutable) 클래스덧셈 연산자(+)를 이용한 문자열 결합은 성능이 떨어짐. 문자열의 결합이나 변경이 잦다면 내용 변경 가능한 StringBuffer를 사용위 경우
String 클래스의 생성자와 메서드 | 메서드 / 설명 | 예제 | 결과 | |----------------------------------------------|-----...
join()은 여러 문자열 사이에 구분자를 넣어서 결합한다.
String처럼 문자형 배열(char\[])을 내부적으로 가지고 있음String이 불변인 점과 다르게 StringBuffer는내용 변경 가능 (mutable)append()는 지정된 내용을 StringBuffer에 추가 후, StringBuffer의 참조를 반환위 코드
StringBuffer의 생성자와 메서드 | 메서드 / 설명 | 예제 | 결과
StringBuffer는 동기화되어 있음 -> 멀티 쓰레드에 안전(thred-safe)싱글 쓰레드 : 한 번에 1개 작업멀티 쓰레드 : 한 번에 n개 작업멀티 쓰레드 프로그램이 아닌 경우, 동기화는 불필요한 성능저하 (싱글 스레드에서는 무조건 StringBuilder를
8개의 기본형을 객체로 다뤄야할 때 사용하는 클래스래퍼클래스를 사용하는 이유?컬렉션 프레임워크 : Java의 컬렉션 프레임워크(List, Set, Map 등)는 객체만을 다룸. 기본형은 객체가 아니기 때문에, 이를 사용하기 위해 기본형 값을 객체로 감쌈유틸리티 메서드
오토박싱 : int -> Integer ( 기본형을 래퍼클래스로 )언박싱 : Integer -> int ( 래퍼클래스를 기본형으로 )
컬렉션(collection) : 여러 객쳬(데이터)를 모아 호은 것프레임웍(framework) : 표준화, 정형화된 체계적인 프로그래밍 방식 -> 프로그래밍의 생산성 증가, 유지보수 쉬워짐컬렉션 프레임웍 : 컬렉션(다수의 객체)을 다루기 위한 표준화된 프로그래밍 방식컬
VectorArrayListLinkedListList 인터페이스의 메서드들은 기본적으로 Collections의 메서드들을 지니고 있음SetSortedSetTreeSetSet 인터페이스의 메서드는 기본적으로 Collection 인터페이스와 동일Hashtable (old)
기존의 Vector를 개선한 것으로 구현원리와 기능적으로 동일Vector와 달리 ArrayList는 동기화처리가 되어있지 않음List 인터페이스를 구현하므로, 저장순서가 유지되고 증복을 허용데이터의 저장공간으로 배열을 사용함 (배열기반)객체만 저장 가능ArrayList
장점배열은 구조가 간단하고 데이터를 읽는 데 걸리는 시간이 짧음단점크기를 변경할 수 없음크기를 변경해야 하는 경우 새로운 배열을 생성 후 데이터를 복사해야 함크기 변경을 피하기 위해 충분히 큰 배열을 생성하면, 메모리가 낭비됨비순차적인 데이터의 추가, 삭제에 시간이 많
LIFO (Last In First Out) 구조마지막에 저장된 것을 제일 먼저 꺼내게 됨밑이 막힌 상자배열로 구현이 유리Stack st = new Stack();FIFO (First In First Out) 구조제일 먼저 저장한 것을 제일 먼저 꺼냄파이프LinkedL
배열을 다루기 편리한 메서드(static) 제공static String toString(boolean\[] a)static String toString(byte\[] a) 등이진 탐색은 정렬되어있을 경우만 사용 가능
객체 정렬에 필요한 메서드(정렬 기준 제공)를 정의한 인터페이스Comparable : 기본 정렬기준을 구현하는데 사용Comparator : 기본 정렬기준 외에 다른 기준으로 정렬하고자할 때 사용CASE_INSENSITIVE_ORDER : 미리 String 클래스에 만들
Set 인터페이스를 구현한 대표적인 컬렉션 클래스순서를 유지하려면, LinkedHashSet 클래스를 사용HashSet() : 생성자HashSet(Collection c) : 지정한 컬렉션에 모든 객체 저장HashSet(int initialCapacity) : 초기 용

이진 탐색 트리(binary search tree)로 구현범위 탐색과 정렬에 유리 (HashSet과 다르게 정렬이 필요 없음)이진 트리는 모든 노드가 최대 2개의 하위 노드를 가짐각 노드가 나무의 형태로 연결 (LinkedList 변형)부모보다 작은 값은 왼쪽 큰 값은
순서 X , 중복 (키 X, 값 O )Map 인터페이스를 구현데이터를 키와 값의 쌍으로 저장HashMap(동기화 X)은 Hashtabe(동기화 O)의 신버전HashMapMap 인터페이스를 구현한 대표적인 컬렉션 클래스순서를 유지하려면, LinkedHashMap 클래스를
컴파일시 타입을 체크해 주는 기능(compile-time type check) -JDK1.5객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌List는 Object 타입을 반환하기 때문에 추출한 요소에 (Tv)를 붙여 형변환을 해주어야 하지만 지네릭스를 사용함으로써
클래스를 작성할 때, Object타입 대신 T와 같은 타입 변수를 사용지네릭스를 사용함으로 인해 name 출력시 Student로 형변환을 하지 않아도 됨여러 개의 타입 변수가 필요한 경우, 콤마()를 구분자로 선언생성자에 지정하는 타입은 위와 같이 생략 가능 (new
오버라이딩을 올바르게 했는지 컴파일러가 체크하게 함오버라이딩할 때 메서드 이름을 잘못 적는 실수를 하는 것을 방지오버라이딩할 때는 메서드 선언부 앞에 @Override 붙이기앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙임이전 버전과의 호환성의 가치 떄문에 권장
프로세스 (공장)실행중인 프로그램자원(resource)과 쓰레드로 구성쓰레드 (일꾼)프로세스 내에서 실제 작업을 수행모든 프로세스는 최소한 하나의 쓰레드를 가지고 있음싱글 쓰레드 프로세스자원 + 쓰레드멀티 쓰레드 프로세스자원 + 쓰레드 + 쓰레드 + ... + 쓰레드하
입출력시 작업 중단입출력시 I/O 블락킹에 의해 작업이 중단되는 것을 극복하기 위해 멀티쓰레드로 작성작업의 중요도에 따라 쓰레드의 우선수위를 다르게 하여 특정 쓰레드가 더 많은 작업시간을 갖게 할 수 있음자바에서는 쓰레드의 우선순위를 1~10으로 보유할 수 있게 함 (
데몬 쓰레드 (deamon thread) 일반 쓰레드(non-daemon thread)의 작업을 돕는 보조적인 역할을 수행 일반 쓰레드가 모두 종료되면 자동적으로 종료 가비지 컬렉터, 자동저장, 화면 자동갱신 등에 사용 무한루프와 조건문을 이용해서 실행 후 대기하다가
현재 쓰레드를 지정된 시간동안 멈추게 함예외처리를 해야 함 (InterruptedException 발생하면 깨어남)특정 쓰레드를 지정해서 멈추게 하는 것은 불가능예시대기상태(WATING)인 쓰레드를 실행대기 상태(RUNNABLE)로 변경예시
suspend(), resume(), stop() 쓰레드의 실행을 일시정지, 재개, 완전정지 suspend(), resume(), stop()은 교착상테에 빠지기 쉬워 deprecated 되었음
함수를 간단한 식으로 표현하는 방법함수와 메서드 차이?근본적으로 동일함수는 일반적 용어메서드는 객체지향개념 용어함수는 클래스에 독립적메서드는 클래스에 종족적메서드의 이름과 반환타입을 제거하고 '->'를 블록{} 앞에 추가반환값이 있는 경우, 식이나 값만 적고 retur
함수형 인터페이스 단 하나의 추상 메서드만 선언된 인터페이스 @FunctionalInterface 애노테이션을 붙여주면 컴파일러가 잘 작성했는지 확인해줌 함수형 인터페이스 타입의 참조변수로 람다식을 참조할 수 있음 단, 함수형 인터페이스의 메서드와 람다식의 매개변
and(), or(), negate()로 두 Predicate를 하나로 결합 (default 메서드)위를 아래와 같이 결합 가능추상메서드 test를 통해 검증
하나의 메서드만 호출하는 람다식은 '메서드 참조'로 간단하기 할 수 있음생성자와 메서드 참조배열과 메서드 참조
다양한 데이터 소스를 표준화된 방법으로 다루기 위한 것스트림이 제공하는 기능 - 중간 연산과 최종 연산중간 연산 : 연산결과가 스트림인 연산. 반복적으로 적용가능최종 연산 : 연산결과가 스트림이 아닌 연산. 단 한번만 적용가능(스트림의 요소를 소모)스트림은 데이터 소스
스트림이 제공하는 기능 - 중간 연산과 최종 연산중간 연산연산결과가 스트림인 연산반복적으로 적용 가능최종 연산연산결과가 스트림이 아닌 연산단 한번만 적용가능(스트림의 요소를 소모)최종 연산 후 스트림이 닫힘
스트림 자르기 - skip(), limit() 스트림의 요소 걸러내기 - filter(), distinct() 스트림 정렬 - sorted() | 문자열 스트림 정렬 방법 | 출력결과 | |------------------------...
파일 스트림(Stream)에서 파일 확장자(대문자)를 중복 없이 뽑아내기ex)
T 타입 객체의 래퍼클래스 - OptionalT에는 모든 종류의 객체 저장 가능 (null 포함)Optional 객체를 생성하는 다양한 방법get(), orElse(), orElseGet(), orElseThrow()isPresent() - Optional 객체의 값이
ex)ex)ex)
collect()는 Collectors를 매개변수로 하는 스트림의 최종연산reduce는 그룹 전체에 대해 리듀싱 하는 반면, collect()는 그룹별로 리듀싱 가능Collector는 수집(collect)에 필요한 메서드를 정의해 놓은 인터페이스Collectors 클래