java.io

IO 종단점

Closeable

  1. 데이터의 출발지나 목적지를 닫을 수 있으면 Closeable
  2. void close()
  3. 스트림 및 이와 관련된 시스템 자원을 해제한다. 이미 호출되었다면 아무 일도 하지 않는다
    close() 실패했을 때, 예외를 던지는 대신 사용하던 자원을 모두 포기하고 Closeable 객체 내부적으로 '닫혔다(closed)'고 마크하길 권장한다

Flushable

  1. flush 가능한 데이터 목적지는 Flushable
  2. void flush()
  3. 버퍼에 저장된 데이터를 스트림에 모두 써 보낸다

바이트 단위 IO

DataInput

  1. binary stream으로부터 바이트들을 읽고, 또 이를 자바 기본 타입 또는 String으로 만들어 반환하는 기능 정의
  2. 읽기는 1바이트 단위로 이루어진다
  3. Modified UTF-8
  4. DataInput과 DataOutput 인터페이스는 수정된 UTF-8을 이용한다

    • '\u0001' ~ '\u007F'는 1바이트(0???????)로 표현한다
    • null('\u0000'), '\u0080' ~ '\u07FF'는 2바이트(110????? 10??????)로 표현한다
    • '\u0800' ~ '\uFFFF'는 3바이트(1110??? 10?????? 10??????)로 표현한다

↓ java

String readLine() // 줄의 끝이나 파일 끝을 만나기까지의 문자열을 반환한다 // 각 바이트들을 0 패딩하여 char로 변환하므로, 유니코드를 읽기는 부적합하다 // 아무것도 읽지 못한 경우, 빈 문자열이 아닌 null이 반환된다 String readUTF() // 먼저 readUnsignedShort()와 같은 방법으로 2개 바이트를 읽어와 길이를 구한다 // 구한 길이만큼의 바이트를 읽으면서 상기한 Modified UTF-8에 맞춰 String을 만든다 // 길이만큼의 바이트를 다 읽기 전에 EOF를 만나면 예외를 던진다

DataOutput

DataInput과 대칭

InputStream

  1. 바이트 단위 읽기에 대한 최상위 추상 클래스
  2. 작업이 끝날 때까지 스레드가 블록되며, 스트림이 비동기적으로 닫히거나, 인터럽트가 발생하는 경우에 대해 대처하지 않는다

↓ java

static InputStream nullInputStream() // 아무것도 읽지 않는 InputStream // 반환된 스트림은 처음부터 열려 있고, 마치 스트림의 끝에 도달한 것처럼 작동한다 long transferTo(OutputStream out) // 입력 스트림의 모든 바이트를 읽어들여 out에 쓴다 // 총 전송 바이트 수를 반환하며, 스트림을 닫는 작업은 하지 않는다 byte[] readAllBytes() byte[] readNBytes(int len) long skip(long n) // 실제로 건너뛴 바이트 수를 반환. 음수 매개변수에 대해 0을 반환한다. 서브클래스들의 구현은 이와 다를 수 있다 int available() // 막힘 없이 한 번에 읽어올 수 있는 바이트 수 예상값을 반환 // 구현에 따라 전체 바이트 수를 반환하기도, 그렇지 않기도 하다. InputStream 자체는 항상 0을 반환하며, 서브클래스에서 재정의해야 한다 boolean markSupported() // mark, reset 메서드를 지원하는지 여부 반환. 기본 false void mark(int readlimit) // 현재 위치 마킹 void reset() // 마지막 마킹 위치로 이동

OutputStream

바이트 단위 쓰기에 대한 최상위 추상 클래스

↓ java

static OutputStream nullOutputStream() // 실제로 데이터를 쓰지는 않는 OutputStream 객체를 반환한다

ByteArrayInputStream

내부 버퍼 byte[] buf에 대한 읽기 연산을 지원하는 InputStream

ByteArrayOutputStream

내부 버퍼 byte[] buf에 대해 쓰기 연산을 지원하는 OutputStream. 버퍼 크기는 자동으로 확장된다

↓ java

void writeTo(OutputStream out) // 버퍼를 out에 모두 쓴다. == out.write(buf, 0, count) byte[] toByteArray() // 사본 반환 void reset() // 버퍼 처음부터 재활용 String toString​(Charset charset)

PipedInputStream

PipedOutputStream를 소스로 하는 InputStream. PipedOutputStream과 별개 스레드에서 동작해야 한다

PipedOutputStream

PipedInputStream에 쓰는 OutputStream. PipedInputStream과 별개 스레드에서 동작해야 한다

SequenceInputStream

여러 InputStream을 이어붙인듯이 활용하는 InputStream

FileInputStream

파일을 읽는 InputStream

↓ java

FileChannel getChannel() // 유니크한 FileChannel을 반환하며, 채널에서의 위치는 스트림에서 읽어들인 만큼과 같다

FileOutputStream

파일에 쓰는 OutputStream

↓ java

FileChannel getChannel() // 유니크한 FileChannel을 반환하며, 채널에서의 위치는 스트림에서 쓴 바이트 수와 같다(append 모드가 아닐 경우) // append 모드에서는 파일의 크기와 채널의 위치가 동일하다

InputStream 장식자

FilterInputStream

아무 기능 추가 없는 장식자

BufferedInputStream

버퍼를 이용해 mark(), reset() 지원

DataInputStream

DataInput 구현 제공

PushbackInputStream

  • 이미 읽은 것을 취소하고 다시 읽을 수 있는 기능을 지원한다
  • 이전에 읽은 내용을 저장하지는 않으므로, 덮어쓰기처럼 이용할 수 있다

OutputStream 장식자

FilterOutputStream

아무 기능 추가 없는 장식자

BufferedOutputStream

버퍼를 이용해 쓰기 작업이 빈번하게 일어나지 않게 해준다

DataOutputStream

DataOutput 구현 제공

PrintStream

  • OutputStream, File에 기본 타입 및 각종 문자열을 쓰는 기능 제공
  • autoFlush : 바이트 배열을 다 쓰거나, 새 줄 문자, '\n'을 쓰면 자동으로 flush()

↓ java

boolean checkError() // flush()한 다음 오류 상태를 검사한다. 예외를 던지지 않으므로 이 메서드로 확인해야 한다 // 스트림에 InterruptedIOException이 발생하면 Thread.currentThread().interrupt()를 실행한다

문자 단위 IO 관련

Console

  1. JVM이 컨트롤할 수 있는 문자 기반 콘솔에 대한 접근 제공. 콘솔 존재 여부는 하위 플랫폼에 의존적이며, 싱글톤으로 System.console()을 통해 얻을 수 있다. 만일 가용한 콘솔이 없다면 null이 반환된다.
  2. 콘솔에 대한 읽기/쓰기 작업은 모두 원자적으로 이루어지며, 따라서 다른 스레드가 대기할 가능성이 있다
  3. 콘솔에 대한 close()는 아무런 영향이 없다
  4. 유닉스의 Ctrl+D, 윈도우의 Ctrl+Z와 같은 종료 문자를 만나면 읽기 메서드는 null을 반환한다
  5. 보안 유의 : 패스워드와 같은 중요한 데이터를 읽을 때, readPassword(...) 메서드를 이용하고, 반환된 char[]는 사용 후 수동으로 0 초기화

↓ java

PrintWriter writer() // 유니크한 PrintWriter 객체 반환 Reader reader() // 유니크한 Reader 객체 반환

Reader

char 단위 읽기에 대한 최상위 추상 클래스

↓ java

static Reader nullReader() // 아무 것도 읽지 않는 Reader 객체를 반환한다 int read() // char 하나를 읽고 int로 반환. 스트림의 끝이라면 -1을 반환한다 boolean ready() // 다음 read()가 블록되지 않음을 보장하면 true, 보장하지 못하면 false // 마킹 관련 boolean markSupported() // mark, reset 메서드를 지원하는지 여부 반환. 기본 false void mark(int readAheadLimit) // 현재 위치 마킹 void reset() // 마지막 마킹 위치로 이동 long transterTo(Writer out) // 모든 글자를 읽어 out에 쓴다. 전송한 글자 수를 반환한다

Writer

  1. char 단위 쓰기에 대한 취상위 추상 클래스
  2. Appendable하므로 편리함이 크다

↓ java

static Writer nullWriter() // 아무것도 쓰지 않는 Writer 객체를 반환한다 void write(int c) // 하위 16비트만 쓴고 나머지는 무시한다

InputStreamReader

InputStream에 대해 Reader 작업을 지원해주는 bridge 클래스

OutputStreamWriter

OutputStream에 Writer 작업을 지원해주는 bridge 클래스

CharArrayReader

내부 버퍼 char[] buf에 대한 읽기 연산을 지원하는 Reader

CharArrayWriter

내부 버퍼 char[] buf에 대해 쓰기 연산을 지원하는 Writer. 버퍼 크기는 자동으로 확장된다

↓ java

void writeTo(Writer out) // out에 버퍼의 모든 내용을 쓴다 void reset() // 버퍼를 처음부터 재활용 char[] toCharArray() // 사본 반환

StringReader

String을 읽는 Reader

StringWriter

StringBuffer에 쓰는 Writer

PipedReader

PipedWriter를 소스로 하는 Reader

PipedWriter

PipedReader로 쓰는 Writer

FileReader

파일을 읽는 Reader

FileWriter

파일에 쓰는 Writer

Reader 장식자

FilterReader

아무 기능 추가 없는 장식자

BufferedReader

버퍼를 이용해 mark(), reset()를 지원하고, 기저 Reader에 대한 읽기 작업이 빈번하게 일어나지 않게 해준다

LineNumberReader

줄 끝을 만날때마다 카운트

↓ java

void setLineNumber(int lineNumber) // 읽고 있는 위치가 이동하는 건 아니다 int getLineNumber()

PushbackReader

Goto - PushbackInputStream과 비슷

Writer 장식자

FilterWriter

아무 기능 추가 없는 장식자

BufferedWriter

버퍼를 이용해 기저 Writer에 대한 쓰기 작업이 빈번하게 일어나지 않도록 한다

PrintWriter

  • Goto - PrintStream의 Writer 버전
  • 다른 OutputStream, Writer, 파일에 기본 타입 및 각종 문자열을 쓰는 기능을 제공
  • PrintStream과 마찬가지로 checkError()로 실패를 확인해야 한다

파일 관련

File

  1. 추상화된 파일 및 디렉터리 경로에 대한 추상화된 표현 제공; 물리적 저장 장치 » 경로 문자열 » File 객체
  2. 경로 문자열은 절대 경로, 상대 경로 둘 다 허용된다. 상대 경로의 기준 위치는 System속성 "user.dir"로 얻을 수 있다
  3. 보다 많은 기능을 제공하는 java.nio.file 패키지가 존재한다

↓ java

public static final char separatorChar public static final String separator // 시스템 속성 "file.separator", UNIX : '/', Windows : '\\' public static final char pathSeparatorChar public static final String pathSeparator // 시스템 속성 "path.separator", UNIX : ':', Windows : ';' boolean mkdirs() // 경로상 필요한 모든 디렉터리들 생성 String[] list() // ls static File[] listRoots() static File createTempFile(String prefix, String suffix) // (특정) 디렉터리에 새로운 빈 파일을 만들어 반환한다 // deleteOnExit()을 통해 자동으로 정리되어야 한다 // prefix : 의미 있는 접두어, suffix : null이면 ".tmp"

RandomAccessFile

  • 읽기(DataInput)/쓰기(DataOutput) 가능한 임의 접근 파일
  • mode : "r" | "rw" | "rws"(파일 내용 및 메타데이터 변경을 곧바로 반영) | "rwd"(파일 내용 변경을 곧바로 반영)
  • 읽기/쓰기의 기준 위치가 되는 file pointer가 존재
  • 읽기로 예정된 바이트들을 모두 읽기 전에 EOF를 만나면 EOFException 발생

↓ java

long getFilePointer() void seek(long pos) // file pointer 설정 long length() void setLength(long newLength) // 기존 크기 > newLength → 자르기 // getFilePointer() > newLength → file pointer = newLength // 기존 크기 < newLength → 확장. 확장한 영역의 데이터는 초기화되지 않는다

java.lang

AutoCloseable

  • 자동으로 자원을 해제하는 객체를 표현한다
  • try-with-resources 블록에 사용되면 close()가 자동으로 호출된다
  • IO 작업이 없는 것들을 try-with-resources 블록에 이용하는 것은 불필요한 일이다

Comparable<T>

  1. 인스턴스를 정렬하는 자연스러운 순서 정의
  2. 이를 구현한 클래스 객체들의 List, array는 Collections.sort, Arrays.sort로 각각 정렬할 수 있다
  3. 이를 구현한 클래스 객체들은 Comparator 정의 없이 SortedMap, SortedSet의 키로 이용할 수 있다
  4. null은 객체가 아니므로 equals(null)이 false를 리턴하는 것과 달리 compareTo(null)은 NullPointerException을 내보내는 것이 바람직하다
  5. 다음 성질을 만족하도록 구현함이 권장된다

    ↓ java

    (e1.compareTo(e2) == 0) == e1.equals(e2)

Iterable<T>

이를 구현한 클래스 객체는 enhanced for statement의 순회 대상이 될 수 있다

ProcessHandle

  1. native process들에 대한 제어 제공
  2. 프로세스 생애 모니터링, 자식 프로세스 나열, 프로세스 정보 얻기, 프로세스 종료 등

  3. ProcessHandle 객체는 다음 팩터리 메서드로 반환된다
  4. ↓ java

    current(), of(long), children(), descendants(), parent(), allProcesses()
  5. SecurityManager의 RuntimePermission("manageProcess")만큼의 제어 권한을 갖는다
  6. ProcessHandle 객체들을 비교할 때는 equals, compareTo 메서드를 이용해야 한다

↓ java

ProcessHandle.Info info() boolean supportsNormalTermination() // destroy() 메서드가 정상적으로 프로세스를 종료하는지 여부. false면 프로세스를 강제로 즉시 종료함을 의미 CompletableFuture<ProcessHandle> onExit() // onExit().get()을 호출하면 프로세스가 종료되는 것을 기다린다 // supportsNormalTermination()이 false일 경우 onExit()에 등록한 후처리들이 진행되지 않을 수 있음 boolean destroy() // 프로세스 종료에 시간이 걸릴 수 있으므로, isAlive()가 얼마간 true를 반환할 수 있다 // 성공적으로 프로세스를 종료하면 true, 아니면 false를 반환한다 boolean destroyForcibly() // 강제 종료 long pid() boolean isAlive() // PID가 유효하면 alive로 간주

ProcessHandle.Info

↓ java

Optional<String> command() // 실행가능한 경로 반환 Optional<String> commandLine() // command()와 arguments()의 결과를 공백으로 구분한 결과 반환 Optional<String[]> arguments() // 프로세스의 인자 반환 Optional<Instant> startInstant() // 프로세스의 시작 시각 반환 Optional<Duration> totalCpuDuration() // CPU 사용 시간 반환 Optional<String> user() // 프로세스 유저 반환

Math, StrictMath

↓ java

static double IEEEremainder(double f1, double f2) static double rint(double d) // round to even // 오버플로우되면 예외 addExact, substractExact, multiplyExact, incrementExact, decrementExact, negateExact, toIntExact static long multiplyFull(int x, int y) static long multiplyHigh(long x, long y) // 상위 64개 비트를 반환 floorDiv(x, y) // x/y 이하 최대 정수 // Integer.MIN_VALUE, Long.MIN_VALUE를 -1로 나누는 경우는 오버플로우가 발생하고, 각각 Integer.MIN_VALUE, Long.MIN_VALUE를 반환한다 floorMod(x, y) // x - (floorDiv(x, y) * y)를 반환한다. 부호는 y와 같다 fma(a, b, c) // a * b + c에 가장 가까운 float, double을 반환

공유 변수 관련

ClassValue<T>

임의 타입에 대하여, 필요할 때에 연산된 값을 가져오도록 지원. 해당 값은 해당 타입에 대해 일관성을 갖는다

↓ java

protected abstract T computeValue(Class<?> type) // type에 대하여, 최초 get 메서드 호출 시 한 번만 호출되며, 이후 remove 메서드 호출이 없으면 더 이상 불리지 않는다 T get(Class<?> type) // 값이 계산되지 않은 상태에서 여러 스레드들이 경합을 벌일 경우, 임의 스레드의 결과값을 모두에 반환한다 void remove(Class<?> type) // 다음 get 호출 시 값을 새로 계산하도록 한다

ThreadLocal<T>

스레드 단위의 지역 변수를 제공한다. 호출 지점과 관계없이 한 스레드 내부에서 변수를 공유한다

↓ java

protected T initialValue() // 초기값이 설정되지 않은 상태에서 최초 get() 호출에 의해 불린다. remove() 호출 후의 get() 요청으로 다시 불린다 static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) // supplier로 초기값이 설정되는 ThreadLocal 반환

InheritableThreadLocal<T>

ThreadLocal에 상속성을 부여. 자식 스레드는 부모의 thread-local 변수들을 초기값으로 상속받고 시작한다. childValue 메서드를 재정의함으로써 부모의 값과 다르게 설정할 수도 있다

타입 관련

  • 각 래퍼 클래스의 TYPE 필드는 기본 타입 클래스 인스턴스를 가리킨다
  • e.g. Boolean.TYPE == boolean.class

  • 각 래퍼 클래스의 valueOf() 함수는 기본 타입에 대해 래핑을 수행하며, 일부는 캐싱을 이용해 빠르게 수행한다
  • 숫자 래퍼 클래스들은 MIN_VALUE, MAX_VALUE, SIZE(비트 크기), BYTES(바이트 크기) 필드를 갖는다
  • byte[] -> 다른 수 타입 변환을 원하는 경우, ByteBuffer 이용
  • ↓ java

    ByteBuffer.wrap(new byte[] { 1, 1, 1, 1 }).getInt()
  • Boolean, Integer, Long은 시스템 속성 관련 유틸리티를 제공한다
  • ↓ java

    static X getX(String name, X defaultVal)
  • 몇몇 래퍼 클래스들은 아래와 같은 비트 함수를 제공한다
  • ↓ java

    static int highestOneBit(X i) // + lowestOneBit static int numberOfLeadingZeros(X i) // + numberOfTrailingZeros static int bitCount(X i) static X rotateLeft(X i, int distance) // + rotateRight static X reverse(X i) static X reverseBytes(X i) // 바이트 단위로 뒤집기
  • 정수 래퍼 클래스들은 아래와 같은 String 파싱을 제공한다
  • ↓ java

    static Z parseZ(String s, int radix) static Z valueOf(String s, int radix) // 예외 // s가 null이거나 길이가 0 // s에 radix진수가 아닌 문자가 포함(단, s가 2글자 이상일 때 첫 '-', '+'는 가능) // radix가 [Character.MIN_RADIX, Character.MAX_RADIX] 범위를 벗어날 때 // 값이 Z를 벗어날 때 static Z decode(String nm) // 다음 문법으로 표현된 10진수, 16진수, 8진수를 parseZ()를 이용해 디코딩한다. 공백 비허용 // (Sign?)(10진수) // (Sign?)(0x | 0X | #)(16진수) // (Sign?)0(8진수) // Sign: '-', '+'
  • 정수 래퍼 클래스들은 몇몇 unsigned 함수를 제공한다
  • ↓ java

    static int compareUnsigned(Z x, Z y) static Z divideUnsigned(Z dividend, Z divisor) static Z parseUnsigned(...) static Z remainderUnsigned(Z dividend, Z divisor) static int toUnsignedInt(Z x) static long toUnsignedLong(Z x) static String toUnsignedString(Z i)

CharSequence

  • 일련의 char 값들을 표현
  • equals(), hashCode()에 대한 규약이 없어, set이나 map의 키로 이용하기에 부적절하다

↓ java

static int compare(CharSequence cs1, CharSequence cs2) // 사전순으로 비교 default IntStream chars() // char들을 int로 0패딩하여 스트림 생성. 두 char로 쪼개진 유니코드 보충 평면의 문자를 하나로 합치진 않는다 default IntStream codePoints() // 유니코드 값들을 스트림으로 생성. 보충 평면의 문자는 Character.toCodePoint 메서드를 통해 하나의 int 값으로 형성

Character

  1. 문자 집합(소문자, 숫자 등) 정의, 변환 기능을 제공한다
  2. 유니코드 표준을 따른다
    • 유효한 범위는 U+0000(MIN_CODE_POINT)부터 U+10FFFF(MAX_CODE_POINT)까지(== Unicode scalar value)
      1. [U+0000, U+FFFF] == 기본 문자 평면(BMP; Basic Multilingual Plane)
      2. [U+10000 == MIN_SUPPLEMENTARY_CODE_POINT, ~) == 보충 문자 평면(supplementary characters)
    • 자바 플랫폼은 보충 평면의 문자들은 2개의 char의 쌍으로 표현한다
    • 이때 첫번째 char는 high-surrogate([MIN_HIGH_SURROGATE, MAX_HIGH_SURROGATE]), 두번째 char는 low-surrogate([MIN_LOW_SURROGATE, MAX_LOW_SURROGATE]) 범위 안의 값이다

    • 하위 21개 비트를 이용하여 int 하나로 모든 유니코드 code point를 표현할 수 있다
  3. int를 받는 메서드는 모든 유니코드를 처리할 수 있지만, char만을 받는 메서드는 보충 평면 문자를 처리하지 못한다

↓ java

static String getName(int codePoint) // 이름 반환 : Character.UnicodeBlock.of(codePoint).toString().replace('_', ' ') + " " + Integer.toHexString(codePoint).toUpperCase(Locale.ROOT); // 정의되어 있지 않으면 null static int codePointOf(String name) // 정의되어 있지 않으면 예외 static boolean isValidCodePoint(int codePoint) // + isBmpCodePoint, isSupplementaryCodePoint, isHighSurrogate, isLowSurrogate static int getType(int codePoint) static byte getDirectionality(char ch) // 문자 표시 순서 : DIRECTIONALITY_UNDEFINED, DIRECTIONALITY_LEFT_TO_RIGHT 등 static boolean isMirrored(char ch) // 좌우 대칭되는 문자가 존재하는지 여부 static boolean isDigit(char ch) // getType(ch) == DECIMAL_DIGIT_NUMBER static boolean isLetter(char ch) // getType(ch) == *_LETTER, isLetterOrDigit static boolean isAlphabetic(int codePoint) // UPPERCASE_LETTER, LOWERCASE_LETTER, TITLECASE_LETTER, MODIFIER_LETTER, OTHER_LETTER, LETTER_NUMBER, 및 기타 알파벳 문자인지 여부 static boolean isSpaceChar(char ch) // getType(ch) == *_SEPARATOR static boolean isWhitespace(char ch) // 공백 문자 '\t', '\n', 'u000B', '\f', '\r', '\u001C', '\u001D', '\u001E', '\u001F' // 단, non-breaking space('\u00A0', '\u2007', '\u202F') 제외 static int charCount(int codePoint) // 표현에 필요한 char 수(1 or 2) static char[] toChars(int codePoint) static String toString(int codePoint) static int toCodePoint(char high, char low) static int codePointAt(CharSequence seq, int index) // + codePointBefore, highSurrogate, lowSurrogate static int codePointCount(CharSequence seq, int beginIndex, int endIndex) // [beginIndex, endIndex) 사이의 유니코드 문자 수 반환 static int offsetByCodePoints(CharSequence seq, int index, int codePointOffset) // 지정된 index로부터 offset 개수만큼 유니코드를 건너뛴 위치. +일 경우 index 포함, -인 경우 index 미포함(예시 코드 참고) static int toLowerCase(int codePoint) // + toUpperCase, toTitleCase // isLowerCase(toLowerCase(x))가 항상 true는 아니다 static int digit(int codePoint, int radix) static char forDigit(int digit, int radix) static int getNumericValue(int codePoint)

Double

↓ java

public static final double POSITIVE_INFINITY // Double.longBitsToDouble(0x7ff0000000000000L) public static final double NEGATIVE_INFINITY // Double.longBitsToDouble(0xfff0000000000000L) public static final double NaN // Double.longBitsToDouble(0x7ff8000000000000L) public static final double MAX_VALUE // Double.longBitsToDouble(0x7fefffffffffffffL), 0x1.fffffffffffffP+1023 public static final double MIN_NORMAL // Double.longBitsToDouble(0x0010000000000000L), 0x1.0p-1022 // 진수가 1 이상인 가장 작은 양수 표현 public static final double MIN_VALUE // Double.longBitsToDouble(0x1L), 0x0.0000000000001P-1022 // 가장 작은 양수 표현 static String toHexString(double d) static long doubleToLongBits(double value) // double 표현 그대로 long으로 전환. 63번 비트는 부호, 62-52번 비트는 지수, 51-0번 비트는 진수 static long doubleToRawLongBits(double value) // NaN의 경우 각각의 NaN에 대응하는 값으로 반환 static double longBitsToDouble(long bits) // NaN : [0x7ff0000000000001L, 0x7fffffffffffffffL] or [0xfff0000000000001L, 0xffffffffffffffffL] int compareTo(Double anotherDouble) // Double.NaN > Double.POSITIVE_INFINITY // 0.0d > -0.0d

Integer

↓ java

static String toString(int i, int radix) // + toUnsignedString, toBinaryString, toOctalString, toHexString

String

로캐일을 고려한 문자열 비교는 Collator 클래스를 이용하면 된다

↓ java

static final Comparator<String> CASE_INSENSITIVE_ORDER // 대소문자 구분없는 비교자. 직렬화 가능 static String format(String format, Object... args) String formatted​(Object... args) static String valueOf(Object obj) boolean isEmpty() // 길이가 0인지 여부 boolean isBlank() // 비거나 공백 문자로만 이루어졌는지 여부 byte[] getBytes(Charset charset) // 문자셋이 지정되지 않은 경우, 플랫폼 기본 문자셋을 이용한다. 기본 문자셋을 변경하려면 JVM 옵션을 조정하면 된다 // 비교 boolean contentEquals(StringBuffer sb) boolean equalsIgnoreCase(String anotherString) int compareToIgnoreCase(String str) boolean regionMatches(int tooffset, String other, int ooffset, int len) // 부분 문자열이 일치하는지 여부 반환. t(his's)offset, o(ther's)offset boolean startsWith(String prefix, int toffset) boolean endsWith(String suffix) // 검색 int indexOf(String str, int fromIndex) // + lastIndexOf boolean matches(String regex) // == Pattern.matches(regex, str) boolean contains(CharSequence s) String replaceAll(String regex, String replacement) // + replaceFirst String replace(CharSequence target, CharSequence replacement) String[] split(String regex, int limit) // limit이 음수인 경우, 제한 없이 분리. 0인 경우 빈 문자열로 끝나지 않음 static String join(CharSequence delimiter, CharSequence... elements) String trim() // 시작과 끝의 공백(<= U+0020) 제거 String strip() // + stripLeading, stripTrailing. 공백 제거 Stream<String> lines() // 줄 끝(\n, \r, \r\n) 기준으로 분리 String indent(int n) // 각 줄이 n개의 공백으로 시작하도록 조정하고, 줄 끝을 \n로 정규화한다. n이 음수인 경우, 최대 n개의 앞선 공백을 제거한다 String stripIndent() // 모든 줄이 공유하는 불필요한 들여쓰기 제거 <R> R transform(Function<? super String, ? extends R> f) String repeat(int count)

StringBuffer

스레드-안전한 변경 가능한 문자열

↓ java

void trimToSize() // 버퍼 크기를 줄여 문자열 크기에 맞춘다 void setLength(int newLength) // 새로운 크기의 문자열에 기존 문자열을 복사. 남는 부분은 '\u0000'(null)로 채워진다 void ensureCapacity(int minimumCapacity) StringBuffer reverse()

StringBuilder

StringBuffer의 비동기화 버전

클래스 관련

Class<T>

↓ java

// ClassLoader 관련 ClassLoader getClassLoader() InputStream getResourceAsStream(String name) URL getResource(String name) static Class<?> forName(String name, boolean initialize, ClassLoader loader) // 타입 관련 T cast(Object obj) // obj를 호출한 Class 객체와 같은 타입으로 변환 boolean isInstance(Object obj) // instanceof 연산자의 동적인 형태. 원시타입 클래스 객체는 false만 반환한다 boolean isAssignableFrom(Class<?> cls) // cls 타입 객체를 현재 클래스의 참조 변수로 참조할 수 있는지 여부 반환 boolean isInterface() // + isArray, isPrimitive, isAnnotation, isEnum, isAnonymousClass, isLocalClass, isMemberClass, isRecord // wrapper 클래스는 원시타입이 아님에 유의 : Integer.class != Integer.TYPE == int.class // 클래스 이름 관련 String toGenericString() // 접근한정자 및 타입 포함하여 반환 String getName() // 배열의 경우 차원마다 '['를 붙이며, 배열 원소 타입을 아래와 같이 인코딩한다 // boolean : Z, byte : B, char : C, class : L{className};, double : D, float : F, int : I, long : J, short : S String getSimpleName() // 익명 클래스면 빈 문자열 반환 String getCanonicalName() // Local class, 익명 클래스, 또는 이들의 배열은 canonical name이 없어 null을 반환한다 // 리플렉션 관련 Class<?>[] getClasses() // public 멤버로 정의된 클래스, 인터페이스 Class 객체 배열 반환 // + getFields, getMethods, getConstructors Class<?>[] getDeclaredClasses() // 상속된 것을 제외하고, 호출하는 클래스 내부에 정의된 public, protected, default, private 클래스와 인터페이스들을 반환한다 // + getDeclaredFields, getDeclaredMethods, getDeclaredConstructors Class<?> getComponentType() // 배열 원소 타입 클래스 객체 반환. 배열이 아닌 경우 null 반환 Method getEnclosingMethod() // 이 클래스가 메서드 내부에서 정의된 경우, 해당 메서드를 반환한다 // + getEnclosingConstructor, getDeclaringClass, getEnclosingClass <A extends Annotation> A getAnnotation​(Class<A> annotationClass) boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) // record 관련 RecordComponent[] getRecordComponents()

Nest

  • Nest는 같은 런타임 패키지 안의, private member에 접근 가능한 클래스와 인터페이스의 집합
  • Nest에 속한 클래스, 인터페이스를 nestmate라 부르고, 하나의 nest에서 하나의 nestmate는 host 역할을 하고 나머지 nestmate 목록을 갖는다
  • ↓ java

    Class<?> getNestHost() Class<?>[] getNestMembers() boolean isNestmateOf​(Class<?> c)

ClassLoader

  1. 전형적으로, 로드할 클래스 이름을 파일명으로 변환하여 ".class"파일을 읽어온다
  2. 모든 Class 객체들은 ClassLoader에 대한 참조를 갖고 있다
  3. 배열의 경우 런타임에 Class 객체가 생성되며, 이때 Class.getClassLoader()는 원소의 것과 동일하다
  4. 클래스를 로드하는 것 외에, 자원(.class 파일, 구성 파일, 이미지 등)을 배치하는 책임도 진다
  5. Delegation model : ClassLoader 객체들은 각기 parent class loader를 갖는다. 클래스나 자원을 찾기 전에 parent를 먼저 조사하게 된다
  6. 동시 로딩을 지원하는 parallel capable class loader들은 클래스 초기화 시 registerAsParallelCapable()를 통해 등록해야 한다. ClassLoader 클래스는 기본적으로 등록되나, 서브클래스들도 자신을 등록해야 한다
  7. 계층구조가 약한 delegation model의 경우 클래스 로더들이 parallel capable하지 않으면 deadlock 발생 가능성이 있다
  8. Run-time Built-in Class Loaders
    • Bootstrap class loader : JVM 내장 클래스 로더. 보통 null이며, parent가 없다
    • Platform class loader : Java SE APIs, JDK-specific run-time classes
    • System class loader, a.k.a Application class loader : Used to define classes on the application class path, module path, and JDK-specific tools
  9. 파일이 아닌 네트워크 같은 다른 소스로부터 클래스를 로드할 경우, defineClass()를 통해 Class 객체를 얻고 Constructor.newInstance()를 통해 클래스 객체를 생성하면 된다
  10. 네트워크 클래스 로더는 findClass(), loadClassData() 메서드를 반드시 작성해야 한다
  11. ↓ java

    public Class findClass(String name) { byte[] b = loadClassData(name); return defineClass(name, b, 0, b.length); } private byte[] loadClassData(String name) { /**/ }
  12. Binary names
  13. ClassLoader 메서드에 전달하는 String 타입 클래스 이름은 아래와 같은 형식을 따라야 한다

    • "java.lang.String"
    • "javax.swing.JSpinner$DefaultEditor"
    • "java.security.KeyStore$Builder$FileBuilder$1"
    • "java.net.URLClassLoader$3$1"

↓ java

static ClassLoader getPlatformClassLoader() static ClassLoader getSystemClassLoader() // 시스템 클래스 로더를 반환하며, 이는 새롭게 정의되는 클래스 로더들의 default delegation parent다 Class<?> loadClass(String name) // == loadClass(name, false) protected Class<?> loadClass(String name, boolean resolve) // 1. findLoadedClass(String)로 이미 로드됐나 확인 // 없으면 : parent 혹은 VM의 클래스 로더의 loadClass를 호출 // 없으면 : findClass(String) 호출 // 2. 위를 통해 클래스를 찾았고, resolve가 true면 resolveClass(Class) 호출 // 3. ClassLoader의 서브클래스들은 이 메서드가 아닌 findClass(String)을 재정의하면 된다 // 4. 재정의되지 않은 이상, getClassLoadingLock()을 통해 메서드는 동기화된다 protected final void resolveClass(Class<?> c) // 클래스를 링크(초기화)한다 // 리소스 관련 ? *Resource*(String name) // name은 '/'으로 구분된 경로

Module

이름 있는 모듈에 속하지 않은 모든 타입은 각 클래스 로더의 익명 모듈에 속한다

↓ java

InputStream getResourceAsStream(String name) // 해당 모듈의 리소스를 스트림으로 반환. name은 '/'으로 구분된 경로

프로그램 실행 단위

Thread

  1. 스레드는 실행 우선순위를 가지며, 그 초깃값은 스레드를 생성한 스레드의 것과 같다. 데몬 스레드로부터 생성된 스레드도 데몬 스레드다
  2. JVM이 시작되면 하나의 non-daemon 스레드가 존재하며, 전형적으로 main 메서드를 호출한다. JVM은 다음의 상황 중 하나라도 일어나기 전까지 실행을 계속한다
    • Runtime 클래스의 exit 메서드 호출, 또는 SecurityManager의 exit 허용
    • 모든 데몬 스레드가 아닌 스레드들의 종료 : run 메서드의 반환이든 예외 발생이든 관계없이

↓ java

public static final int MIN_PRIORITY public static final int NORM_PRIORITY public static final int MAX_PRIORITY final void setDaemon(boolean on) // 스레드를 daemon 또는 user 스레드로 변경. 스레드가 시작되기 전에 호출돼야한다 // user 스레드가 하나도 없으면 프로그램은 종료된다 void start() // JVM이 run() 호출. 스레드를 재시작하는 것은 허용되지 않는다 void run() // 관련된 Runnable의 run() 호출 void interrupt() // 1. checkAccess()가 호출된다. wait, join, sleep으로 블록된 경우 인터럽트 상태가 초기화되고, InterruptedException 발생 // 2. InterruptibleChannel로 I/O 작업 중 블록된 경우, 인터럽트 상태가 설정되고 채널은 닫힌다. ClosedByInterruptException 발생 // 3. Selector에서 블록된 경우, 인터럽트 상태가 설정되고 selection 연산에서 즉시 반환된다. 그 외의 경우 인터럽트 상태가 설정된다 static Thread currentThread() ClassLoader getContextClassLoader() long getId() Thread.State getState() static boolean interrupted() // 현재 스레드가 인터럽드됐는지 여부. 스레드의 인터럽트 상태는 이 메서드로 인해 초기화된다 boolean isInterrupted() // 스레드의 인터럽트 상태를 변경하지 않고 반환한다 final boolean isAlive() final void join(long millis) // 이 스레드가 중지되기까지 일시 대기. 0이면 무기한 대기. 지정 되지 않은 경우 0 static void dumpStack() // 현재 스레드의 스택 추적을 표준 에러 출력 final void checkAccess() // 현재 스레드가 이 스레드를 변경할 수 없으면 SecurityException 발생 static boolean holdsLock(Object obj) // 특정 객체를 lock으로 갖는지 확인 static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

static void onSpinWait()

Spin-wait 루프에서 조건이 충족되어 루프를 벗어나기를 기다린다

↓ java

class EventHandler { volatile boolean eventNotificationNotReceived; void waitForEventAndHandleIt() { while ( eventNotificationNotReceived ) { java.lang.Thread.onSpinWait(); } readAndProcessEvent(); } void readAndProcessEvent() { // Read event from some source and process it ... } }

Thread.State

NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED

Thread.UncaughtExceptionHandler

  1. 처리되지 않은 예외로 인해 스레드가 종료되는 상황을 대비한 핸들러. 그러한 상황에서, 먼저 Thread.getUncaughtExceptionHandler()를 통해 얻은 핸들러에 해당 스레드와 예외 객체를 전달한다
  2. 만일 스레드에 핸드러가 설정되지 않은 경우, ThreadGroup의 핸들러를 이용하며, ThreadGroup에도 없는 경우 default 핸들러를 이용할 수 있다

Process

ProcessBuilder.start, Runtime.exec으로 시작된 native process들에 대한 제어 제공

↓ java

abstract OutputStream getOutputStream() // + getInputStream, getErrorStream abstract int waitFor() // 현재 스레드가 이 프로세스의 종료를 기다린다. 프로세스의 종료 값을 반환 boolean waitFor(long timeout, TimeUnit unit) // 시간 내에 프로세스가 종료되었다면 true 반환 abstract int exitValue() abstract void destroy() // 정상 종료 Process destroyForcibly() // 강제, 즉시 종료 boolean isAlive() long pid() boolean supportsNormalTermination() CompletableFuture<Process> onExit() ProcessHandle toHandle() ProcessHandle.Info info() Stream<ProcessHandle> children() Stream<ProcessHandle> descendants()

ProcessBuilder

이 클래스는 스레드-안전하지 않다

↓ java

ProcessBuilder command(String... command) ProcessBuilder directory(File directory) ProcessBuilder redirectInput(ProcessBuilder.Redirect source) // + redirectOutput, redirectError ProcessBuilder inheritIO() ProcessBuilder redirectErrorStream(boolean redirectErrorStream) // true면 서브프로세스들의 에러 출력이 표준 출력으로 나온다 Process start() static List<Process> startPipeline(List<ProcessBuilder> builders) // 프로세스들의 표준 출력을 다음 프로세스의 표준 입력으로 연결한다

ProcessBuilder.Redirect

서브프로세스의 입력 소스 또는 출력 방향을 표현한다

↓ java

public static final ProcessBuilder.Redirect PIPE // 현재 프로세스와 파이프로 연결 public static final ProcessBuilder.Redirect INHERIT // 현재 프로세스의 것과 동일 public static final ProcessBuilder.Redirect DISCARD // 출력 버림 static ProcessBuilder.Redirect from(File file) static ProcessBuilder.Redirect to(File file) // file의 이전 내용은 새로운 쓰기 작업에 의해 버려진다 static ProcessBuilder.Redirect appendTo(File file)
ProcessBuilder.Redirect.Type

↓ java

APPEND, // Redirect.appendTo(File) INHERIT, PIPE, READ, // Redirect.from(File) WRITE // Redirect.to(File)

Runtime

모든 Java 애플리케이션은 하나의 Runtime 인스턴스를 가진다

↓ java

static Runtime getRuntime() void exit(int status) // 현재 실행중인 JVM을 종료 void addShutdownHook(Thread hook) // + removeShutdownHook // JVM이 종료 절차에 진입하면 등록된 모든 hook를 실행 void halt(int status) // 강제종료 Process exec(String[] cmdarray, String[] envp, File dir) int availableProcessors() long freeMemory() // + totalMemory, maxMemory void gc() void runFinalization() // 소멸 대기중인 모든 객체 소멸

System

↓ java

public static final InputStream in // + out, err static void setIn(InputStream in) // + setOut, setErr static long currentTimeMillis() // + nanoTime static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) static int identityHashCode(Object x) static String lineSeparator() static void setProperties(Properties props) // getProperties static String setProperty(String key, String value) static String clearProperty(String key) static String getenv(String name) // 환경변수 static void exit(int status)

StackWalker

현재 스레드의 StackFrame에 대한 스트림을 열고 특정 작업을 수행한다. 스트림은 실행 지점인 맨 위 frame부터 아래로 내려가면서 작업한다

↓ java

static StackWalker getInstance(...) // 기본 설정 : 숨겨진 프레임 생략. 클래스 정보 미포함 <T> T walk(Function<? super Stream<StackWalker.StackFrame>, ? // 예. 현재 스레드의 상위 10개 스택 프레임 가져오기 StackWalker.getInstance().walk(s -> s.limit(10).collect(Collectors.toList())); void forEach(Consumer< super StackWalker.StackFrame> action) Class<&?> getCallerClass() // 이 메서드를 호출하는 호출자의 클래스 객체를 반환 // Util::getResourceBundle 메서드는 이 메서드를 통해 얻은 호출자의 클래스로부터 클래스 로더를 얻고, 클래스 로더를 통해 리소스를 로드한다

StackWalker.Option

↓ java

RETAIN_CLASS_REFERENCE // StackFrame에 클래스 정보 유지 SHOW_HIDDEN_FRAMES // 숨겨진 프레임 표시 SHOW_REFLECT_FRAMES // reflection 프레임 표시

java.lang.annotation

Annotation

이 인터페이스를 구현하는 것으로 새로운 애너테이션을 정의할 순 없다

ElementType

애너테이션이 적용되는 요소를 표현한다

↓ java

TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VALIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, MODULE

RetentionPolicy

애너테이션 유지 정책

↓ java

SOURCE // 컴파일러가 제거 CLASS // 컴파일러가 클래스 파일에 기록(default) RUNTIME // 클래스 파일에 기록하고 JVM 런타임에도 유지. 따라서 리플렉션 가능

@Documented

@Documented가 다른 애너테이션 타입 A에 존재하면, @A로 꾸며진 요소의 공개적인 서명으로 인식하여 JavaDoc에 포함된다

@Inherited

Superclass의 애너테이션을 상속함을 표시. 클래스에만 유효한 애너테이션이다

@Repeatable

애너테이션을 반복적으로 정의할 수 있음을 표현 repeating.html

@Retention

애너테이션을 얼마나 유지할 지 표현. value ← RetentionPolicy

@Target

애너테이션을 적용할 요소들을 표현한다. 여러 개(또는 0개)일 경우 배열 리터럴 표기 {}를 이용한다. value ← ElementType[]

java.lang.ref

Package Summary

  1. java.net 포스트NAVER 개발 포스트
  2. 다른 객체(referent)를 참조하는 reference object를 이용해 GC 절차 일부와 상호작용할 수 있다
  3. 3단계의 참조 레벨을 제공한다 : Soft > Weak > Phantom
    1. Strongly reachable
      • Reference object 없이 객체에 직접 접근 가능한 스레드가 존재
      • e.g. 객체를 생성한 스레드, 객체를 매개변수로 받아 실행 중인 스레드 등

    2. Softly reachable
      • Not strongly reachable && Soft reference object가 객체를 참조 중
      • 마지막으로 strongly reachable한 이후 기간, 여유 힙 크기, JVM 옵션(-XX:SoftRefLRUPolicyMSPerMB)에 따라 GC 여부가 결정된다
      • ReferenceQueue를 지정한 경우, GC 대상으로 판별된 즉시(약간의 지연은 있을 수 있다) 등록된다
    3. Weakly reachable
      • Not strongly reachable && Not softly reachable && Weak reference object가 객체를 참조 중
      • Referent는 GC 대상이며, 따라서 get()은 null을 반환할 수 있다
      • ReferenceQueue를 지정한 경우, GC 대상으로 판별된 즉시(약간의 지연은 있을 수 있다) 등록된다
    4. Phantom reachable
      • Not strongly reachable && Not softly reachable && Not weakly reachable && 객체는 소멸(finalize)됐지만 Phantom reference object가 참조 중
      • Finalization 이후 ReferenceQueue에 등록된다
      • 객체 소멸 감지를 위해 존재하므로, get()은 항상 null을 반환한다
      • ReferenceQueue에서 꺼낸 뒤, 메모리 해제를 위해 clear()를 호출해야 한다
    5. Unreachable
    6. 참조 불가능하며, 따라서 GC 대상이 된다

Cleaner

  1. 객체 참조와 관련 정리 작업을 관리한다
  2. 객체가 phantom reachable 상태로 변했음을 통지받으면 정리 작업이 실행된다. 참조 레벨의 변경을 통지받기 위해 PhantomReference와 ReferenceQueue를 이용한다

  3. 객체 참조와 정리 작업을 등록하면 Cleanable 인스턴스가 반환된다
  4. 가장 효과적인 사용법은 객체의 close() 메서드나, 객체가 필요없는 시점에 명시적으로 clean()을 호출하는 것

  5. 등록하는 객체를 객체 정리 작업이 참조하면 안 된다
  6. 참조하는 경우, 객체는 Phantom reachable 레벨에 도달할 수 없고, 따라서 자동으로 정리 작업이 호출될 수 없다

  7. 정리 작업은 Runnable이며, 실행 중 발생하는 모든 예외는 무시된다. 발생한 예외는 Cleaner와 다른 정리 작업에 영향을 미치지 않는다 Cleaner 인스턴스와 관계된 스레드가 정리 작업을 실행하며, 모든 정리 작업이 실행된 후엔 Cleaner 인스턴스가 GC에 의해 정리된다
  8. System.exit 도중의 정리 작업의 실행은 정의되지 않는다

↓ java

static Cleaner create() Cleaner.Cleanable register(Object obj, Runnable action)

Cleaner.Cleanable

↓ java

void clean() // cleanable을 등록 취소하고 정리 작업을 실행한다. 반복 호출되도 정리 작업은 최대 1번만 실행된다

ReferenceQueue<T>

참조 큐. 참조 레벨 변화를 감지하면 GC가 reference object를 큐에 추가한다

↓ java

Reference<? // reference object가 즉시 사용 가능하면 큐에서 제거하고 반환한다. 그 외의 경우 즉시 null을 반환한다 Reference<? // 다음 reference object를 규에서 제거하고 반환한다. 그 다음 reference object가 사용 가능해질 때까지 최대 timeout 만큼 대기한다

Reference<T>

GC와 상호작용하기 위한 메서드들을 정의한다. 이 클래스를 직접 상속하지 않아야 한다

↓ java

static void reachabilityFence​(Object ref) // ref가 가리키는 객체를 strongly reachable하게 고정하여 // 적어도 이 메서드 호출이 끝날 때 까지는 GC 대상이 아니게 한다 T get() // referent를 반환한다(즉, hard reference) final boolean refersTo(T obj) // referent == obj ? void clear() boolean enqueue() // clear() 후 지정된 큐에 넣는다 class SoftReference<T> extends Reference<T> class WeakReference<T> extends Reference<T> class PhantomReference<T> extends Reference<T>

java.lang.reflect

자바 제네릭 제약사항

  1. 자바의 제네릭은 컴파일 과정에서 모두 Object 또는 바운드된 클래스로 교체(type erasure)된다
  2. 따라서 List<T> 참조 변수만 가지고 T가 어떤 타입인지 런타임에 알아내는 방법은 없다
  3. 다만, 원소가 존재한다면 instanceof, Class::isInstanse, Class::isAssignableFrom을 이용한 판별은 가능하다

  4. 따라서 제네릭 타입에 대한 직접적인 연산은 모두 무효하다
  5. 제네릭에 대한 익명 클래스는 정의에 사용된 타입 인자를 알 수 있다
  6. ↓ java

    (ParameterizedType) new ArrayList<String>().getClass().getGenericSuperclass(); // java.util.AbstractList<E> ((ParameterizedType) new ArrayList<String>().getClass().getGenericSuperclass()).getActualTypeArguments()[0]; // E (ParameterizedType) new ArrayList<String>() {}.getClass().getGenericSuperclass(); // java.util.ArrayList<java.lang.String> ((ParameterizedType) new ArrayList<String>() {}.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; // class java.lang.String

Modifier

↓ java

public static final int PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, SYNCHRONIZED, VOLATILE, TRANSIENT, NATIVE, INTERFACE, ABSTRACT, STRICT static int classModifiers() // 사용할 수 있는 제한자들을 OR하여 반환 // + interfaceModifiers, constructorModifiers, ...

지원 타입 종류

↓ java

interface Type // 모든 타입의 공통 super interface interface ParameterizedType extends Type // Collection<String>처럼 파라미터화된 타입을 표현 interface GenericArrayType extends Type // 원소 타입이 parameterized type 또는 type 변수인 배열 타입을 표현 interface WildcardType extends Type // ?, ? extends Number, ? super Integer와 같은 와일드카드 타입을 표현 interface AnnotatedElement // 애너테이트된 요소를 표현 interface AnnotatedType extends AnnotatedElement { default AnnotatedType getAnnotatedOwnerType(); // 이 타입을 멤버로 갖는, 애너테이트된 타입 반환. // e.g. 이 타입이 @XXX O<T>.I<S>라면, @XXX O<T>를 반환 // null이 반환되는 경우 ↓ // 타입이 top-level이거나 local 클래스, 익명 클래스, 기본 자료형, void인 경우 // 타입이 AnnotatedArrayType, AnnotatedTypeVariable, AnnotatedWildcardType의 인스턴스인 경우 Type getType(); // 이 애너테이트된 타입의 기저 타입 } interface AnnotatedArrayType extends AnnotatedType // 원소가 애너테이트된 배열을 표현 interface AnnotatedParameterizedType extends AnnotatedType // 타입 인자들이 애너테이트된 parameterized type을 표현 interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement // 타입 변수에 관한 공통 superinterface interface GenericDeclaration extends AnnotatedElement // 모든 타입 변수 정의들에 대한 공통 인터페이스 interface AnnotatedTypeVariable extends AnnotatedType // 애너테이트된 바운드를 가진 타입 변수를 표현 interface AnnotatedWildcardType extends AnnotatedType // 애너테이트된 upper 또는 lower 바운드들에 대한 와일드카드 타입을 표현

클래스 멤버 관련

Member

하나의 멤버(필드나 메서드) 또는 생성자를 가리킨다

↓ java

boolean isSynthetic() // 컴파일러에 의해 만들어진 멤버인지 여부

AccessibleObject

Field, Method, Constructor의 base 클래스. 리플렉트된 객체를 사용하기 전에 suppressing check 표시한다

↓ java

void setAccessible(boolean flag) static void setAccessible(AccessibleObject[] array, boolean flag) // 배열의 각 원소들을 setAccessible(boolean)으로 설정할 수 있을 때, 한번에 하기 위한 메서드 final boolean canAccess(Object obj) final boolean trySetAccessible() // accessible flag 값을 반환한다. 실패할 경우 예외를 발생하지 않고 false를 반환

Field

↓ java

boolean isEnumConstant() void set(Object obj, Object value) // + get, setBoolean, getBoolean, ...

Executable

Method, Constructor의 공통 기능

↓ java

abstract Class<?>[] getParameterTypes() Parameter[] getParameters()

Method

↓ java

Class<&?> getReturnType() Object invoke(Object obj, Object... args)

Constructor<T>

↓ java

T newInstance(Object... initargs)

Parameter

메서드 인자에 관한 정보

InvocationHandler

Proxy 인스턴스의 invocation handler에서 구현하는 인터페이스

↓ java

Object invoke(Object proxy, Method method, Object[] args)

Proxy

  • Proxy는 인터페이스 익명 객체처럼 행동하면서 사용자 정의 메서드를 호출할 수 있는 객체를 생성하는 static 메서드를 제공한다
  • ↓ java

    // 예. 인터페이스 Foo의 프록시 인스턴스 생성 InvocationHandler handler = new MyInvocationHandler(...); var f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class }, handler);
  • 프록시 클래스 속성
  • "$Proxy"로 이름이 시작. final and non-abstract. java.lang.reflect.Proxy를 상속. 생성시 주어진 인터페이스들을 차례대로 구현. ProtectionDomain은 bootstrap 클래스 로더가 로드한 시스템 클래스들과 동일

↓ java

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) static boolean isProxyClass(Class<?> cl) static InvocationHandler getInvocationHandler(Object proxy)

java.math

BigDecimal

임의 정밀도의 변경할 수 없는 10진 정수와 32비트 정수인 지수로 십진수를 표현한다

↓ java

public static final BigDecimal ZERO, ONE, TEN public BigDecimal(String val) // val ::= (부호)?(진수부)(지수부)? // 진수부 ::= 정수부.(소수부) or .소수부 or 정수부 // 지수부 ::= (e|E)정수 BigDecimal add(BigDecimal augend) // + subtract, multiply, divide BigDecimal divideToIntegralValue(BigDecimal divisor) // 몫 BigDecimal remainder(BigDecimal divisor) // 나머지 BigDecimal[] divideAndRemainder(BigDecimal divisor) // + sqrt, pow, abs, negate, scale, precision, unscaledValue, round, movePointRight, scaleByPowerOfTen, ...

BigInteger

변경할 수 없는 임의 길이의 정수. -2^(Integer.MAX_VALUE) ~ 2^(Integer.MAX_VALUE)

↓ java

public static final BigInteger ZERO, ONE, TWO, TEN public BigInteger(int signum, byte[] magnitude, int off, int len) public BigInteger(String val, int radix) public BigInteger(int numBits, Random rnd) : [0 ~ 2^numBits) 사이 난수 public BigInteger(int bitLength, int certainty, Random rnd) // rnd를 통해 난수를 생성하고, 특정 비트 길이의 양의 정수(아마도 소수) 반환. 소수일 확률은 (1 - 0.5^certainty) 초과 static BigInteger probablePrime(int bitLength, Random rnd) // 합성수일 가능성은 2^(-100)을 넘지 않는다 BigInteger nextProbablePrime() // 이 BigInteger보다 큰 첫 소수(아마도)를 반환한다. 합성수일 가능성은 2^(-100)을 넘지 않는다 // BigDecimal에는 없는 메서드 sqrtAndRemainder(), gcd(BigInteger), modPow(BigInteger, BigInteger), shiftLeft(int), and(BigInteger), testBit(int), setBit(n), flipBit(int)

MathContext

정밀도, 반올림 모드를 캡슐화한 변경 불가능한 객체

↓ java

public static final MathContext UNLIMITED // precision=0 && roundingMode=HALF_UP public static final MathContext DECIMAL32, DECIMAL64, DECIMAL128 // 각각 7/16/34digits && roundingMode=HALF_EVEN int getPrecision() RoundingMode getRoundingMode()

RoundingMode

  • CEILING, FLOOR, UP : 0에서 멀어지도록 선택
  • DOWN : 0에 가까워지도록 선택
  • HALF_UP, HALF_DOWN, HALF_EVEN : 가장 인접한 두 이웃들이 같은 거리에 있는 경우(.5인 경우), 각각 큰/작은/짝수 이웃을 선택
  • UNNECESSARY : 올림이나 내림이 필요없는 상태. 그 외엔 ArithmeticException 발생

java.net

Address

InetAddress

IP 주소를 표현하며, IPv4, IPv6 각각에 대응하는 서브 클래스가 있다. 서브 클래스를 직접 이용하는 일은 별로 없을 거라고 한다

↓ java

static InetAddress getLoopbackAddress() // 127.0.0.1(127.*.*.*) or ::1 static InetAddress getByAddress(byte[] addr) static InetAddress getByName(String host) static InetAddress[] getAllByName(String host) byte[] getAddress()

SocketAddress

프로토콜과 무관한 소켓 주소를 의미

InetSocketAddress

IP 소켓 주소[(IP 주소 or 호스트 이름) + 포트]를 표현

↓ java

public InetSocketAddress(int port) // port가 0이면 바인드시 자동 할당 public InetSocketAddress(InetAddress addr, int port) // addr이 null이면 와일드카드 할당 public InetSocketAddress(String hostname, int port)

InterfaceAddress

  1. IPv4 : IP 주소 + 서브넷 마스크 + 브로드캐스트 주소
  2. IPv6 : IP 주소 + network prefix length

Connection

URLConnection

    URL이 지정하는 원격지와의 연결을 정의하며, 일반적으로 아래 단계에 따라 사용된다

  1. openConnection 메서드를 통해 연결 객체 획득
  2. 구성 인자 및 요청 속성 설정
  3. setAllowUserInteraction, setDoInput, setDoOutput, setIfModifiedSince, setUseCaches

  4. connect 메서드로 연결 시도
  5. 연결 성공하면 헤더와 컨텐츠에 접근할 수 있다
  6. getContent, getHeaderField(getContentEncoding, getContentLength, getContentType, getDate, getExpiration, getLastModified), getInputStream, getOutputStream

HttpURLConnection

HttpURLConnection은 요청을 1회만 하지만, 기저 네트워크 연결은 다른 인스턴스가 공유할 수 있다

↓ java

public static final int HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, ... int getResponseCode()

URI

URI syntax and components

  1. syntax : [scheme:]scheme-specific-part[#fragment]
  2. Absolute URI : 스킴을 명시한 URI
  3. Relative URI : Not absolute URI
  4. Opaque URI : scheme-specific-part가 '/'로 시작하지 않는 absolute URI
  5. 예: "mailto:java-net@java.sun.com", "urn:isbn:096139210x"

  6. Hierarchical URI : scheme-specific-part가 '/'로 시작하는 absolute or relative URI
  7. [scheme:][//authority][path][?query][#fragment]
    예: "http://example.com/languages/java", "sample/a/index.html#28", "../../demo/b/index.html"

  8. Server-based authority : [user-info@]host[:port]
  9. Registry-based authority : not server-based authority

Operations on URI instances

  1. Normalization : "."과 ".."을 제거
  2. Resolution : 상대 URI와 base URI를 이용해 단일 URI를 찾는 작업
  3. Relativization : Resolution의 역
  4. 임의의 정규화된 두 URI u, v에 대하여, u.relativize(u.resolve(v)).equals(v)와 u.resolve(u.relativize(v)).equals(v)는 항상 성립한다

URL

인스턴스 생성 시, URI와 다르게, 정의된 scheme에 대한 핸들러를 찾기 때문에, 핸들러를 찾지 못하면 예외가 발생한다

↓ java

boolean sameFile(URL other) // fragment(#) 제외하고 같은 파일인지 여부 URI toURI() URLConnection openConnection() final InputStream openStream() // == openConnection().getInputStream() final Object getContent() // == openConnection().getContent()

URLClassLoader

URL을 이용한 클래스 로더를 제공한다

NetworkInterface

이름과 할당된 IP 주소들로 구성된 Network Interface 표현

↓ java

static Stream<NetworkInterface> networkInterfaces() Stream<InetAdress> inetAddresses() byte[] getHardwareAddress() // 보통 MAC 주소

java.nio

Buffer

  1. 버퍼는 유한 길이의 기본 자료형 원소 나열
    • Capacity : 저장하고 있는 원소들의 개수
    • Limit : 읽거나 쓸 수 없는 최초의 인덱스. 0보다 작거나 capacity보다 클 수 없다
    • Position : 다음에 읽거나 쓸 대상의 인덱스. 0보다 작거나 limit보다 클 수 없다
    • 0<=mark<=position<=limit<=capacity // 마킹은 지원하지 않을수도 있다
  2. get/put 연산의 Relative/Absolute 구분
    • Relative : 버퍼의 현재 position에 대한 연산
    • Absolute : 버퍼의 특정 위치를 지정한 연산
  3. Additional operations
    • clear() : 새로운 채널-읽기 또는 relative put 연산을 준비; limit<-capacity, position<-0
    • flip() : 새로운 채널-쓰기 또는 relative get 연산을 준비; limit<-position, position<-0
    • rewind() : 이미 읽은 것을 다시 읽도록; position<-0
    • slice() : 기존 버퍼의 부분 시퀀스 생성
    • duplicate() : 기존 버퍼의 얕은 복사본 생성

↓ java

abstract boolean hasArray() // 기저 배열의 존재 유무. true면 array()와 arrayOffset() 사용가능 abstract boolean isDirect() // Direct 버퍼(즉시 읽기/쓰기)인지 여부

ByteBuffer

  1. 다음 연산을 정의
    • 바이트 하나에 대한 absolute/relative get/put
    • 바이트 시퀀스에 대한 bulk get/put
    • 다른 원시 타입에 대한 absolute/relative get/put
    • 다른 원시 타입으로 읽기 가능한 view 버퍼 생성; asCharBuffer, ...
    • compact : 인덱스 [0, position) 사이의 데이터가 버려진다(Optional operation)
  2. Direct 버퍼
  3. 읽기/쓰기 연산이 직접적으로 이루어지며, 별개의 복사본을 이용하는 non-direct 버퍼에 비해 할당/제거 비용이 크다. Direct 버퍼는 allocateDirect 팩토리 메서드로 생성된다

  4. Access to binary data
  5. 버퍼의 byte order는 해당 버퍼에 대한 연산의 기준이 된다. 기본값은 ByteOrder.BIG_ENDIAN

  6. 인덱싱
    • ByteBuffer에 대한 absolute get/put의 인덱스는 바이트 단위
    • 뷰 버퍼의 인덱스는 해당 타입 크기 단위

↓ java

final ByteBuffer alignedSlice(int unitSize) // 현재 버퍼를 unitSize 크기씩 잘라 view 버퍼를 생성(BIG_ENDIAN)한다 // 현재 위치가 unitSize의 배수가 아니라면 바로 다음 배수 위치부터 포함하며, limit도 unitSize 배수에 맞춰 끊는다 int mismatch(ByteBuffer that) // 두 바이트 버퍼의 현재 읽기 위치들을 시작 위치로 하여, 바이트 값이 다른 최초 index를 반환한다

ByteOrder

↓ java

public static final ByteOrder BIG_ENDIAN, LITTLE_ENDIAN static ByteOrder nativeOrder()

java.nio.channels

Channel

채널이란, 독립적인 IO를 수행할 수 있는 개체에 대한 연결이다

↓ java

boolean isOpen()

ReadableByteChannel

↓ java

int read(ByteBuffer dst) // dst.remaining()만큼 읽어 dst에 저장. 읽은 바이트 개수를 반환. 스트림의 끝이면 -1

WritableByteChannel

↓ java

int write(ByteBuffer src) // src.remaining() 부분을 채널에 쓴다

InterruptibleChannel

"instanceof InterruptibleChannel" IFF "비동기적으로 close() 메서드를 통해 인터럽트되고 닫을 수 있는 채널"

ScatteringByteChannel

채널의 바이트들을 여러 버퍼에 순서대로 저장. 네트워크 헤더나 파일 메타데이터처럼 고정 길이의 헤더를 읽는 데 유용

↓ java

long read(ByteBuffer[] dsts, int offset, int length) // dsts[offset]부터 length개의 버퍼가 각각의 remaining()만큼씩 바이트를 읽어 가져간다

GatheringByteChannel

↓ java

long write(ByteBuffer[] srcs, int offset, int length) // srcs[offset]부터 length개의 버퍼의 remaining() 부분을 채널에 쓴다

SeekableByteChannel

현재 위치를 기억하는 바이트 채널

↓ java

long position() SeekableByteChannel position​(long newPosition) SeekableByteChannel truncate(long size) // 채널에 연결된 개체의 크기를 size로 조정 // size가 현재보다 작은 경우 나머지는 버려진다(position이 size보다 큰 경우 size로 조정된다) // size가 현재 이상인 경우 아무 변경 없다

NetworkChannel

네트워크 소켓에 대한 채널

↓ java

NetworkChannel bind​(SocketAddress local) Set<SocketOption<?>> supportedOptions() <T> NetworkChannel setOption​(SocketOption<T> name, T value)

DatagramChannel

  1. 데이터그램-지향 소켓 채널
  2. 기존 데이터그램 소켓에서 채널을 얻는 방법은 없으며, open 팩터리 메서드로 획득해야 한다
  3. send/receive 메서드는 연결없이 사용할 수 있지만, read/write 메서드는 connect 메서드를 통해 연결해야 이용할 수 있다
  4. 연결된 경우, 송/수신에 불필요한 보안 체크를 하지 않는다

  5. 지원하는 소켓 옵션 : SO_SNDBUF, SO_RCVBUF, SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP

AsynchronousChannel

비동기 I/O를 지원하는 채널. close()도 비동기적으로 수행되며, close 도중/이후 작업은 AsynchronousCloseException 발생

↓ java

// 전형적인 메서드 형태 Future<V> operation(...) void operation(..., A attachment, CompletionHandler<V,? super A> handler)

CompletionHandler<V, A>

비동기 I/O 작업 결과를 소비

↓ java

void completed(V result, A attachment) // 성공시 호출 void failed(Throwable exc, A attachment) // 실패시 호출

AsynchronousByteChannel

비동기 바이트 채널

↓ java

Future<Integer> read(ByteBuffer dst) Future<Integer> write(ByteBuffer src) // 반환된 Future::get 메서드로 읽은/쓴 바이트 수를 얻을 수 있다

AsynchronousChannelGroup

  • 시스템 속성에 따라 생성된 ThreadFactory가 비동기 작업을 실행할 데몬 스레드들을 만든다
  • 그룹이 지정되지 않은 비동기 채널들은 시스템 기본 그룹에 묶인다

AsynchronousFileChannel

  1. 파일에 대한 비동기 채널. I/O의 기준이 되는 위치는 메서드에서 지정한다
  2. 생성된 채널들은 스레드-안전하며, 완료 핸들러들은 별개의 스레드에서 실행됨이 보장된다
  3. 연산에 사용되는 ByteBuffer 자체는 스레드-안전하지 않음에 유의

↓ java

static AsynchronousFileChannel open(Path file, Set<? extends OpenOption> options, ExecutorService executor, FileAttribute<?>... attrs) // 파일을 열거나 생성한 뒤 비동기 채널을 하나 반환한다 // options에 java.nio.file.StandardOpenOption 이용 abstract AsynchronousFileChannel truncate(long size) // size() > size인 경우 파일을 자른다. return this; abstract void force(boolean metaData) // true면 StandardOpenOption.SYNC를, false면 StandardOpenOption.DSYNC를 적용하는 것과 같다 // 기저 파일이 로컬에 존재하는 경우에만 유효 abstract Future<FileLock> lock​(long position, long size, boolean shared) // 기저 파일 일부에 대한 잠금을 얻는다 // size는 고정이므로, 파일 크기가 커질 것도 고려하여 필요한 만큼 신청해놔야 한다 // shared : 잠금 영역에 대한 추가 잠금 허용 여부

AsynchronousServerSocketChannel

  1. 스트림 지향 서버 소켓 채널
  2. 스레드-안전하지만 최대 accept 가능한 스레드는 하나 뿐이며, accept 도중 중복되는 요청은 AcceptPendingException
  3. 클라이언트 채널은 동일한 채널 그룹에 속하게 된다
  4. 지원하는 소켓 옵션
    • SO_RCVBUF : 수신 버퍼 크기
    • SO_REUSEADDR : 주소 재사용
    • 구현에 따라 추가될 수 있다

AsynchronousSocketChannel

  1. 스트림 지향 클라이언트 소켓 채널
  2. 스레드-안전하지만 최대 하나의 읽기/쓰기만 각각 동시에 존재할 수 있다
  3. 도중에 중복되는 요청은 각각 ReadPendingException, WritePendinException 발생

  4. 읽기/쓰기 시 양수의 타임아웃을 지정한 경우, 시간 내에 완료되지 못하면 InterruptedByTimeoutException으로 종료되고, 이후 상태는 비결정적이며, 따라서 사용된 채널, 버퍼들은 버리는 게 낫다
  5. 지원하는 소켓 옵션
    • SO_SNDBUF : 전송 버퍼 크기
    • SO_RCVBUF : 수신 버퍼 크기
    • SO_KEEPALIVE : 기본 false, keep-alive 작동은 구현체에 의존적이다
    • TCP_NODELAY : Nagle 알고리즘 비활성

java.nio.charset

Charset

↓ java

static SortedMap<String, Charset> availableCharsets() static boolean isSupported(String charsetName) static Charset forName(String charsetName) static Charset defaultCharset() abstract CharsetDecoder newDecoder() // + newEncoder final CharBuffer decode(ByteBuffer bb) // + encode

CharsetDecoder

바이트열을 문자열로 변환

↓ java

final CharBuffer decode(ByteBuffer in) final float averageCharsPerByte() // + maxCharsPerByte

CharsetEncoder

문자열을 바이트열로 변환

↓ java

final ByteBuffer encode(CharBuffer in) final float averageBytesPerChar() // + maxBytesPerChar

StandardCharsets

US-ASCII(= ISO646-US), ISO-8859-1(= ISO-LATIN-1), UTF-8, UTF-16BE, UTF-16LE, UTF-16

java.nio.file

파일 순회 관련

FileVisitor<T>

Files::walkFileTree 메서드에 사용

SimpleFileVisitor<T>

  1. preVisitDirectory : CONTINUE 반환
  2. visitFile : CONTINUE 반환
  3. visitFileFailed : rethrow
  4. postVisitDirectory : 예외없으면 CONTINUE, 있으면 rethrows

FileVisitResult

  1. CONTINUE : 순회 계속
  2. TERMINATE : 순회 종료
  3. SKIP_SUBTREE : FileVIsitor::preVisitDirectory에서 반환된 경우, 하위 레벨 트리는 순회하지 않는다
  4. SKIP_SIBLINGS : 현재 요소가 포함된 디렉터리 내부에서, 현재 요소와 동일한 레벨의 요소들은 더 이상 순회하지 않는다
  5. FileVIsitor::preVisitDirectory에서 반환된 경우, 현재 디렉터리의 내부 요소들과 postVisitDirectory 모두 건너뛴다

옵션 관련

StandardCopyOption

↓ java

REPLACE_EXISTING, COPY_ATTRIBUTES, ATOMIC_MOVE

StandardOpenOption

  1. READ : 읽기
  2. WRITE : 쓰기
  3. APPEND : TRUNCATE_EXISTING 옵션이 있거나 읽기 전용일 때는 적용되지 않는다
  4. TRUNCATE_EXISTING : 파일을 열 때 크기를 0바이트로 줄인다. 읽기 전용으로 열 때는 적용되지 않는다
  5. CREATE : 기존 파일이 존재하면 열고, 없으면 새로 생성한다
  6. CREATE_NEW : 신규 파일을 생성한다. 기존 파일이 존재하면 실패한다
  7. DELETE_ON_CLOSE : close() 호출 시 파일을 지운다(best effort)
  8. SPARSE : 파일이 sparse임을 OS에 알려준다. 신규 파일을 생성하는 경우에만 유효하다
  9. SYNC : 파일 내용 및 메타데이터의 변경을 동기적으로 물리 장치에 기록한다
  10. DSYNC : 파일 내용 변경을 동기적으로 물리 장치에 기록한다

FileVisitOption

FOLLOW_LINKS : 심볼릭 링크를 따라 들어가는 경우

LinkOption

NOFOLLOW_LINKS : 심볼릭 링크를 따라 들어가지 않는 경우

파일 시스템 관련

Path

파일 경로를 가리킨다

↓ java

static Path of(String first, String... more) static Path of(URI uri) // ↔ toUri FileSystem getFileSystem() // 이 Path를 만든 FileSystem 반환 Path getRoot() // + getFileName, getParent, getNameCount, getName, subpath, toAbsolutePath, toRealPath Path normalize() // 불필요한 ".", ".." 제거 Path resolve(Path other) // 호출한 path를 기준 디렉터리로 하여, other가 가리키는 지점을 단일 Path로 반환한다 default Path resolveSibling(Path other) // (getParent() == null) ? other : getParent().resolve(other); Path relativize(Path other) // 호출한 path를 기준으로, other에 도달하는 상대경로를 반환한다

Files

↓ java

static InputStream newInputStream(Path path, OpenOption... options) // + newOutputStream, newByteChannel, newBufferedReader, newBufferedWriter static Path createFile(Path path, FileAttribute<?>... attrs) // + createDirectory, createDirectories(경로 상의 모든 디렉터리 생성), createTempFile, createTempDirectory, createSymbolicLink, createLink(하드 링크) static void delete(Path path) // + deleteIfExists, copy, move static bolean isSameFile(Path path, Path path2) static long mismatch(Path path, Path path2) // 두 파일이 불일치하는 최초의 바이트 위치를 반환한다. 같으면 -1L static byte[] readAllBytes(Path path) // + readString, lines, readAllLines static Path write(Path path, Iterable<? extends CharSequence> lines, OpenOption... options) static Path writeString(Path path, CharSequence csq, Charset cs, OpenOption... options) static boolean isHidden(Path path) // + isDirectory, isSymbolicLink, isRegularFile, exists, notExists, isReadable, isWritable, isExecutable static String probeContentType(Path path) // + getFileAttributeView, readAttributes, getAttribute, setAttribute, getLastModifiedTime, setLastModifiedTime, size static Stream<Path> list(Path dir) static Stream<Path> walk(Path start, int maxDepth, FileVisitOption... options) // + walkFileTree static Stream<Path> find(Path start, int maxDepth, BiPredicate<Path, BasicFileAttributes> matcher, FileVisitOption... options)

FileSystems

↓ java

static FileSystem getDefault()

java.security

암호적으로 안전한 난수 생성기

SecureRandom

  1. 비결정적인 출력을 위해, 전달되는 시드 역시 예측할 수 없어야 한다
  2. 시드를 제공하지 않은 경우, 최초 nextBytes 호출 시 구현체에서 정의하는 엔트로피 소스로부터 시드를 선택한다

  3. SecureRandom 인스턴스는 스레드-안전하다

↓ java

static SecureRandom getInstance(String algorithm) // https://docs.oracle.com/en/java/javase/12/docs/specs/security/standard-names.html#securerandom-number-generation-algorithms static SecureRandom getInstance(String algorithm, SecureRandomParameters params) // e.g. SecureRandom.getInstance("DRBG", DrbgParameters.instantiation(128, RESEED_ONLY, null)); static SecureRandomParameters getInstanceStrong() void reseed() // 엔트로피 소스로부터 시드 재선택 void nextBytes(byte[] bytes) // + generateSeed

DrbgParameters

  1. DRBG; Deterministic Random Bit Generator 이용을 위한 파라미터
  2. 직접 지정하고 싶은 경우, 메서드의 SecureRandomParameters 파라미터로 넘기면 된다

    ↓ java

    var drbg = SecureRandom.getInstance("DRBG", DrbgParameters.instantiation(112, NONE, null)); // Weak DRBG 인스턴스. 112비트 보안 강도 drbg.nextBytes(buffer, DrbgParameters.nextBytes(256, false, "more".getBytes())); // 보안 강도 112비트를 초과하여 실패 drbg.nextBytes(buffer, DrbgParameters.nextBytes(112, true, "more".getBytes())); // 예측 저항(PR_AND_RESEED) 없으므로 실패
  3. 관련 시스템 속성
  4. securerandom.drbg.config : 기본값 == Hash_DRBG with SHA-256

DrbgParameters.Capability

↓ java

NONE(예측 저항 x, reseed x), PR_AND_RESEED(예측 저항 o, reseed o), RESEED_ONLY(예측 저항 x, reseed o)

java.text

Normalizer

유니코드_정규화 관련 기능을 제공한다

↓ java

static enum Normalizer.Form { NFC, NFD, NFKC, NFKD } static String normalize(CharSequence src, Normalizer.Form form) // + isNormalized

NumberFormat

↓ java

static enum NumberFormat.Style { SHORT, LONG } static class NumberFormat.Field INTEGER(정수부), FRACTION(분수), EXPONENT(지수부), DECIMAL_SEPARATOR(소수 구분 기호) SIGN(부호), GROUPING_SEPARATOR(단위 구분 문자), EXPONENT_SYMBOL, PERCENT, PERMILLE, CURRENCY, EXPONENT_SIGN, PREFIX, SUFFIX } static final NumberFormat getInstance(Locale inLocale) // + getNumberInstance : 범용 // + getIntegerInstance : 포맷에 HALF_EVEN을 이용하고, 파싱은 정수부만

SimpleDateFormat

문자표현요소
G기원 전/후AD
y1996; 96
YWeek year2009; 09
M월(context sensitive)July; Jul; 07
L월 (standalone form)July; Jul; 07
wWeek in year27
WWeek in month2
DDay in year189
dDay in month10
FDay of week in month2
EDay name in weekTuesday; Tue
uDay number of week1 = Monday, ..., 7 = Sunday
aAm/pmPM
HHour in day (0-23)0
kHour in day (1-24)24
KHour in am/pm (0-11)0
hHour in am/pm (1-12)12
mMinute in hour30
sSecond in minute55
SMillisecond978
zGeneral time zonePacific Standard Time; PST; GMT-08:00
ZRFC 822 time zone-0800
XISO 8601 time zone-08; -0800; -08:00

MessageFormat

↓ java

MessageFormatPattern ::= String | MessageFormatPattern FormatElement String FormatElement ::= { ArgumentIndex[, FormatType[, FormatStyle]] } FormatType ::= number | date | time | choice FormatStyle ::= short | medium | long | full | integer | currency | percent | SubformatPattern
  1. '' 안의 포맷 문자열은 이스케이프된다
  2. 동일 요소에 대한 반복적인 파싱은 마지막 파싱 결과만 유효하다
FormatTypeFormatStyleSubformat Created
(none)(none)null
number(none)NumberFormat.getInstance(getLocale())
integerNumberFormat.getIntegerInstance(getLocale())
currencyNumberFormat.getCurrencyInstance(getLocale())
percentNumberFormat.getPercentInstance(getLocale())
SubformatPatternnew DecimalFormat(subformatPattern, DecimalFormatSymbols.getInstance(getLocale()))
date(none)DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())
shortDateFormat.getDateInstance(DateFormat.SHORT, getLocale())
mediumDateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())
longDateFormat.getDateInstance(DateFormat.LONG, getLocale())
fullDateFormat.getDateInstance(DateFormat.FULL, getLocale())
SubformatPatternnew SimpleDateFormat(subformatPattern, getLocale())
time(none)DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())
shortDateFormat.getTimeInstance(DateFormat.SHORT, getLocale())
mediumDateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())
longDateFormat.getTimeInstance(DateFormat.LONG, getLocale())
fullDateFormat.getTimeInstance(DateFormat.FULL, getLocale())
SubformatPatternnew SimpleDateFormat(subformatPattern, getLocale())
choiceSubformatPatternnew ChoiceFormat(subformatPattern)

java.time

Clock

시간대(time-zone)을 이용한 현재의 date와 time 제공. 지정하지 않는 이상, 시계 내부의 시각은 계속 변한다

↓ java

static Clock system(ZoneId zone) // 특정 시간대의 시계 반환 // systemUTC() == system(ZoneOffset.UTC) // systemDefaultZone() == system(ZoneId.systemDefault()) static Clock tick(Clock baseClock, Duration tickDuration) // 지정된 시계의 tick 단위를 조정. 예를 들어 1분이 지정된 경우, 1분 미만의 값은 버려진다 // tickMillis(ZoneId zone) == tick(system(zone), Duration.ofMillis(1)) static Clock fixed(Instant fixedInstant, ZoneId zone) // 현재 시각으로 멈춘 시계 반환 static Clock offset(Clock baseClock, Duration offsetDuration) // 시각을 조정한 새로운 시계 반환 abstract Clock withZone(ZoneId zone) // 지정된 시간대에 현재 시계의 복사본을 생성하여 반환한다. 따라서 시각 자체는 조정하지 않는다

Duration

↓ java

static Duration of(long amount, TemporalUnit unit) static Duration from(TemporalAmount amount) // amount 그대로 Duration으로 변환 static Duration parse(CharSequence text) // ISO-8601 duration format PnDTnHnMn.nS // 추가로 접두 부호 가능 static Duration between(Temporal startInclusive, Temporal endExclusive) Duration withSeconds(long seconds) // 나노초 단위만 남기고 seconds로 변경 Duration withNanos(int nanoOfSecond) // 나노초 단위만 nanoOfSecond로 변경

Instant

Epoch(1970-01-01 00:00:00)를 기준으로 한 초(long)와 나노초(int)로 시각을 표현한다. 음수면 epoch 이전

↓ java

public static final Instant EPOCH, MIN(아주 먼 옛날), MAX(아주 먼 미래) static Instant now() static Instant parse(CharSequence text) // DateTimeFormatter.ISO_INSTANT // 예. 2007-12-03T10:15:30.00Z)

DayOfWeek

↓ java

public static final DayOfWeek MONDAY ~ SUNDAY int getValue() // ISO-8601. 1(MONDAY) ~ 7(SUNDAY)

Month

↓ java

public static final Month JANUARY ~ DECEMBER int getValue() // ISO-8601. 1(JANUARY) ~ 12(DECEMBER)

java.time.format

DateTimeFormatter

DateTimeFormatter.html#predefined

FormatterDescriptionExample
ofLocalizedDate(dateStyle)Formatter with date style from the locale'2011-12-03'
ofLocalizedTime(timeStyle)Formatter with time style from the locale'10:15:30'
ofLocalizedDateTime(dateTimeStyle)Formatter with a style for date and time from the locale'3 Jun 2008 11:05:30'
ofLocalizedDateTime(dateStyle,timeStyle)Formatter with date and time styles from the locale'3 Jun 2008 11:05'
BASIC_ISO_DATEBasic ISO date'20111203'
ISO_LOCAL_DATEISO Local Date'2011-12-03'
ISO_OFFSET_DATEISO Date with offset'2011-12-03+01:00'
ISO_DATEISO Date with or without offset'2011-12-03+01:00'; '2011-12-03'
ISO_LOCAL_TIMETime without offset'10:15:30'
ISO_OFFSET_TIMETime with offset'10:15:30+01:00'
ISO_TIMETime with or without offset'10:15:30+01:00'; '10:15:30'
ISO_LOCAL_DATE_TIMEISO Local Date and Time'2011-12-03T10:15:30'
ISO_OFFSET_DATE_TIMEDate Time with Offset'2011-12-03T10:15:30+01:00'
ISO_ZONED_DATE_TIMEZoned Date Time'2011-12-03T10:15:30+01:00[Europe/Paris]'
ISO_DATE_TIMEDate and time with ZoneId'2011-12-03T10:15:30+01:00[Europe/Paris]'
ISO_ORDINAL_DATEYear and day of year'2012-337'
ISO_WEEK_DATEYear and Week'2012-W48-6'
ISO_INSTANTDate and Time of an Instant'2011-12-03T10:15:30Z'
RFC_1123_DATE_TIMERFC 1123 / RFC 822'Tue, 3 Jun 2008 11:05:30 GMT'

java.util

Collection API

컬렉션 자료형 인터페이스

Collection<E>

  1. 컬렉션 최소 연산을 정의
  2. 서브 컬렉션을 작성할 때, 인자없는 생성자와 Collection 인자 하나만 받는 생성자를 각각 작성하도록 권장한다
  3. 정의하지 않아도 되는 선택적 메서드들에 대하여, 구현하지 않는 경우 UnsupportedOperationException을 던져야 한다
  4. 컬렉션이 자기 자신을 요소로 갖는 경우 일부 메서드 실행 중 예외가 발생할 수 있다

↓ java

int size() boolean isEmpty() boolean add(E e) boolean addAll(Collection<? extends E> c) boolean contains(Object o) boolean containsAll(Collection<?> c) boolean retainAll(Collection<?> c) // c에 속한 원소만 남기고 모두 제거한다. 이 연산으로 컬렉션이 변경됐다면 true 반환 boolean remove(Object o) boolean removeAll(Collection<?> c) default boolean removeIf(Predicate<? super E> filter) void clear() <T> T[] toArray(T[] a) // 사용 : toArray(new Clazz[0]) default <T> T[] toArray(IntFunction<T[]> generator) // 사용 : toArray(Clazz[]::new) default Stream<E> stream() default Stream<E> parallelStream()

Queue<E>

↓ java

boolean add(E e) // 추가할 수 없으면 예외 발생. 따라서 반환이 있다면 그 값은 항상 true boolean offer(E e) // 추가하면 true, 실패하면 false E remove() // 앞쪽 원소 하나 제거. 없으면 예외 E poll() // 앞쪽 원소 하나 제거. 없으면 null E element() // 앞쪽 원소 하나 제거하지 않고 가져오기. 없으면 예외 E peek() // 앞쪽 원소 하나 제거하지 않고 가져오기. 없으면 null

Deque<E>

양방향 삽입/삭제 가능한 Queue

↓ java

boolean removeLastOccurrence(Object o) Iterator<E> descendingIterator()

List<E>

↓ java

static <E> List<E> of​(E... elements) static <E> List<E> copyOf​(Collection<? extends E> coll) // 변경 불가 리스트 반환 default void replaceAll(UnaryOperator<E> operator) // 모든 원소를 연산 결과로 대체 default void sort(Comparator<? super E> c) int indexOf(Object o) // + lastIndexOf ListIterator<E> listIterator() List<E> subList(int fromIndex, int toIndex)

Set<E>

↓ java

static <E> Set<E> of(E... elements) static <E> Set<E> copyOf(Collection<? extends E> coll) // 변경 불가 집합 반환

SortedSet<E>

원소가 정렬된 Set. 다음 4가지 생성자를 구현할 것을 권장. (void), (Comparator), (Collection), (SortedSet)

↓ java

SortedSet<E> subSet(E fromElement, E toElement) // 부분집합 반환. toElement는 미포함 // + headSet, tailSet E first() // + last

NavigableSet<E>

인접 원소 탐색이 가능한 SortedSet

↓ java

E lower(E e) // e보다 작은 원소들 중 최댓값을 반환. 없으면 null // + floor: <=e, ceiling: >=e, higher: >e E pollFirst() // + pollLast() NavigableSet<E> subSet​(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) NavigableSet<E> descendingSet() Iterator<E> descendingIterator()

Map<K, V>

↓ java

default V getOrDefault(Object key, V defaultValue) default V putIfAbsent(K key, V value) default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) // 값을 다시 계산하여 덮어쓴다 default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) + computeIfPresent // key가 맵에 없거나, 대응하는 값이 null인 경우 새로운 값을 계산하여 넣고 반환 // 계산된 값이 null이면 null 반환. 그 외의 경우 현재값 반환 // + computeIfPresent : key가 존재하고, 대응하는 값이 null이 아닌 경우 새로운 값을 계산하여 넣고 반환 default V replace(K key, V value) // key가 있을 때만 대체. 없으면 null 반환 // + replaceAll default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) // if (key가 맵에 없거나, 대응하는 값이 null인 경우) => value로 연결 // else => 주어진 함수를 통해 새로운 값에 연결 // 결과가 null인 경우 맵에서 제거 static <K,​V> Map<K,​V> of(), ofEntries(), copyOf() // 변경 불가능한 맵 반환; 키와 값 모두 null 비허용
Map.Entry<K, V>

↓ java

static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey() // 키를 기준으로 엔트리를 비교하는 비교자 반환. 인자 있는 함수의 경우 해당 비교자를 이용 // + comparingByValue

SortedMap<K, V>

키가 정렬된 Map. 다음 4가지 생성자를 구현할 것을 권장. (void), (Comparator), (Map), (SortedMap)

↓ java

SortedMap<K, V> subMap(K fromKey, K toKey) // 지정된 범위의 키만으로 구성된 서브 맵 반환. toKey는 미포함 // + headMap, tailMap

NavigableMap<K, V>

인접 키 탐색이 가능한 SortedMap

↓ java

Map.Entry<K, V> lowerEntry(K key) // key보다 작은 키들 중 최댓값에 대한 entry 반환. 없으면 null // + floorEntry: <=key, ceilingEntry: >=key, higherEntry: >key NavigableMap<K, V> descendingMap() NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) // + headMap, tailMap

컬렉션 순회 인터페이스

Iterator<E>

↓ java

boolean hasNext() E next() default void remove() // 마지막으로 반환된 원소를 제거. next() 호출 뒤 한 번만 호출 가능 default void forEachRemaining(Consumer<? super E> action)

ListIterator<E>

양방향으로 이동 가능한 iterator

↓ java

boolean hasPrevious() E previous() int nextIndex() // + previousIndex void set(E e) // 마지막으로 반환된 요소를 변경 void add(E e) // next()로 반환될 요소 바로전에 삽입

PrimitiveIterator<T, T_CONS>

기본 타입의 박싱을 회피하기 위한 PrimitiveIterator.OfInt, OfLong, OfDouble 제공

Spliterator<T>

  1. Iterator와 달리 병렬 순회가 가능하며, 순회 메서드가 hasNext(), next()로 이분화되지 않는다
  2. 병렬 순회하려는 경우, 동일 Spliterator 객체를 이용하지 말고, 다른 스레드는 trySplit()을 통해 얻은 객체로 순회해야 한다
  3. 박싱을 피하기 위한 Spliterator.OfInt, OfLong, OfDouble 제공

↓ java

static int CONCURRENT, DISTINCT, IMMUTABLE, NONNULL, ORDERED, SIZED, SORTED, SUBSIZED boolean tryAdvance(Consumer<? super T> action) // 남은 원소가 존재하면 하나를 소비하고 true 반환. 그 외엔 false default void forEachRemaining(Consumer<? super T> action) Spliterator<T> trySplit() // 이 spliterator를 분리할 수 있다면, 일부분을 분리하여 반환하고, 이 spliterator는 나머지 원소들을 순회한다. 그 외엔 null long estimateSize() // forEachRemaining() 메서드에서 순회할 원소의 수를 예측하여 반환한다 // 무한하거나, 알 수 없거나, 계산하는 연산이 비싼 경우 Long.MAX_VALUE를 반환하면 된다 default long getExactSizeIfKnown() // 이 spliterator가 SIZED인 경우 estimateSize()를 반환한다. 그 외엔 -1 default Comparator<? super T> getComparator() // 이 spliterator의 소스가 Comparator를 이용해 정렬된(SORTED) 경우, 해당 Comparator를 반환한다 // 그 외엔 null, 또는 IllegalStateException

컬렉션 자료형 콘크리트 클래스

ArrayDeque<E>

가변 길이 배열로 구현한 Deque. 스레드-안전하지 않음

ArrayList<E>

가변 길이 배열로 구현한 List. 스레드-안전하지 않음

Vector<E>

ArrayList와 달리 스레드-안전하다

BitSet

n개의 비트열 표현. 각 비트의 기본값은 false. 스레드-안전하지 않음

↓ java

void andNot(BitSet set) // set에 true로 설정된 모든 index에 대해 false 설정 boolean intersects(BitSet set) // 하나라도 true로 일치하는 경우 int size() // 총 비트 수 int cardinality() // true 비트 수 int length() // the index of the highest set bit

EnumMap<K extends Enum<K>, V>

Enum을 키로 이용

EnumSet<E extends Enum<E>>

↓ java

static <E extends Enum<E>> EnumSet<E> range(E from, E to) static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) // 공집합 반환 static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) // 전체 집합 반환 static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) // 여집합 반환

HashMap<K, V>

null 허용 해시테이블. 스레드-안전하지 않음

HashSet<E>

HashMap를 이용하는 null 허용 집합. 스레드-안전하지 않음

IdentityHashMap<K, V>

  • k1 == k2 비교를 이용하는 해시테이블. 스레드-안전하지 않다
  • keySet(), values(), entrySet()으로 반환되는 컬렉션 모두 원소 비교를 == 연산으로 한다

LinkedList<E>

List와 Deque을 모두 구현한 연결 리스트. 스레드-안전하지 않음

LinkedHashMap<K, V>

  • 키 순서를 유지하는 이중 연결 리스트를 가진다
  • 스레드-안전하지 않다

↓ java

public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) // accessOrder == true ? 접근 빈도로 정렬 : 삽입 순서로 정렬

LinkedHashSet<E>

삽입된 순서대로 원소를 유지하는 이중 연결 리스트를 가진다. 원소가 존재하는 상황에서 add() 호출로 순서가 변경되지 않는다. 스레드-안전하지 않다

PriorityQueue<E>

우선순위 힙에 기반한 unbounded 우선순위 큐. head가 가장 우선순위가 작은 원소. 스레드-안전하지 않다(-> PriorityBlockingQueue)

Stack<E>

LIFO 스택

↓ java

int search(Object o) // top으로부터 거리 반환

TreeMap<K, V>

Red-Black tree(이진 탐색 트리의 일종)를 이용한 NavigableMap 구현. log(n) 시간의 작업을 보장한다. 스레드-안전하지 않다

TreeSet<E>

TreeMap을 이용한 NavigableSet 구현. 스레드-안전하지 않다

WeakHashMap<K, V>

  • key를 Goto - WeakReference 로 관리
  • key, value 모두에 null 허용
  • value가 key의 참조를 가지지 않도록 유의
  • 스레드-안전하지 않다

Hashtable<K, V>

스레드-안전한 해시 테이블 구현. 스레드-안전할 필요가 없으면 HashMap, 높은 동시성이 요구되는 경우엔 ConcurrentHashMap을 이용

유틸리티

Collections

↓ java

// 리스트 연산 static <T extends Comparable<? super T>> void sort(List<T> list) // T 자체가 Comparable하거나, T에 대한 Comparator를 넘기거나 static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) static void reverse(List<?> list) // + shuffle, swap, fill, rotate static <T> void copy(List<? super T> dest, List<? extends T> src) static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) static int indexOfSubList(List<?> source, List<?> target) // + lastIndexOfSubList // 컬렉션 연산 static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) static int frequency(Collection<?> c, Object o) static boolean disjoint(Collection<?> c1, Collection<?> c2) // 공통 원소가 없는지 여부 // 컬렉션 장식 static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) static <T> Collection<T> synchronizedCollection(Collection<T> c) // 반환된 컬렉션에 대해 synchronized 제약을 걸고 이용하는 것이 좋다 static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type) // 타입 체킹 추가 // 팩터리 static <T> Set<T> singleton(T o) static <T> List<T> nCopies(int n, T o) static <T> List<T> singletonList(T o) static <K, V> Map<K, V> singletonMap(K key, V value)

Spliterators

↓ java

static <T> Spliterator<T> spliterator(Object[] array, int additionalCharacteristics) // Arrays.spliterator()가 제공하는 것에 특성을 추가하고 싶을 때 사용. 전형적으로 IMMUTABLE, ORDERED static <T> Spliterator<T> spliteratorUnknownSize(Iterator<? extends T> iterator, int characteristics) // Spliterator로 래핑한 후, 원본 iterator를 사용하면 안 된다 static <T> Iterator<T> iterator(Spliterator<? extends T> spliterator) // Iterator로 래핑한 후, 원본 spliterator를 사용하면 안 된다.
Spliterators.AbstractSpliterator<T>

estimateSize(), characteristics(), trySplit()을 구현한 추상 클래스

Arrays

↓ java

// 정렬, 검색 static void sort(int[] a) static void parallelSort(byte[] a) // ForkJoin common pool을 이용해 병합 정렬을 병렬로 수행 static int binarySearch(long[] a, long key) // 변경, 변환 static void fill(long[] a, long val) static <T> void setAll(T[] array, IntFunction<? extends T> generator) static <T> void parallelSetAll(T[] array, IntFunction<? extends T> generator) static <T> void parallelPrefix(T[] array, BinaryOperator<T> op) // 전체 원소에 순차적으로 연산 적용하여 값 변경. 큰 배열은 루프보다 이게 더 빠르다 static String toString(?[] a) static String deepToString(Object[] a) // deep : 원소가 배열인 경우 "[]"를 추가하고 해당 배열의 원소들에 대해 같은 작업을 한다 static <T> List<T> asList(T... a) static <T> Spliterator<T> spliterator(T[] array) // characteristics()에서 SIZED | SUBSIZED | ORDERED | IMMUTABLE를 반환하는 Spliterator 인스턴스를 반환한다 static <T> Stream<T> stream(T[] array) // 복사 static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) static <T> T[] copyOf(T[] original, int newLength) static <T, U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) static <T> T[] copyOfRange(T[] original, int from, int to) // 비교 static int mismatch(?[] a, ?[] b) // 처음으로 일치하지 않는 인덱스 반환 static boolean equals(?[] a, int aFromIndex, int aToIndex, ?[] b, int bFromIndex, int bToIndex) // Object의 경우, Objects.equals(e1, e2)일 때 같다고 간주한다 static boolean deepEquals(Object[] a1, Object[] a2) // null일 수 있는 각 배열의 두 원소 e1, e2에 대하여, 다음 4가지 경우에 대해 둘이 같다고 판단한다 // 1. e1 == e2 // 2. 둘 모두 참조변수에 대한 배열이고, Arrays.deepEquals(e1, e2)가 true // 3. 둘 모두 원시타입에 대한 배열이고, Arrays.equals(e1, e2)가 true // 4. e1.equals(e2)가 true // 해싱 static int hashCode(?[] a) // 동일 원소를 가진 List의 해시코드와 동일. null이면 0 반환 static int deepHashCode(Object[] a) // 원소가 배열인 경우, 해당 원소의 해시를 deepHashCode로 구한다 // 자기 자신을 포함하는 배열 등은 적합하지 않다

Objects

↓ java

// 비교 static boolean deepEquals(Object a, Object b) // 둘 다 null이면 true // 둘 다 배열이면 Arrays.deepEquals() // 나머진 a.equals(b) static <T> int compare(T a, T b, Comparator<? super T> c) // hashCode static int hash(Object... values) // Arrays.hashCode(Object[])를 이용한다. Object.hashCode()의 간편한 구현으로 이용할 수 있다 // 주의. o.hashCode() != Objects.hash(o) // toString static String toString(Object o, String nullDefault) // null static boolean isNull(Object obj) // Predicate, filter(Objects::isNull)에 이용 static <T> T requireNonNull(T obj) // 메서드나 생성자에서 null검사를 하도록 설계되었다 static <T> T requireNonNullElse(T obj, T defaultObj) static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier) // index static int checkIndex(int index, int length) // index가 [0, length)에 존재하면 그대로 반환. 아니면 예외 발생 static int checkFromToIndex(int fromIndex, int toIndex, int length) // subrange [fromIndex, toIndex)가 [0, length)에 포함되면 fromIndex 반환. 아니면 예외 발생 static int checkFromIndexSize(int fromIndex, int size, int length) // subrange [fromIndex, fromIndex + size)가 [0, length)에 포함되면 fromIndex 반환. 아니면 예외 발생

시간 관련

Date

↓ java

long getTime() boolean before(Date when) + after, compareTo static Date from(Instant instant) + toInstant

Calendar

  1. 관대함(Leniency) : 범위를 벗어나는 값도 받아들이며, 나중에 정규화한다. 예를 들어 1월 32일은 2월 1일이 된다
  2. add와 roll : add는 오버플로되면 다음 단위가 변하지만, roll은 modulo연산처럼 해당 단위만 변한다

Field Detail

  1. 시간 단위
  2. public static final int ERA, YEAR, MONTH, WEEK_OF_YEAR, WEEK_OF_MONTH_, DATE, ...

  3. 단위 상수
  4. public static final int SUNDAY, ..., JANUARY, ...AM, PM

  5. 스타일
  6. public static final int ALL_STYLES, SHORT, LONG, NARROW_FORMAT, ...

↓ java

static Calendar getInstance() // 달력의 현재 시점을 저장하고 있으므로, 시각 비교, 설정 등의 연산 제공 final Date getTime() int get(int field) abstract void add(int field, int amount) void roll(int field, int amount) boolean isLenient()

Calendar.Builder

↓ java

Calendar.Builder setInstant(long instant) // 밀리초 Calendar.Builder set(int field, int value) Calendar.Builder setFields(int... fieldValuePairs) // 예: setFields(Calendar.YEAR, 2013, Calendar.MONTH, Calendar.DECEMBER, Calendar.DAY_OF_MONTH, 23) Calendar.Builder setTimeZone(TimeZone zone) Calendar.Builder setLenient(boolean lenient)

GregorianCalendar

GregorianCalendar는 아래 메서드를 지원한다

↓ java

int getWeekYear() void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) int getWeeksInWeekYear() final Instant toInstant() int getActualMaximum(int field) int getActualMinimum(int field)

Timer

  1. 백그라운드 스레드에서 미래에 실행될 작업들을 스케쥴링하는 기능을 제공한다. 작업은 일회용일수도, 일정한 주기를 가지고 반복될 수도 있다. 한 타이머의 모든 작업들은 하나의 백그라운드 스레드를 공유하기 때문에, 작업의 실행은 직렬적이며, 따라서 각 작업들은 가능한 한 빠르게 종료되어야 한다. 그렇지 않은 경우, 뒤에 대기하는 모든 작업이 밀려 제대로 실행되지 않을 수 있다
  2. 스레드-안전하다. 정시성을 보장하지 않는다. 스케쥴은 Object.wait(long) 메서드를 통해 이루어진다. java.util.concurrent 패키지의 ScheduledThreadPoolExecutor가 더 나은 대안으로 이용될 수 있다
  3. 기본적으로 타이머의 백그라운드 스레드는 데몬 스레드가 아니다. 따라서 타이머의 작업이 전체 프로그램의 종료를 지연시킬 수 있다. 백그라운드 스레드는 타이머 임의의 생성자에 의해 시작된다

↓ java

void schedule(TimerTask task, long delay) // delay밀리초 이후 task가 실행되도록 스케쥴 void schedule(TimerTask task, Date time) // time에 task가 실행되도록 스케쥴. time이 과거라면 즉시 실행 void schedule(TimerTask task, long delay, long period) // delay밀리초 이후 period 주기를 갖고 task가 실행되도록 스케쥴 void schedule(TimerTask task, Date firstTime, long period) // firstTime 이후 period 주기를 갖고 task가 실행되도록 스케쥴 void scheduleAtFixedRate(TimerTask task, long delay, long period) // period가 이전 task 종료가 아닌 최초 실행 시점을 기준으로 작동한다. 따라서 어떤 이유로 이전 작업이 지연된 경우, 시간당 작업률을 맞추기 위해 이후 작업이 연속적으로 실행될 수 있다 void cancel() // 타이머를 종료한다. 스케쥴된 모든 작업을 버리고, 현재 실행중인 작업에는 간섭하지 않는다. 타이머 종료 후 백그라운드 스레드도 우아하게 종료되어 GC 대상이 된다. 이후 더 이상의 스케쥴은 불가능하다

TimerTask

Timer 작업으로 사용하기 위한 Runnable

  1. boolean cancel()
    • 작업을 취소한다
    • 작업이 1회용으로 스케쥴되었지만 아직 실행되지 않은 경우, 또는 아직 스케쥴되지 않은 경우 작업은 결코 실행되지 않는다
    • 반복 작업으로 스케쥴된 경우, 작업은 결코 반복되지 않는다
    • 작업 도중에 호출된 경우, 작업은 마무리까지 실행된다
    • 반복 호출 가능하며 2회째 호출부터는 아무런 영향이 없다
    • true 반환 : 1회용으로 스케쥴되었지만 아직 실행되지 않은 경우, 반복 작업으로 스케쥴된 경우
    • false 반환 : 1회용으로 스케쥴되어 이미 실행된 경우, 아직 스케쥴되지 않은 경우, 이미 취소된 경우
  2. long scheduledExecutionTime()
  3. 가장 최근에 스케쥴된 ─ 또한 실제로 실행된 ─ 시점을 반환한다. 전형적으로 run 메서드에서, 작업이 너무 길어지는 것을 방지하기 위해 사용된다

숫자 관련

DoubleSummaryStatistics

  1. double에 관한 통계를 모은 상태 객체. 스트림과 함께 사용되도록 설계되었다
  2. ↓ java

    var stats = doubleStream.collect(DoubleSummaryStatistics::new, DoubleSummaryStatistics::accept, DoubleSummaryStatistics::combine); var stats = people.stream().collect(Collectors.summarizingDouble(Person::getWeight));
  3. + IntSummaryStatistics, LongSummaryStatistics

↓ java

public DoubleSummaryStatistics() // 개수 0, 합계 0, 최솟값 Double.POSITIVE_INFINITY, 최댓값 Double.NEGATIVE_INFINITY, 평균 0인 객체 생성 // + (long count, double min, double max, double sum) void accept(double value) // 요약 정보에 value를 추가

Random

의사난수 생성기. 스레드-안전하지만 성능 저하 가능성이 있으므로 ThreadLocalRandom을 고려

↓ java

void nextBytes(byte[] bytes) double nextGaussian() // 평균 0, 표준분산 1인 정규분포 난수 반환 // 난수 스트림 : + Long, Double 버전 존재 IntStream ints(long streamSize) IntStream ints() // == ints(Long.MAX_VALUE) IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) // [origin, bound)

SplittableRandom

분열하는 의사난수 생성기. 스레드-안전하지 않으며, 분열하여 스레드들이 각자 하나씩 갖도록 설계되었다

↓ java

SplittableRandom split() // 분열. 상태를 공유하진 않지만, 생성한 난수는 통계적으로 유사한 속성을 갖는다

문자열 및 국제화 관련

Base64

Base64 인코더와 디코더를 반환하는 유틸리티. RFC 2045, 4648

↓ java

static Base64.Encoder getEncoder() static Base64.Encoder getUrlEncoder() static Base64.Encoder getMimeEncoder()

Locale

↓ java

public static final Locale US, ENGLISH, KOREA, KOREAN, ... static Locale getDefault() static Locale[] getAvailableLocales()

Scanner

  1. 정규 표현식을 통해 원시 타입과 String을 분리해내는 간단한 text scanner
  2. 지정되지 않은 경우, 기본 구분자 패턴은 공백 문자(Character::isWhitespace)
  3. 기저 스트림으로부터 입력을 대기하는 동안 스레드가 블록될 수 있다
  4. 기저 Readable의 read()에서 IOException이 발생한 경우 소스의 끝에 도달했다고 판단하며, 가장 최근의 예외는 ioException()을 통해 얻을 수 있다
  5. 기저 스트림이 Closeable인 경우, Scanner에 대해 close()가 호출되면 기저 스트림도 닫힌다

↓ java

public Scanner(Readable source) public Scanner(InputStream source) public Scanner(File source) public Scanner(Path source) public Scanner(String source) public Scanner(ReadableByteChannel source) Pattern delimiter() // + useDelimiter Locale locale() // + useLocale int radix() // + useRadix String findInLine(Pattern pattern) // 구분자를 무시하고 pattern을 검색한다. 줄 바꿈 문자 전에 문자열을 찾으면 해당 문자열을 반환하고 다음 라인으로 넘어간다. 줄 바꿈 문자를 만날 때까지 매칭이 없으면 읽기 위치는 변경없이 null을 반환한다 String findWithinHorizon(Pattern pattern, int horizon) // 구분자를 무시하고 pattern을 검색한다. 현재 위치로부터 최대 horizon개의 code point만을 검색에 이용한다. horizon == 0인 경우, 제한없이 검색을 수행한다. 매칭된 문자열이 없으면 읽기 위치 변경없이 null을 반환한다 Scanner skip(Pattern pattern) // 구분자를 무시하고 pattern을 검색한다. 매칭된 문자열이 있으면 건너뛰고, 없으면 읽기 위치 변경 없이 NoSuchElementException 발생 MatchResult match() // 가장 최근의 매칭 결과를 반환한다. MatchResult는 각종 next, findInLine, findWithinHorizon, skip 메서드의 성공적인 실행으로 설정된다 Stream<MatchResult> findAll(Pattern pattern) // 스트림의 MatchResult 순서는 findWithinHorizon(pattern, 0), match()를 반복적으로 호출한 것과 동일하다 Stream<String> tokens() // 구분자로 자른 문자열들의 스트림을 반환한다 Scanner reset() // scanner.useDelimiter("\\p{javaWhitespace}+").useLocale(Locale.getDefault(Locale.Category.FORMAT)).useRadix(10);

etc

Comparator<T>

↓ java

default Comparator<T> reversed() default Comparator<T> thenComparing(Comparator<? super T> other) // 이 비교자가 두 객체를 같다고 판단하면, other가 새로 판단한다 // + thenComparingInt, Long, Double static <T extends Comparable<? super T>> Comparator<T> naturalOrder() // 자연스러운 비교자를 반환한다 // + reverseOrder static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) // null은 모든 non-null 값보다 작다고 간주한다. null끼리는 서로 같다고 간주한다 // + nullsLast static <T, U> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) // 정렬에 이용할 키를 생성하는 함수와, 키를 이용해 비교하는 비교자를 넘기면 둘을 포함하는 T타입 비교자를 반환 // + comparingInt, Long, Double

Optional<T>, OptionalInt, OptionalDouble, OptionalLong

null을 허용하지 않는 객체에 대한 컨테이너

↓ java

static <T> Optional<T> empty() static <T> Optional<T> of(T value) // null이면 예외 static <T> Optional<T> ofNullable(T value) // null이면 empty(), 아니면 of(value) T get() T orElse(T other) T orElseGet(Supplier<? extends T> supplier) Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) // 값이 존재하면 그대로 반환. 없으면 제공되는 값 반환 T orElseThrow() // 값이 없으면 NoSuchElementException boolean isPresent() // + isEmpty void ifPresent(Consumer<? super T> action) void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) Optional<T> filter(Predicate<? super T> predicate) // 값이 존재하고 필터를 통과하면 그대로 반환. 아니면 empty() Stream<T> stream() // 값이 존재하면 해당 값 하나만 포함하는 스트림 반환. 없으면 빈 스트림 반환 <U> Optional<U> map(Function<? super T, ? extends U> mapper) <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)

Properties

stream을 통해 로드/저장되는 영구적인 속성값들을 표현. 기본값으로 이용하기 위해 다른 Properties를 포함할 수 있다. 스레드-안전하다

↓ java

Object setProperty(String key, String value) String getProperty(String key, String defaultValue) void list(PrintStream out) // 디버깅에 유용 void load(Reader reader) void store(Writer writer, String comments) void loadFromXML(InputStream in) void storeToXML(OutputStream os, String comment)

UUID

+ com.fasterxml.uuid, com.datastax.cassandra

↓ java

public UUID(long mostSigBits, long leastSigBits) // 2개 long을 이용해 128비트 UUID 생성 static UUID randomUUID() // version 4 UUID 생성 static UUID nameUUIDFromBytes(byte[] name) // version 3 UUID 생성 static UUID fromString(String name) int version() // 1 Time-based UUID // 2 DCE security UUID // 3 Name-based UUID // 4 Randomly generated UUID int variant() // 0 Reserved for NCS // 2 RFC 4122(이 클래스에서 사용) // 6 Reserved for Microsoft // 7 Reserved for future long timestamp() // 60비트로 구성된 Time-based UUID의 시각을 반환한다. 1582-10-15 00:00:00 UTC로부터 몇 100ns가 흘렀는지를 의미한다 long node() //Time-based UUID의 48비트 Mac address를 반환한다

java.util.concurrent

비동기 연산

Future<V>

비동기적 계산의 결과를 표현

↓ java

V get() // 결과가 준비될 때까지 대기 V get(long timeout, TimeUnit unit) // 결과가 준비될 때까지 최대 timeout만큼 대기 boolean cancel(boolean mayInterruptIfRunning) // 작업을 취소한다. 결과를 기다리고 있던 스레드들은 CancellationException 발생 // 작업이 완료됐거나 이미 취소된 경우 false 반환 // 이 메서드가 종료된 후의 isDone()은 항상 true

CompletableFuture<T>

  1. (비)동기 연산들의 파이프라인을 구성할 수 있는, 명시적으로 종료(값과 상태를 설정)되는 Future
  2. ↓ java

    CompletableFuture.supplyAsync(() -> 123).thenApplyAsync((n) -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(n); return n * 2; }).thenApplyAsync((n) -> { System.out.println(n); return n * 2; }).get();
  3. 수행되는 연산은 Function, Consumer, Runnable로 표현되어야 한다
  4. 각각 apply, accept, run 메서드로 stage에 제공된다

  5. 둘 이상의 스레드가 complete, completeExceptionally, cancel을 호출할 경우, 하나만 성공한다
  6. non-async 메서드로 등록된 작업은 현재 CompletableFuture의 스레드, 또는 호출자에서 실행된다
  7. 명시적인 Executor 없이 async 메서드로 등록된 작업은 ForkJoinPool::commonPool에서 실행
  8. CompletionStage 메서드들을 독립적으로 구현했기 때문에, 하나를 재정의해도 다른 메서드에 영향이 없다
  9. CompletionStage 메서드들만 이용하도록 하려면 minimalCompletionStage()를, future를 변경하지 못하도록 하려면 copy()를 이용
  10. 전반적인 계산에 대한 직접적인 제어를 할 수 없어서, cancel()의 호출은 completeExceptionally(new CancellationException()) 호출과 동일하다

↓ java

static Executor delayedExecutor(long delay, TimeUnit unit) // 주어진 딜레이 이후에 executor로 작업을 제출하는 새로운 Executor 반환 static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) // supplier의 결과를 가지고 비동기 종료되는 CompletableFuture 반환 static CompletableFuture<Void> runAsync(Runnable runnable) // runnable을 실행하고 비동기 종료되는 CompletableFuture 반환 static <U> CompletableFuture<U> completedFuture(U value) // 이미 특정 값으로 종료된 CompletableFuture 반환 static <U> CompletionStage<U> completedStage(U value) // 주어진 value로 이미 종료된 새로운 CompletionStage 반환 static <U> CompletableFuture<U> failedFuture(Throwable ex) // 주어진 예외로 이미 종료된 새로운 CompletableFuture 객체 반환 static <U> CompletionStage<U> failedStage(Throwable ex) // 주어진 예외로 이미 종료된 새로운 CompletionStage 반환 <U> CompletableFuture<U> newIncompletableFuture() // 완료되지 않은 새로운 CompletableFuture 객체를 반환 // 서브클래스들은 각자의 클래스 인스턴스를 반환하도록 재정의해야 한다 static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) // 모든 cfs가 완료하면 완료되는 새로운 CompletableFuture 객체 반환 // 하나라도 예외 종료되면 반환된 CompletableFuture도 그러하다 // cfs가 빈 경우, null로 종료된다 static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) // 하나라도 완료되면, 그 결과와 같은 값으로 완료되는 CompletableFuture 객체 반환 // cfs가 빈 경우, 완료되지 않는다 // this 완료 후 실행 <U> CompletableFuture<U> thenApply(Function<? super T, ? extends U> fn) CompletableFuture<Void> thenAccept(Consumer<? super T> action) CompletableFuture<Void> thenRun(Runnable action) // this 완료 후 실행 + 값 대신 CompletionStage 직접 반환 <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn) // this와 other 모두 완료 후 실행 <U, V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T, ? super U, ? extends V> fn) <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action) CompletableFuture<Void> runAfterBoth(CompletionStage<?> other, Runnable action) // this나 other 둘 중 하나라도 완료하면 실행 <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn) CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action) CompletableFuture<Void> runAfterEither(CompletionStage<?> other, Runnable action) // this 예외 발생/완료 후 실행 <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn) CompletionStage<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) // this 예외 발생 시 실행 CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn) default CompletionStage<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn) T join() // 종료되면 결과 값 반환, 또는 발생한 예외 던지기 // 예외는 CompletionException이고, 기저 예외를 cause로 설정한다 T getNow(T valueIfAbsent) // 종료되었다면 결과 값 반환, 또는 발생한 예외 던지기. 아니면 valueIfAbsent 반환 boolean complete(T value) // 종료되지 않았다면 get()과 연관 메서드들의 반환값을 value로 설정 // 이 호출로 CompletableFuture가 종료하면 true 반환 CompletableFuture<T> completeAsync(Supplier<? extends T> supplier) // 이 CompletableFuture를 supplier의 결과값으로 종료한다 CompletableFuture<T> orTimeout(long timeout, TimeUnit unit) // 이 CompletableFuture가 주어진 시간 내에 종료되지 않은 경우, TimeoutException으로 예외 종료한다 CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit) // 이 CompletableFuture가 주어진 시간 내에 종료되지 않은 경우, value로 종료한다 boolean completeExceptionally(Throwable ex) // 종료되지 않았다면 get()과 연관 메서드들이 주어진 예외를 던지도록 한다 // 이 호출로 CompletableFuture가 종료하면 true 반환 boolean isCompletedExeptionally() void obtrudeValue(T value) // 강제로 get()과 연관 메서드들의 반환값 설정. 에러 복구를 위해 설계됨 // + obtrudeException int getNumberOfDependents() // 종료 대기중인 CompletableFuture의 개수 추정 // 동기화가 아니라, 시스템 모니터링을 위해 설계됨 CompletableFuture<T> copy() // 정상적으로 종료되었다면, 같은 값을 갖는 종료된 CompletableFuture 반환 // 예외 종료되었다면, 해당 예외를 원인으로 한 CompletionException으로 예외 종료된 CompletableFuture 반환 CompletionStage<T> minimalCompletionStage() // CompletionStage에 정의된 메서드만 이용 가능 // 재정의되지 않았다면 toCompletableFuture() 메서드를 통해 다시 다른 메서드에 접근 가능

Executor

전달받은 Runnable을 실행하는 객체. Executor 자체가 스레드의 병행성을 부여하진 않으며, 구현체에서 다른 스레드 공간을 마련해주어야 한다

ExecutorService

Executor + Runnable 관리 기능

↓ java

void shutdown() // 작업을 더 이상 받지 않는다. 이전에 추가된 것은 마저 실행한다 List<Runnable> shutdownNow() // 실행중인 모든 작업을 중지. 실행 대기중이었던 작업들은 반환 boolean isTerminated() // shutdown, shutdownNow 호출 이후 모든 작업이 끝났는지 여부 boolean awaitTermination(long timeout, TimeUnit unit) // shutdown 요청 후 모든 작업이 종료되기를 기다리며 블록한다. timeout 발생한 경우 false 반환 <T> Future<T> submit(Callable<T> task) // 결과를 반환하는 작업을 등록한다. 작업이 성공적으로 종료되면 Future::get으로 결과를 확인할 수 있다 <T> Future<T> submit(Runnable atask, T result) // 작업을 등록한다. 작업이 성공적으로 종료되면 Future::get으로 result를 얻을 수 있다 Futur<?> submit(Runnable task) // 작업을 등록한다. 작업이 성공적으로 종료되면 Future::get은 null을 반환한다 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) // 모든 작업이 종료되면 Future 리스트를 반환한다. 따라서 리스트 안의 각 Future::isDone은 true다 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timout, TimeUnit unit) // 모든 작업이 종료되거나 timeout이 발생하면 반환. 리스트 안의 각 Future::isDone은 true. timeout 발생 시 완료되지 않은 작업들은 취소된다 <T> T invokeAny(Collection<? extends Callable<T>> tasks) // 성공적으로 완료된 첫 작업의 결과를 반환한다. 완료되지 않은 작업들은 취소된다 <T> T invokeAny(Collection<? extends Callable<>> tasks, long timeout, TimeUnit unit) // timeout되면 TimeoutException 발생

ScheduledExecutorService

↓ java

ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) // 주어진 delay 이후 command가 1회 실행되도록 한다 ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) // 반복되는 작업은 반환된 Future를 통해 취소할 수 있다 ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) // scheduleAtFixedRate와 달리, 이전 작업이 완료된 후 다음 작업이 시작된다

ThreadPoolExecutor

  1. 스레드 풀 각 스레드들이 서로 다른 작업을 실행
  2. corePoolSize
  3. 이 값에 도달할 때까지 신규 작업에 대해 신규 스레드 할당

  4. maxPoolSize
  5. 대기 중인 스레드가 없으면, 이 값에 도달할 때까지 신규 작업에 대해 신규 스레드 할당

  6. keepAliveTime
  7. corePoolSize를 초과한 스레드들은 대기 상태가 이 값을 초과하면 종료된다. allowCoreThreadTimeOut() 메서드로 코어 스레드에도 적용할 지 설정 가능

  8. Queuing
    • 처리를 기다리는 작업들은 BlockingQueue에서 대기한다
    • corePoolSize 이상의 스레드가 활성 상태라면 작업은 우선 큐에 진입된다. 큐에 자리가 없으면 신규 스레드가 생성되어 작업을 처리한다
    • 큐에 자리도 없고 활성 스레드 수가 maximumPoolSize와 같다면 추가 작업은 거부된다
    • 큐잉 전략 1. Direct handoff
    • SynchronousQueue. 작업 가능한 스레드가 없으면 신규로 생성한다. 제한없는 maximumPoolSize 필요

    • 큐잉 전략 2. Unbounded queue
    • 무제한으로 큐에 작업을 추가하므로, 활성 스레드의 수는 항상 corePoolSize 이하

    • 큐잉 전략 3. Bounded queue
    • 큐의 크기와 maxPoolSize의 적절한 trade off 필요

  9. Rejected tasks
    • 거부된 작업에 대하여 RejectedExecutionHandler::rejectedExecution 메서드가 실행된다
    • ThreadPoolExecutor.AbortPolicy(defaullt) : 핸들러가 RejectedExecutionException 발생
    • ThreadPoolExecutor.CallerRunsPolicy : 작업을 제출한 스레드가 직접 작업을 실행한다
    • ThreadPoolExecutor.DiscardPolicy : 거부된 작업은 버려진다
    • ThreadPoolExecutor.DiscardOldestPolicy : 신규 작업이 아닌, 큐에서 가장 오래된 작업이 버려진다. 신규 작업은 다시 시도된다
  10. Hook methods
  11. beforeExecute, afterExecute, terminated 메서드를 재정의하여 작업 전후에 필요한 부분을 실행할 수 있다

↓ java

void execute(Runnable command) // command를 언젠가 실행한다. 작업 스레드가 실행하지 못하면, RejectedExecutionHandler가 처리한다 // ↔ remove void shutdown() // 순차적 종료 절차에 진입한다. 추가 작업은 받지 않고, 이미 제출된 작업들은 마저 처리한다 List<Runnable> shutdownNow() // 대기 중인 작업에 더해 실행 중인 작업들도 모두 중지한다. 대기중이었던 작업들은 리스트로 반환한다 // 실행 중인 작업들에 유예 시간을 주고 싶다면 ExecutorService::awaitTermination 이용 boolean isTerminating() // shutdown 또는 shutdownNow 메서드가 호출되었지만, 아직 중지가 완료되지 않았다면 true void setThreadFactory(ThreadFactory threadFactory) // + set/getRejectedExecutionHandler, set/getCorePoolSize, set/getMaximumPoolSize, set/getKeepAliveTime BlockingQueue<Runnable> getQueue() // 직접 조작하진 말고, 모니터링/디버깅 용도로 이용함이 바람직하다 int getPoolSize() // 현재 풀 안의 스레드 수 반환 int getActiveCount() // 현재 실행 중인 스레드 수 추정치 반환 int getLargestPoolSize() // 풀에 동시에 존재했던 스레드 최대 개수 반환 long getTaskCount() // 실행 스케쥴된 작업의 총 개수의 근사치 반환 long getCompletedTaskCount() // 실행 완료된 작업의 총 개수의 근사치 반환

ScheduledThreadPoolExecutor

↓ java

void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) // 기본값 false. true면 shutdownNow가 호출되거나 이 정책이 false가 될 때까지 주기 작업을 계속 실행한다 void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) // 기본값 true. true면 shutdownNow가 호출되거나 종료 후 이 정책이 false가 되기 전까지는 지연 작업을 실행한다 void setRemoveOnCancelPolicy(boolean value) // 기본값 false. 취소된 작업을 즉시 큐에서 제거할 것인지, 또는 해당하는 딜레이 후 제거할 것인지 설정

CompletionService<V>

  • 생산자가 작업들을 추가하면, 소비자는 그것이 완료된 순서대로 이용할 수 있다
  • 구현체 : ExecutorCompletionServiceExecutorCompletionService

↓ java

Future<V> submit(Callable<V> task) Future<V> submit(Runnable task, V result) Future<V> take() // 완료된 작업을 가져온다. 없으면 대기한다 Future<V> poll() // 완료된 작업을 가져온다. 없으면 null Futur<V> poll(long timeout, TimeUnit unit)

Executors

↓ java

static ExecutorService newFixedThreadPool(int nThreads) // 최대 동시 실행 가능한 스레드 수 제한. 나머지 스레드는 큐에서 대기. 스레드들은 명시적으로 shutdown되기 전까지 풀에 존재한다 static ExecutorService newWorkStealingPool() // 사용 가능한 프로세서 수를 parallelism level로 이용. 반환되는 객체는 ForkJoinPool 인스턴스 static ExecutorService newCachedThreadPool() // 스레드 재사용. 60초 동안 이용되지 않으면 풀에서 삭제된다 static ScheduledExecutorService newSingleThreadScheduledExecutor() static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

리액티브 스트림

↓ java

interface Flow.Publisher<T> { void subscribe(Flow.Subscriber<? super T> subscriber) }

Publisher 규칙

  1. Publisher가 Subscriber에 onNext로 신호를 보낸 횟수 <= Subscriber가 Subscription으로 보낸 request의 횟수
  2. 이 규칙은 onNext의 호출에 대하여, 선행되는 request가 항상 존재함을 함의한다

  3. Publisher가 onNext로 신호를 보낸 횟수가 request보다 적은 경우, Subscription을 onComplete 또는 onError로 종결한다
  4. 이 규칙은 request에 대한 onNext가 항상 존재하지는 않음을 명시한다

  5. onSubscribe, onNext, onError, onComplete 신호는 직렬적이어야 한다
  6. 결코 다른 신호와 중첩되는 시점이 있어서는 안 된다

  7. Publisher의 실패는 반드시 onError로 보내야 한다
  8. 스트림이 정상적으로 종결된 경우 Publisher는 반드시 onComplete 신호를 보내야 한다
  9. Publisher가 onError, onComplete 신호를 보낸 경우, Subscription은 반드시 취소된 것으로 간주되야 한다
  10. 종료 상태(onError, onCompletion)에서 추가적인 신호의 발생은 절대 없다
  11. Subscription이 취소된 경우, 추가적인 신호 전달은 절대 없다
  12. Publisher.subscribe 안에서 onSubscribe를 반드시 호출해야 하며, 반드시 다른 신호를 보내기 전에 선행되어야 한다. 또, 이 경우 메서드는 반드시 정상 종결되어야 한다
  13. Subscriber.onSubscribe 호출 시 null 검사는 필요없다. NullPointerException이 발생하게 내버려두면 된다

  14. Publisher.subscribe는 여러 번 호출될 수 있지만, 하나의 Subscriber로부터는 최대 한 번만 호출되어야 한다
  15. Publisher는 여러 Subscriber들에 대한 멀티캐스트를 지원할 수 있다

↓ java

interface Flow.Subsbriber<T> { void onSubscribe(Flow.Subscription) onNext(T) onError(Throwable) onComplete(Void) }

Subscriber 규칙

  1. Subscriber는 onNext 신호를 받고 싶다면 반드시 먼저 request 신호를 보내야 한다
  2. 신호를 보낼 때, Publisher의 완료를 기다리지 말고 비동기적으로 전달함이 권장된다
  3. onComplete, onError 메서드는 절대 Subscription, Publisher 어느쪽의 메서드도 호출해선 안 된다
  4. onComplete, onError 신호를 받은 이후부터, Subscription은 반드시 취소로 간주되어야 한다
  5. 유효한 Subscription이 존재한다면, 추가적인 onSubscribe 신호에 대해 반드시 cancel을 호출해야 한다
  6. 하나의 Subscriber는 둘 이상의 Publisher를 동시에 구독하지 않아야 한다

  7. 더 이상 필요없다면 반드시 Subscription.cancel을 호출해야 한다
  8. Subscription으로 보내는 신호들은 반드시 직렬적이어야 한다
  9. 결코 동시에 두 신호를 보내는 순간은 없어야 한다

  10. cancel의 호출은 대기 중인 작업의 취소를 보장하지 않는다. cancel 이후 추가적인 onNext 신호에 대해 준비되어야 한다
  11. 아무런 request를 보내지 않았더라도, onComplete, onError 신호에 대해 준비되어야 한다
  12. onSubscribe, onNext, onError, onComplete는 인자가 null이 아닌 이상 반드시 정상 종료되어야 한다
  13. Subscriber의 실패는 Subscription.cancel로만 통지할 수 있다. 이 규칙이 지켜지지 않은 경우, Subscription은 반드시 취소로 간주되어야 한다

↓ java

interface Flow.Subscription { void request(long) cancel(Void) }

Subscription 규칙

  1. request, cancel은 반드시 Subscriber가 호출해야 한다
  2. onNext, onSubscribe 안에서 동기적으로 request를 호출하는 것은 허용된다
  3. cancel의 호출은 멱등이어야 하고, 그 실행은 스레드-안전해야 한다
  4. Subscription이 취소됐다면, 이후의 request, cancel의 호출은 아무 작업도 하지 않아야 한다
  5. 0이하에 대한 request 호출은 onError로 IllegalArgumentException을 보내야 한다
  6. Subscription이 취소됐다면, Publisher는 Subscriber에 대한 모든 참조를 제거해야 한다
  7. request, cancel은 항상 정상 종료되어야 한다
  8. Subscription은 반드시 무제한적인 request 호출을 허용해야 한다. n == Long.MAX_VALUE

SubmissionPublisher<T>

↓ java

public SubmissionPublisher(Executor executor, int maxBufferCapacity, BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> handler) // executor : 비동기적으로 구독자에게 전달하는 데 쓰일 Executor // maxBufferCapacity : 각 구독자에 대한 버퍼의 한도. 실제 한도는 getMaxBufferCapacity()로 확인 // handler : null이 아니면 onNext에서 발생한 예외를 처리 public SubmissionPublisher() // executor = ForkJoinPool.commonPool() // maxBufferCapacity = Flow.defaultBufferSize() // handler = null int submit(T item) // 각 구독자에게 비동기적으로 item을 보낸다(onNext). lag(배포된 item 중에 아직 소비되지 않은 개수) 추정치를 반환한다 int offer(T item, BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) // 가능하다면 각 구독자에게 비동기적으로 item을 보낸다(onNext). 리소스 초과(버퍼가 가득 찼다던지)로 실패한 경우 onDrop이 실행된다. onDrop이 true를 반환하면 onNext를 다시 시도한다 // 반환값이 음수인 경우 drop된 구독자 수를 의미하고, 그 외의 경우 lag(배포된 item 중에 아직 소비되지 않은 개수) 추정치를 의미한다 long estimateMinimumDemand() // 각 구독자들이 요청한 아이템 수 중, 아직 공급되지 않은 수의 최소값(추정치) 반환 int estimateMaximumLag() // 각 구독자들에 보낸 아이템 중 아직 소비되지 않은 수의 최대값(추정치) 반환 CompletableFuture<Void> consume(Consumer<? super T> consumer) // 배포된 모든 아이템에 대해 consumer 실행. 정상적으로 모두 실행되면 onComplete가 호출되고, CompletableFuture도 정상 종료된다

Blocking 컬렉션

BlockingQueue<E>

  1. 기본적으로 스레드-안전하지만, addAll 따위의 bulk 연산은 특별히 표시되지 않는 한 그렇지 않다
  2. 요소를 획득할 때, 큐가 비어있는 경우 블로킹. 요소를 추가할 때, 큐에 빈 자리가 있을 때까지 블로킹
예외 발생특별값 반환블로킹시간 제한
Insertadd(E)offer(E)put(E)offer(E,long,TimeUnit)
Removeremove()poll()take()poll(long,TimeUnit)
Examineelement()peek()--

↓ java

int remainingCapacity() // 블로킹없이 삽입 가능한 요소의 수. 오차가 있을 수 있다 int drainTo(Collection<? super E> c) // 모든 원소를 c로 옮긴다

ArrayBlockingQueue<E>

  1. 크기가 고정된 기저 배열을 이용한 BlockingQueue
  2. 기본적으로 삽입을 기다리는 스레드들 사이의 처리 순서는 보장되지 않지만, fairness를 설정하면 FIFO 순으로 처리된다
  3. Collection, Iterator의 모든 선택적 연산을 구현했다

LinkedBlockingQueue<E>

  1. 크기를 고정할 수 있는 연결된 BlockingQueue
  2. Collection, Iterator의 모든 선택적 연산을 구현했다

PriorityBlockingQueue<E>

  1. 크기 제한 없고, PriorityQueue와 비슷한 정렬을 이용한 BlockingQueue
  2. Collection, Iterator의 모든 선택적 연산을 구현했다
  3. 다만 iterator(), spliterator()로 제공되는 인스턴스들은 순회하는 순서를 보장하지 않는다. 순차적인 순회를 원한다면 Arrays.sort(queue.toArray())를 고려할 것

  4. 같은 우선순위의 원소 사이의 정렬은 정의되지 않았다

SynchronousQueue<E>

서로 연관된 삽입 연산과 삭제 연산 한 쌍이 동시에 존재할 때까지 연산을 블로킹한다

DelayQueue<E extends Delayed>

  1. Delayed 요소들로 구성된, 크기 제한없는 BlockingQueue. 요소의 지연 시간이 만료되어야 큐로부터 획득 가능하다
  2. 요소가 만료됐음은 getDelay(TimeUnit.NANOSECONDS) 리턴값이 0 이하일 때로 판정

  3. Collection, Iterator의 모든 선택적 연산을 구현했다

BlockingDeque<E>

요소를 획득할 때, 덱이 비어있는 경우 블로킹. 요소를 추가할 때, 덱에 빈 자리가 있을 때까지 블로킹

예외 발생특별값 반환블로킹시간 제한
InsertaddFirst(E)
addLast(E)
offerFirst(E)
offerLast(E)
putFirst(E)
putLast(E)
offerFirst(E,long,TimeUnit)
offerLast(E,long,TimeUnit)
RemoveremoveFirst()
removeLast()
pollFirst()
pollLast()
takeFirst()
takeLast()
pollFirst(long,TimeUnit)
pollLast(long,TimeUnit)
ExaminegetFirst()
getLast()
peekFirst()
peekLast()
--

LinkedBlockingDeque<E>

  1. 크기를 제한할 수 있는 BlockingDeque
  2. Collection, Iterator의 모든 선택적 연산을 구현했다

TransferQueue<E>

  1. 생산자가 소비자가 소비할 때까지 대기할 수 있는 BlockingQueue
  2. BlockingQueue와 SynchronousQueue 기능 모두를 선택적으로 이용할 수 있다

↓ java

void transfer(E e) // 소비자에게 e를 전달한다. 소비자가 소비할 때까지 대기한다 boolean tryTransfer(E e) // 대기 중인 소비자에게 e를 전달한다. 대기 중인 소비자가 없다면 즉시 false를 반환한다 boolean tryTransfer(E e, long timeout, TimeUnit unit) // timeout이 지나도록 대기 중인 소비자가 없다면 false를 반환한다

LinkedTransferQueue<E>

  1. 크기 제한없고 연결된 TransferQueue
  2. size 계산에 순회가 필요하므로 정확하지 않을 수 있다
  3. addAll 따위의 bulk 연산은 원자적으로 실행되지 않을 수 있다
  4. Collection, Iterator의 모든 선택적 연산을 구현했다

Non-Blocking 컬렉션

CopyOnWriteArrayList<E>

  1. 스레드-안전한 ArrayList
  2. add, set 등의 연산마다 새로운 배열을 만든다. 따라서 일반적인 용도로는 매우 나쁘다
  3. iterator는 생성된 시점의 snapshot을 순회함이 보장되지만, iterator를 통한 요소의 변경은 불가하다

CopyOnWriteArraySet<E>

모든 연산에 CopyOnWriteArrayList를 사용하는 Set

ConcurrentLinkedQueue<E>

  1. 크기 제한 없고, 스레드-안전한 연결된 Queue
  2. size 계산에 순회가 필요하므로, 오차가 있을 수 있다
  3. addAll 따위의 bulk 연산은 원자적으로 실행되지 않을 수 있다
  4. Collection, Iterator의 모든 선택적 연산을 구현했다

ConcurrentlinkedDeque<E>

  1. 크기 제한 없고, 스레드-안전한 연결된 Deque
  2. size 계산에 순회가 필요하므로, 오차가 있을 수 있다
  3. addAll 따위의 bulk 연산은 원자적으로 실행되지 않을 수 있다
  4. Collection, Iterator의 모든 선택적 연산을 구현했다

ConcurrentMap<K, V>

  1. 스레드-안전, 작업의 원자성 보장
  2. Map의 각 연산, Map이 반환하는 컬렉션들의 연산 모두 재정의해야 한다

ConcurrentNavigableMap<K, V>

NavigableMap 연산을 지원하는 ConcurrentMap

ConcurrentHashMap<K, V>

  1. 읽기 연산에 대해서는 완전한 동시성을, 갱신 연산에 대해서는 높은 수준의 동시성을 제공
  2. Hashtable의 모든 연산을 구현했다. 읽기 연산에 대해 원소를 잠그지는 않으며, 테이블 전체를 잠그는 기능 또한 없다. 가져간 원소를 사용하려고 하는 시점에는 맵에서 제거됐을 수도 있다

  3. 카운터로 사용할 수 있다. 예. map.computeIfAbsent(key, x -> new LongAdder()).increment();
  4. Map, Iterator의 모든 선택적 연산을 구현했다
  5. 3가지 Bulk 연산을 지원한다 : forEach, search, reduce
  6. 인자로 받은 parallelismThreshold보다 맵이 작다고 판단되면 순차적으로 원소를 소비, 그 외엔 병렬로 소비. 1이면 최대 병렬성, Long.MAX_VALUE면 병렬 X

  7. 모든 작업 메서드의 매개변수는 non-null이어야 한다

↓ java

long mappingCount() // 크기가 매우 큰 경우, Map.size() 대신 이용 void forEach(long parallelismThreshold, BiConsumer<? super K, ? super V> action) // + forEachKey, forEachValue, forEachEntry <U> U search(long parallelismThreshold, BiFunction<? super K, ? super V, ? extends U> searchFunction) // 엔트리에 searchFunction를 적용했을 때 결과가 non-null인 것 하나 반환. 없으면 null // + searchKeys, searchValues, searchEntries <U> U reduce(long parallelismThreshold, BiFunction<? super K, ? super V, ? extends U> transformer, BiFunction<? super U, ? super U, ? extends U> reducer) // + reduceToDouble ~ Int, reduceKeys, reduceKeysToDouble ~ Int, reduceValues, reduceValuesToDouble ~ Int, reduceEntries, reduceEntriesToDouble ~ Int

ConcurrentSkipListMap<K,V>

  1. ConcurrentNavigableMap 구현체. 평균 log(n) 시간이 소요되는, 스레드-안전한SkipList 구현을 이용
  2. 오름차순 정렬된 뷰와 이터레이터가 내림차순보다 빠르다
  3. putAll과 같은 bulk 연산은 원자적으로 종료되지 않을 수 있다
  4. Map, Iterator의 모든 선택적 연산을 구현했다

ConcurrentSkipListSet<E>

ConcurrentSkipListMap을 이용한 NavigableSet

실행 기법

Semaphore

  1. 제한된 수의 접근 권한을 acquire()로 획득, release()로 반환
  2. fairness : acquire()호출 순서대로 권한 획득. default false

↓ java

void acquire() // 권한을 하나 요구한다. 권한을 얻을 때까지 대기하며, 대기 중인 스레드는 인터럽트될 수 있다 void acquireUninterruptibly() // 대기 중일 때 인터럽트되더라도 계속 대기한다. 인터럽트되지 않았을 경우와 권한을 얻는 시기가 달라질 수 있다 boolean tryAcquire() void release() int availablePermits() int drainPermits() // 가용한 모든 권한을 얻는다. 만약 음수라면 release하여 0으로 맞춘다 boolean isFair() final boolean hasQueuedThreads() final int getQueueLength()

CountDownLatch

count가 0일 될때까지(원하는 작업들이 완료될 때까지), 1개 이상의 스레드가 대기하는 동기화 제공

↓ java

public CountDownLatch(int count) void await() // count가 0이 될때까지 대기한다. 대기 중에 인터럽트될 수 있다 boolean await(long timeout, TimeUnit unit) // 대기 중에 timeout을 넘으면 즉시 false 반환 void countDown() // --count, count가 0이면 대기하는 모든 스레드를 깨운다

CyclicBarrier

스레드들이 공통의 목적이 달성되기까지 함께 대기. 그 목적을 barrier라고 하며, barrier를 재사용할 수 있어 cyclic하다

↓ java

public CyclicBarrier(int parties, Runnable barrierAction) // barrierAction : barrier를 넘을 때 실행. 지정하지 않은 경우, 대기하던 스레드를 깨우기만 한다 int getParties() int await() // 마지막 스레드가 await을 호출할 때까지 대기한다. 대기 중에 인터럽트될 수 있다 // 현재 스레드의 대기 순번 반환. getParties() - 1이 첫 번째, 0이 마지막 스레드 int await(long timeout, TimeUnit unit) // timeout을 초과하여 대기하면 barrier는 부서진다 boolean isBroken() void reset() // barrier를 초기 상태로 재설정한다. 이미 대기 중인 스레드가 있다면 BrokenBarrierException 발생 /// 부서진 barrier를 재사용하려면 별도의 동기화가 필요하므로, 차라리 새로 하나 만들자 int getNumberWaiting()

Exchanger<V>

두 스레드가 같은 시점에 값을 서로 교환하도록 해준다

↓ java

V exchange(V x) // 다른 스레드가 같은 지점에 도달하기까지 기다렸다가, 서로 값을 교환한다 V exchange(V x, long timeout, TimeUnit unit) // timeout 초과 시 TimeoutException 발생

Phaser

  1. 재사용 가능한 동기화 barrier. CyclicBarrier, CountDownLatch 기능에 더해 보다 유연한 메서드 제공
  2. CyclicBarrier와 다르게 각 회전마다 총 대기하는 스레드 수가 다를 수 있다
  3. 현재 phase가 완료되기 전에 미리 이후의 phase(들)을 등록할 수 있다. 각 phase는 0부터 시작하는 번호를 가진다(Integer.MAX_VALUE에 도달하면 다음은 다시 0)

  4. 계층 구조를 구성할 수 있다. 자식 Phaser의 parties가 0이 아니게 되는 순간 parent에 등록되고, 0이 되는 순간 parent에서 제거된다

↓ java

public Phaser(int parties) // parties : 다음 phase로 넘어가기 위해 필요한 수 public Phaser(Phaser parent, int parties) int register() // 새로운 phase를 등록한다 // + bulkRegister int arrive() // 현재 phaser에 도착한다. 다른 스레드의 도착을 기다리지는 않는다. 현재 phase 번호를 반환한다(종료됐다면 음수) int arriveAndDeregister() // 현재 phaser에 도착하고, 이후 phase에서는 자신이 빠짐을 알린다 int arriveAndAwaitAdvance() // 현재 phaser에 도착하고, 현재 phase의 모든 구성원이 도착할 때까지 기다린다 == awaitAdvance(arrive()) int awaitAdvance(int phase) + awaitAdvanceInterruptibly // 지정한 번호의 phase의 모든 구성원이 도착할 때까지 기다린다. 현재 phase의 번호와 다르거나, phaser가 종료된 경우엔 즉시 반환한다 void forceTermination() // 계층 구조에 속해있다면, 모든 phaser가 종료된다 final int getPhase() // 현재 phase 번호를 반환한다. Phaser가 종료됐다면 음수(마지막 phase 번호 + Integer.MAX_VALUE)를 반환한다

TimeUnit

↓ java

NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS long convert(long sourceDuration, TimeUnit sourceUnit) void timeWait(Object obj, long timeout) // timeout만큼 obj.wait() void timedJoin(Thread thread, long timeout) // timeout만큼 Thread.join() void sleep(long timeout)

java.util.concurrent.atomic

Package Summary

  1. 변수 하나에 대한 잠금 없는 스레드-안전성을 제공한다
  2. VarHandle을 통해 변수를 원자적으로 접근한다
  3. AtomicBoolean, AtomicInteger 등은 일반적인 Boolean, Integer 등을 대신할 수 없다
  4. 메모리 장벽을 만나면 CPU 코어의 캐시값이 RAM으로 반영된다

VarHandle

  1. java.lang.invoke 패키지 멤버임
  2. 하나의 변수, 매개변수, 필드 등에 대한 동적인 타입 참조. plain 읽기/쓰기, volatile 읽기/쓰기, compare-and-set 접근을 지원한다
  3. ↓ java

    class AtomInt { private static final VarHandle V; private volatile int value = 0; static { VarHandle v = null; try { v = MethodHandles.lookup().findVarHandle(AtomInt.class, "value", int.class); } catch (Exception e) { } V = v; } public int getAndSet(int newValue) { int v; do { v = (int) V.getVolatile(this); } while (V.compareAndSet(this, v, newValue) == false); return v; } } public class StandAloneTest { public static void main(String[] args) throws Exception { var i = new AtomInt(); IntStream.range(0, 100).parallel() .forEach(n -> System.out.printf("Before : %d, After : %d\n", i.getAndSet(n), n)); } }

↓ java

final Object get(Object... args) // 변수가 non-volatile인 것처럼 읽는다(= plain read) final void set(Object... args) // 변수가 non-volatile, non-final인 것처럼 쓴다(= plain write) final Object getVolatile(Object... args) // 변수가 volatile인 것처럼 읽는다 final void setVolatile(Object... args) // 변수가 volatile인 것처럼 쓴다 final Object getOpaque(Object... args) // Opaque : Program order 순서대로 접근한다. 다른 스레드와의 조율은 없다 // + setOpaque final Object getAcquire(Object... args) // 같은 변수에 대해 이어지는 load/store 연산이 이 접근보다 먼저 발생하지 않는다 final void setRelease(Object... args) // 같은 변수에 대한 이전의 load/store 연산이 이 접근보다 나중에 발생하지 않는다 final boolean compareAndSet(Object... args) // 원자적으로 다음이 실행된다. getVolatile과 동일한 문맥으로 가져온 값(witness value)이 expectedValue와 동일(==)하면 setVolatile과 동일한 문맥으로 newValue 설정 후 true 반환, 그 외엔 false 반환 final Object compareAndExchange(Object... args) // 원자적으로 다음이 실행된다. getVolatile과 동일한 문맥으로 가져온 값(witness value)이 expectedValue와 동일(==)하면 setVolatile과 동일한 문맥으로 newValue 설정. 반환값은 witness value final Object compareAndExchangeAcquire(Object... args) // 원자적으로 다음이 실행된다. getAcquire와 동일한 문맥으로 가져온 값(witness value)이 expectedValue와 동일(==)하면 set와 동일한 문맥으로 newValue 설정. 반환값은 witness value final Object compareAndExchangeRelease(Object... args) // 원자적으로 다음이 실행된다. get와 동일한 문맥으로 가져온 값(witness value)이 expectedValue와 동일(==)하면 setRelease와 동일한 문맥으로 newValue 설정. 반환값은 witness value final boolean weakCompareAndSetPlain(Object... args) // 다음이 실행된다. get과 동일한 문맥으로 가져온 값(witness value)이 expectedValue와 동일(==)하면 set과 동일한 문맥으로 newValue 설정 후 true 반환. 그 외엔 false final boolean weakCompareAndSet(Object... args) + ~Acquire, ~Release // 다음이 실행된다. getVolatile과 동일한 문맥으로 가져온 값(witness value)이 expectedValue와 동일(==)하면 setVolatile과 동일한 문맥으로 newValue 설정 후 true 반환. 그 외엔 false final Object getAndSet(Object... args) + ~Acquire, ~Release // 원자적으로 다음이 실행된다. getVolatile과 동일한 문맥으로 값(witness value)을 가져오고, setVolatile과 동일한 문맥으로 newValue 설정 후 witness value 반환 final Object getAndAdd(Object... args) + ~Acquire, ~Release // 원자적으로 값을 더한 후 이전 값 반환 final Object getAndBitwiseOr(Object... args) // 원자적으로 OR 연산 수행 후 이전 값 반환 // + ~Acquire, ~Release, getAndBitwiseAnd~, getAndBitwiseXor~ static void acquireFence() // 장벽 이전의 load 연산이 장벽 이후의 load/store 뒤로 재배치되지 않음 static void fullFence() // 장벽 이전의 load/store 연산이 장벽 이후의 load/store 뒤로 재배치되지 않음 static void releaseFence() // 장벽 이전의 load/store 연산이 장벽 이후의 store 뒤로 재배치되지 않음 static void loadLoadFence() // 장벽 이전의 load 연산이 장벽 이후의 load 뒤로 재배치되지 않음 static void storeStoreFence() // 장벽 이전의 store 연산이 장벽 이후의 store 뒤로 재배치되지 않음

VarHandle.AccessMode

GETVarHandle.get
SETVarHandle.set
GET_VOLATILEVarHandle.getVolatile
SET_VOLATILEVarHandle.setVolatile
GET_ACQUIREVarHandle.getAcquire
SET_RELEASEVarHandle.setRelease
GET_OPAQUEVarHandle.getOpaque
SET_OPAQUEVarHandle.setOpaque
COMPARE_AND_SETVarHandle.compareAndSet
COMPARE_AND_EXCHANGEVarHandle.compareAndExchange
COMPARE_AND_EXCHANGE_ACQUIREVarHandle.compareAndExchangeAcquire
COMPARE_AND_EXCHANGE_RELEASEVarHandle.compareAndExchangeRelease
WEAK_COMPARE_AND_SET_PLAINVarHandle.weakCompareAndSetPlain
WEAK_COMPARE_AND_SETVarHandle.weakCompareAndSet
WEAK_COMPARE_AND_SET_ACQUIREVarHandle.weakCompareAndSetAcquire
WEAK_COMPARE_AND_SET_RELEASEVarHandle.weakCompareAndSetRelease
GET_AND_SETVarHandle.getAndSet
GET_AND_SET_ACQUIREVarHandle.getAndSetAcquire
GET_AND_SET_RELEASEVarHandle.getAndSetRelease
GET_AND_ADDVarHandle.getAndAdd
GET_AND_ADD_ACQUIREVarHandle.getAndAddAcquire
GET_AND_ADD_RELEASEVarHandle.getAndAddRelease
GET_AND_BITWISE_ORVarHandle.getAndBitwiseOr
GET_AND_BITWISE_OR_RELEASEVarHandle.getAndBitwiseOrRelease
GET_AND_BITWISE_OR_ACQUIREVarHandle.getAndBitwiseOrAcquire
GET_AND_BITWISE_ANDVarHandle.getAndBitwiseAnd
GET_AND_BITWISE_AND_RELEASEVarHandle.getAndBitwiseAndRelease
GET_AND_BITWISE_AND_ACQUIREVarHandle.getAndBitwiseAndAcquire
GET_AND_BITWISE_XORVarHandle.getAndBitwiseXor
GET_AND_BITWISE_XOR_RELEASEVarHandle.getAndBitwiseXorRelease
GET_AND_BITWISE_XOR_ACQUIREVarHandle.getAndBitwiseXorAcquire

AtomicBoolean

↓ java

final boolean get() // VarHandle::getVolatile final boolean compareAndSet(boolean expectedValue, boolean newValue) // VarHandle::compareAndSet boolean weakCompareAndSetPlain(boolean expectedValue, boolean newValue) // VarHandle::weakCompareAndSetPlain final void set(boolean newValue) // VarHandle::setVolatile final void lazySet(boolean newValue) // VarHandle::setRelease final boolean getAndSet(boolean newValue) // VarHandle::getAndSet final boolean getPlain() // VarHandle::get final void setPlain(boolean newValue) // VarHandle::set final boolean getOpaque() // VarHandle::getOpaque final void setOpaque(boolean newValue) // VarHandle::setOpaque final boolean getAcquire() // VarHandle::getAcquire final void setRelease(boolean newValue) // VarHandle::setRelease final boolean compareAndExchange(boolean expectedValue, boolean newValue) // 메모리 영향은 VarHandle::compareAndExchange와 같다 // + ~Acquire, ~Release final boolean weakCompareAndSetVolatile(boolean expectedValue, boolean newValue) // 메모리 영향은 VarHandle::weakCompareAndSet와 같다 // + ~Acquire, ~Release

AtomicIntegerArray

인덱스를 추가로 받는 것 외에, 지원하는 메서드들은 AtomicInteger와 같다

AtomicIntegerFieldUpdater<T> + AtomicLongFieldUpdater, AtomicReferenceFieldUpdater

  1. 지정된 volatile int 필드를 atomic 연산으로 갱신
  2. 해당 필드를 단일 업데이터로만 접근한다면, compareAndSet 메서드들이 원자적으로 작동됨이 보장된다

  3. 지원하는 메서드는 AtomicInteger와 유사하다

AtomicMarkableReference<V>

원자적으로 갱신되는 마커 bit와 객체 참조 쌍

↓ java

public AtomicMarkableReference(V initialRef, boolean initialMark) V getReference() V get(boolean[] markHolder) // 값 V를 반환하고, markHolder[0]에는 마커 bit 설정 boolean compareAndSet(V expectedReference, V newReference, boolean expectedMark, boolean newMark) // 기존 참조와 마커 bit가 모두 예상과 동일(==)하다면 원자적으로 갱신하고 true 반환. 그 외엔 false // + weakCompareAndSet void set(V newReference, boolean newMark) boolean attemptMark(V expectedReference, boolean newMark) // 기존 참조가 예상과 동일(==)하다면, 마커 bit를 원자적으로 갱신하고 true 반환. 그 외엔 false

AtomicStampedReference<V>

원자적으로 갱신되는 index와 참조 쌍

↓ java

public AtomicStampedReference(V initialRef, int initialStamp) V getReference() V get(int[] stampHolder) // 값 V를 반환하고, stampHolder[0]에는 index 설정 boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) // 기존 참조와 인덱스가 예상과 동일(==)하다면 원자적으로 갱신하고 true 반환. 그 외엔 false // + weakCompareAndSet void set(V newReference, int newStamp) boolean attempStamp(V expectedReference, int newStamp) //기존 참조가 예상과 동일(==)하다면, 인덱스를 원자적으로 갱신하고 true 반환. 그 외엔 false

LongAdder

  1. 초깃값 0으로 시작하는 스레드-안전한 합계
  2. 합의 순서는 정의되지 않으므로 순서에 상관 없는 경우에 이용해야 한다

  3. + DoubleAdder

↓ java

void add(long x) void increment() void decrement() long sum() // 현재 합계 void reset() long sumThenReset()

LongAccumulator

  1. 특정 값과 특정 함수로 갱신되는 long 값 유지
  2. 주어진 accumulatorFunction은 부작용이 없어야 한다

  3. + DoubleAccumulator

↓ java

void accumulate(long x) long get() void reset() long getThenReset()

java.util.function

java.util.regex

MatchResult

정규표현식 매칭 결과. group의 의미에 대해선 Pattern 참고

↓ java

int start() // 매치된 결과의 시작 인덱스 반환 int start(int group) // group번째 매치된 결과의 시작 인덱스 반환 int end() // 매치된 결과의 마지막 글자 다음 인덱스 반환 int end(int group) // group번째 매치된 결과의 마지막 글자 다음 인덱스 반환 String group() // 이전 매치된 결과 반환 String group(int group) // group번째 매치된 결과 반환 int groupCount() // 매치된 group 개수 반환

Pattern

↓ java

public static final int UNIX_LINES // 줄끝 '\n'만 ., ^, $에서 동작. (?d) 플래그도 같은 의미 public static final int CASE_INSENSITIVE // 대소문자 구분 없음. (?i) 플래그도 같은 의미 public static final int COMMENTS // 공백과 주석 허용. 공백과 #부터 줄 끝까지의 주석이 무시된다. (?x) 플래그도 같은 의미 public static final int MULTILINE // ^, $이 각 줄의 끝을 기준으로도 작동; 기본 동작은 입력 시작과 끝에서만 작동. (?m) 플래그도 같은 의미 public static final int LITERAL // 표현식 전체를 상수 문자열 취급 public static final int DOTALL // .이 줄 끝도 포함하여 매치; 기본 동작은 줄 끝 문자는 미포함. (?s) 플래그도 같은 의미 public static final int UNICODE_CASE // CASE_INSENSITIVE 플래그가 유니코드 표준 상에서 동작한다; 기본은 US-ASCII에서만 동작. (?u) 플래그도 같은 의미 static Pattern compile(String regex) static boolean matches(String regex, CharSequence input) // 1회용 static String quote(String s) // s를 매칭할 수 있는 정규표현식 리터럴 문자열 표현을 반환 Predicate<String> asPredicate() Stream<String> splitAsStream(CharSequence input)

Line terminator

↓ java

"\n", "\r\n", "\r", "\u0085", "\u2028", "\u2029" // UNIX_LINES 모드에서는 "\n"만 줄 끝으로 인식

Groups and capturing

  • Group : 괄호로 감싸인 정규표현식 (X)
  • Capturing group : 괄호 순서에 따라 그룹에 ID가 매겨지며, 이는 나중에 참조(backreference)될 수 있다
  • 0번 그룹은 항상 전체 표현을 가리킨다 (A)(B(C))에 대하여,

    Group IDPattern
    0(A)(B(C))
    1(A)
    2(B(C))
    3(C)
  • Non-capturing group : (?:X)는 후참조(backreference)할 수 없다

Character expression

  • x, \\ : 각각 x, \에 대응
  • \0n, \0nn, \0nnn : 8진수 아스키 코드[0,255] == [00, 0377]
  • \xhh : 16진수 아스키 코드[0,255]
  • \uhhhh, \u{h...h} : 16진수 유니코드[Character.MIN_CODE_POINT, Character.MAX_CODE_POINT]
  • \N{name} : 유니코드 이름
  • \t(tab \u0009), \n(newline \u000A), \r(carriage-return \u000D), \f(form-feed \u000C), \a(alert \u0007), \e(escape \u001B), \cx(x에 관한 제어 문자)

Character class

  • [abc] : 단순 집합
  • [^abc] : 여집합
  • [a-z] : 유니코드 Range(inclusive)
  • [a-d[m-p]] == [a-dm-p] : 합집합
  • [a-z&&[def]] : 교집합
  • [a-z&&[^bc]] : 차집합(A and not(B) == A - B)

Predefined character class

  • . : 임의 문자. DOTALL 플래그가 있으면 line terminator도 매칭
  • \d : [0-9], \D : [^\d]
  • \s : 공백 문자 [ \t\n\x0B\f\r], \S : [^\s]
  • \h : 수평 공백 [ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000], \H : [^\h]
  • \v : 수직 공백 [\n\x0B\f\r\x85\u2028\u2029], \V : [^\v]
  • \w : Word character, \W : [^w]

Character class

  • \p{javaLowerCase} : Character.isLowerCase()
  • \p{javaUpperCase} : Character.isUpperCase()
  • \p{javaWhitespace} : Character.isWhitespace()
  • \p{javaMirrored} : Character.isMirrored()

Unicode class

  • \R : 임의 줄바꿈 문자열 \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]
  • \p{IsLatin} : script
  • \p{InGreek} : block
  • \p{Lu} : category
  • \p{IsAlphabetic} : binary property
  • \p{Sc} : 통화 단위
  • \P{expr} == [^\p{expr}]

Boundary matcher

  • ^ : 줄 시작, $ : 줄 끝
  • \b : 단어 경계, \B : 비단어 경계
  • \A : The beginning of the input
  • \G : The end of the previous match
  • \z : The end of the input

Greedy quantifier

    처음에 매치할 수 있는 만큼 최대한 매치. 그 다음 요소의 매칭이 없으면 백트래킹 greedy-vs-reluctant-vs-possessive-quantifiers

  • X? : X, once or not at all
  • X* : X, zero or more times
  • X+ : X, one or more times
  • X{n} : X, exactly n times
  • X{n,} : X, at least n times
  • X{n,m} : X, at least n but not more than m times

Reluctant quantifier

처음에 최소한만 매치. 그 다음 요소의 매칭이 없으면 백트래킹; X??, X*?, X+?, X{n}?, X{n,}?, X{n,m}?

Possessive quantifier

Greedy quantifier와 같지만, 백트래킹은 없다; X?+, X*+, X++, X{n}+, X{n,}+, X{n,m}+

Logical operation

  • XY : X followed by Y
  • X|Y : Either X or Y
  • (X) : X, as a capturing group

Backreference

  • \n : The n-th capturing group matched
  • \k<name> : Tthe named-capturing group "name" matched
  • ↑ 정규표현식 내에서는 위 두 가지 backreference가 가능하며, replace()에서는 $0, $1, $2, ...로 표기한다

Quotation

  • \ : Nothing, but quotes the following character
  • \Q : Nothing, but quotes all characters until \E
  • \E : Nothing, but ends quoting started by \Q

Special construct

  • (?<name>X) : X, as a named-capturing group
  • (?:X) : X, as a non-capturing group
  • (?idmsuxU-idmsuxU) : 각 플래그를 켜거나 끈다
  • (?idmsux-idmsux:X) : 주어진 플래그로 non-capturing group X를 매칭한다
  • (?=X) : Positive lookahead, (?!X) : Negative lookahead
  • (?<=X) : Positive lookbehind, (?<!X) : Negative lookbehind
  • (?>X) : Non-capturing group + Possessive

Matcher

Pattern.matcher(CharSequence)로부터 만들어지는 매칭 엔진으로, 아래 세 가지 작업을 수행한다

  1. matches() : 전체 입력에 대해 패턴 매칭
  2. lookingAt() : 입력 시작부분 패턴 매칭
  3. find() : 입력의 다음 부분 패턴 매칭

↓ java

MatchResult toMatchResult() Stream<MatchResult> results() Matcher usePattern(Pattern newPattern) Matcher reset() int start(String name) // 주어진 식별자에 해당하는 그룹의 시작 인덱스 반환 int end(String name) String group(String name) static String quoteReplacement(String s) // appendReplacement 메서드의 replacement로 사용될 s의 리터럴 표기를 반환 Matcher appendReplacement(StringBuffer sb, String replacement) // 1. 입력 소스의 append position부터 start() 전까지 sb에 추가 // 2. replacement를 sb에 추가 // 3. 현재 matcher의 append position을 end()로 설정 StringBuffer appendTail(StringBuffer sb) // 입력 소스의 append position부터를 sb에 추가 // appendReplacement 메서드를 호출한 뒤에 이를 호출하여 나머지 부분을 복사할 목적으로 만들어짐 String replaceAll(String replacement) // 입력 소스의 모든 매칭되는 부분을 replacement로 변경 String replaceAll(Function<MatchResult, String> replacer) String replaceFirst(String replacement) Matcher region(int start, int end) // 입력 소스의 특정 구간을 매칭 대상으로 하도록 초기화한다. transparency, anchoring 속성에 따라 동작이 다르다 Matcher useTransparentBounds(boolean b) // region의 경계 너머를 패턴 매칭에 보이도록 할지 여부 Matcher useAnchoringBounds(boolean b) // region의 경계에서 ^, $를 작동하게 할지 여부

java.util.stream

BaseStream<T, S extends BaseStream<T,​S>>

↓ java

Iterator<T> iterator() Spliterator<T> spliterator() boolean isParallel() S sequential() // 순차적인 스트림 반환(어쩌면 자기 자신) S parallel() // 병렬적인 스트림 반환(어쩌면 자기 자신) S unordered() // 순서 없는 스트림 반환(어쩌면 자기 자신) S onClose(Runnable closeHandler)

DoubleStream

↓ java

double sum() OptionalDouble min(), max(), average(), findFirst(), findAny() DoubleSummaryStatistics SummaryStatistics() Stream<Double> boxed()

IntStream

↓ java

static IntStream range(int startInclusive, int endExclusive) static IntStream rangeClosed(int startInclusive, int endInclusive)

Stream<T>

  1. 2가지 스트림 연산
    • Terminal Operation
    • 종결 연산. 스트림 연산 파이프라인의 마지막으로, 더 이상 스트림 연산을 수행할 수 없다

    • Intermediate Operation
    • 중간 연산. 새로운 스트림을 반환한다

  2. 2가지 중간 연산
    • Stateless Operation
    • 요소의 연산 과정에 상태의 보존이 필요 없는 경우. filter, map 등

    • Stateful Operation
    • 요소의 연산 과정에 상태의 보존이 필요한 경우. sorted, distinct 등
      이러한 연산을 사용하기 위해선 스트림 전체 인풋이 필요할 수 있으며, 병렬 스트림에서는 요구되는 버퍼의 크기가 늘어나게 된다

↓ java

static <T> Stream<T> empty() static <T> Stream<T> of(T t) static <T> Stream<T> ofNullable(T t) static <T> Stream<T> of(T... values) static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next) static <T> Stream<T> generate(Supplier<? extends T> s) static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) // 중간 연산 Stream<T> filter(Predicate<? super T> predicate) // predicate이 true인 요소만 남긴다 <R> Stream<R> map(Function<? super T, ? extends R> mapper) // mapper : 하나의 T 변수에서 하나의 R 변수로 대응하는 변환 IntStream mapToInt(ToIntFunction<? super T> mapper) // + long, double <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) // mapper : 하나의 T 변수에서 여러 R 변수(R 스트림)로 대응하는 변환 // mapper를 이용해 만들어진 여러 R 스트림을 일렬로 펴서(flattening) 하나의 R 스트림으로 변환. mapper가 null을 반환하면 빈 스트림을 대신 이용 // 최종적으로 반환되는 스트림 외의 모든 중간 스트림은 닫힌다 IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper ) // + long, double Stream<T> distinct() // Object.equals(Object)를 이용해 유일한 것들만으로 구성. stateful 중간 연산 Stream<T> sorted() // 자연스러운 방향으로 정렬. T가 Comparable하지 않으면 예외 발생할 수 있음. stateful 중간 연산 Stream<T> sorted(Comparator<? super T> comparator) Stream<T> peek(Consumer<? super T> action) // forEach와 유사한 기능을 하는 중간 연산. 다른 중간 연산 전후의 값을 살펴보는 디버깅 용도로 만들어짐 Stream<T> limit(long maxSize) // 스트림의 크기가 maxSize 이하가 되도록 한다. short-circuiting stateful 중간 연산 Stream<T> skip(long n) // n개를 버린 나머지로 스트림을 구성해 반환한다. 더 없으면 빈 스트림이 반환된다 default Stream<T> takeWhile(Predicate<? super T> predicate) // 요소들을 하나씩 검사하여, predicate을 만족하지 않는 요소가 나오기 전까지로 구성된 스트림을 반환한다 // 순서 있는 스트림에 대하여는 조건을 만족하는 최장 길이 접두 요소들을 얻게 되며, 순서 없는 스트림은 조건을 만족하는 부분 집합을 얻게 된다 // short-circuiting stateful 중간 연산 // 일반적으로 연산이 저렴하지만, 순서 있는 병렬 스트림에 대하여는 최장 길이 접두 요소들을 찾기 위해 연산이 비싸지므로, 허용된다면 순서 없는 스트림 소스(generate(Supplier))를 이용하거나, BaseStream.unordered()를 이용해 순서를 없애는 것이 성능에 도움이 될 것이다 default Stream<T> dropWhile(Predicate<? super T> predicate) // stateful 중간 연산 // 종결 연산 void forEach(Consumer<? super T> action) void forEachOrdered(Consumer<? super T> action) // 순서 있는 스트림의 경우, 이를 이용하면 요소의 순서대로 소비자가 실행된다 Object[] toArray() <A> A[] toArray(IntFunction<A[]> generator) // generator : 배열 크기를 먹고 배열을 뱉는 함수. 예: A[]::new T reduce(T identity, BinaryOperator<T> accumulator) // 하나의 T 변수로 축약하는 종결 연산. 아래와 동치다 { var result = identity; for(T element : stream) result = accumulator.apply(result, element); return result; } Optional<T> reduce(BinaryOperator<T> accumulator) // 하나의 T로 축약하는 종결 연산. 처음 연산 결과는 null이며, 스트림 첫 번째 요소를 만나면 치환된다. 이후는 reduce(T, BinaryOperator)와 같다 <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) // 하나의 U 변수로 축약하는 종결 연산. 연산은 reduce(T, BinaryOperator)와 동일한데, identity 값은 combiner 연산에 대한 항등원이어야 한다 // 다시 말해, 임의의 U 타입 변수 u에 대하여 u == combiner(identity, u)를 만족해야 한다 // 이는 연산 과정에서 다음의 검사를 통해 검증된다. combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t) // 이것보다는 map과 reduce를 쪼개 이용하는 것이 훨씬 간결 <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) // 하나의 R 변수로 축약하는 종결 연산. reduce와 다르게 R 자체가 결과값에 대한 가변적인 컨테이너(ArrayList, String 등)가 되어야 한다. 아래와 동치다 // 여기서는 combiner를 사용하지 않는 것처럼 보이지만, combiner는 병렬 스트림 연산을 위해 존재하는 것이므로, 연산 결과 자체는 아래와 동치가 맞다 { var result = supplier.get(); for(T element : stream) accumulator.accept(result, element); return result; } // 용례 { collect(ArrayList::new, ArrayList::add, ArrayList::addAll); collect(StringBuilder::new, StringBuilder::append, StringBuilder::append); } <R, A> collect(Collector<? super T, A, R> collector) // collect(Supplier, BiConsumer, BiConsumer)의 매개변수를 캡슐화한 Collector를 이용 // Collectors 유틸리티 클래스에 이미 정의된 Collector들이 있으니 편하게 이용 가능 Optional<T> min(Comparator<? super T> comparator) long count() // 개수를 반환하는 종결 연산 boolean anyMatch(Predicate<? super T> predicate) // short-circuiting 종결 연산 // + allMatch, noneMatch Optional<T> findFirst() // short-circuiting 종결 연산 // + findAny

StreamSupport

↓ java

static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) static <T> Stream<T> stream(Supplier<? extends Spliterator<T>> supplier, int characteristics, boolean parallel) // characteristics = supplier.get().characteristics() static IntStream intStream(Spliterator.OfInt spliterator, boolean parallel) // + long, double static IntStream intStream(Supplier<? extends Spliterator.OfInt> supplier, int characteristics, boolean parallel)

Collector<T, A, R>

↓ java

static enum Collector.Characteristics { CONCURRENT, IDENTITY_FINISH, UNORDERED; } Supplier<A> supplier() // 결과 컨테이너인 A를 생성하는 함수 반환 BiConsumer<A, T> accumulator() // A의 결과에 T 타입 데이터를 축적하는 함수 BinaryOperator<A> combiner() // 두 결과 컨테이너를 받아 하나로 반환하는 함수 Function<A, R> finisher() // 결과 컨테이너로부터 최종 결과 R로 변환하는 함수 반환 Set<Collector.Characteristics> characteristics() static <T, A, R> Collector<T, A, R> of(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner, Function<A, R> finisher, Collector.Characteristics... characteristics)

Collectors

↓ java

static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) static <T> Collector<T, ?, List<T>> toList() // 반환된 List의 타입, 변경 가능 여부, 직렬화, 스레드-안전 그 무엇도 보장하지 않음 static <T> Collector<T, ?, List<T>> toUnmodifiableList() static <T> Collector<T, ? Set<T>> toSet() // 반환된 Set의 타입, 변경 가능 여부, 직렬화, 스레드-안전 그 무엇도 보장하지 않음 static <T> Collector<T, ?, Set<T>> toUnmodifiableSet() static <T, K, U> Collector<T, ?, Map<K, U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) static <T, K, U> Collector<T, ?, Map<K, U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) // Since 10 static <T, K, U> Collector<T, ?, ConcurrentMap<K, U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) static Collector<CharSequence, ?, String> joining() static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) static <T, K> Collector<T, ?, ConcurrentMap<K, List<T>>> groupingByConcurrent(Function<? super T, ? extends K> classifier) static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate)

java.util.zip

Checksum

구현 클래스 : Adler32, CRC32, CRC32C

↓ java

default void update(byte[] b) long getValue()

ZipInputStream

↓ java

public ZipInputStream(InputStream in, Charset charset) ZipEntry getNextEntry() void closeEntry() // 현재 ZipEntry를 닫고 읽기 위치를 다음 entry로 이동 int available() // EOF를 만났으면 0, 아니면 1

ZipOutputStream

↓ java

public ZipOutputStream(OutputStream out, Charset charset) void setComment(String comment) void setMethod(int method) // ZipEntry에 설정되지 않은 경우 사용하는 압축 방법 : DEFLATED(압축, 기본값), STORED(비압축) void setLevel(int level) // 압축 레벨 : 0(BEST_SPEED) ~ 9(BEST_COMPRESSION). 기본은 DEFAULT_COMPRESSION(-1)이며, 보통 6 void putNextEntry(ZipEntry e) void closeEntry() // 현재 ZipEntry를 닫고 다음 쓰기 위치로 이동. putNextEntry 메서드는 쓰기 전에 알아서 닫는다 void finish() // 쓰기를 종료하고 스트림을 닫는다. 동일한 출력 스트림에 여러 필터를 적용한 경우에 사용

ZipEntry

↓ java

public ZipEntry(String name) public ZipEntry(ZipEntry e) // e로 필드를 채운다 String getName() ZipEntry setLastModifiedTime(FileTime time) ZipEntry setLastAccessTime(FileTime time) ZipEntry setCreationTime(FileTime time) void setSize(long size) // 비압축 크기 설정 void setCompressedSize(long csize) void setCrc(long crc) void setMethod(int method) // DEFLATED(압축), STORED(비압축), -1(미설정) void setExtra(byte[] extra) void setComment(String comment) boolean isDirectory() // 이름이 "/"로 끝나면 디렉터리

ZipFile

↓ java

public ZipFile(File file, int mode) // UTF-8 // mode : OPEN_READ | OPEN_DELETE(파일이 close 호출 전까지 삭제됨, 내용은 객체를 통해 계속 접근 가능) public ZipFile(File file, int mode, Charset charset) ZipEntry getEntry(String name) InputStream getInputStream(ZipEntry entry) // ZipFile이 닫히면 이 메서드가 반환한 모든 스트림도 같이 닫힌다 Enumeration<? extends ZipEntry> entries() Stream<? extends ZipEntry> stream() int size() // entry 개수

javax.crypto

javax.net

SocketFactory

↓ java

static SocketFactory getDefault() Socker createSocket(String host, int port)

ServerSocketFactory

↓ java

static ServerSocketFactory getDefault() ServerSocker createServerSocket(int port)

javax.net.ssl

HttpsURLConnection