java

    [백준 BOJ / JAVA] 괄호의 값 (2504번)

    📘 1. 문제 소개 2504번: 괄호의 값 4개의 기호 ‘(’, ‘)’, ‘[’, ‘]’를 이용해서 만들어지는 괄호열 중에서 올바른 괄호열이란 다음과 같이 정의된다. 한 쌍의 괄호로만 이루어진 ‘()’와 ‘[]’는 올바른 괄호열이다. 만일 X www.acmicpc.net 📘 2. 풀이 해당 문제는 일반적인 스택 문제에 값을 구하는 문제가 더해진 문제다. 괄호를 이용한 일반적인 스택 문제에 대한 설명은 아래 문제를 참고하도록 하자. 9012번: 괄호 괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’ 와 ‘)’ 만으로 구성되어 있는 문자열이다. 그 중에서 괄호의 모양이 바르게 구성된 문자열을 올바른 괄호 문자열(Valid PS, VPS)이라고 www.acmicpc.net ..

    null이 아닌, 빈 컬렉션이나 배열을 반환하라 - [8장. 메서드(아이템54)]

    📙 1. null을 반환하는 경우 매장 안의 치즈 목록을 반환하는 메서드를 살펴보자. private final List cheeseInStock = ...; /** * @return 매장 안의 모든 치즈 목록을 반환한다. * 단, 재고가 하나도 없다면 null을 반환한다. */ public List getCheeses() { return cheeseInStock.isEmpty() ? null : new ArrayList(cheeseInStock); } 컬렉션이나 배열 같은 컨테이너(container)가 비었을 때 null을 반환하는 메서드를 사용할 때면 항시 아래와 같은 방어 코드를 넣어줘야 한다. List cheeses = shop.getCheese(); if(cheeses != null && chee..

    가변인수는 신중히 사용하라 - [8장. 메서드(아이템53)]

    📙 1. 가변인수 인수 개수가 일정하지 않은 메서드를 정의할 때 가변인수(varargs)를 사용할 수 있다. 가변인수 메서드를 호출하면, 가장 먼저 인수의 개수와 길이가 같은 배열을 만들고 인수들을 이 배열에 저장하여 가변인수 메서드를 건네준다. 입력받은 int 인수들의 합을 계산해 주는 가변인수 메서드를 다음과 같이 만들 수 있다. static int sum(int... args) { int sum = 0; for (int arg : args) sum += arg; return sum; } 📙 2. 가변인수의 문제점과 그에 따른 해결책 가변인수를 아래와 같이 잘못 구현할 수도 있다. static int min(int... args) { if(args.length == 0) throw new Illega..

    다중정의는 신중히 사용하라 - [8장. 메서드(아이템52)]

    📙 1. 다중정의의 문제 컬렉션을 '집합, 리스트, 그 외'로 구분하는 프로그램이 있다고 하자. public class CollectionClassifier { public static String classify(Set s) { return "집합"; } public static String classify(List s) { return "집합"; } public static String classify(Collection s) { return "집합"; } public static void main(String[] args) { Collection [] collections = { new HashSet(), new ArrayList(), new HashMap().values() }; for (Coll..

    적시에 방어적 복사본을 만들라 - [8장. 메서드(아이템50)]

    자바는 일반적으로 안전한 언어다. 하지만 아무리 자바라 해도 다른 클래스로부터의 침범을 아무런 노력 없이 다 막을 수 있는 것은 아니다. 그렇기 때문에 클라이언트가 우리의 불변식을 깨뜨리려 혈안이 되어 있다고 가정하고 방어적으로 프로그래밍해야 한다. 📙 1. 첫 번째 공격 - 생성자 이용 '시작 시각이 종료 시각보다 늦을 수 없다는 불변식'이 있는 다음과 같은 클래스가 있다고 하자. public final class Period { private final Date start; private final Date end; /** * @param start 시작 시각 * @param end 종료 시각; 시작 시각보다 뒤여야 하낟. * @throws IllegalArgumentException 시작 시각이 종..

    매개변수가 유효한지 검사하라 - [8장. 메서드(아이템49)]

    메서드나 생성자를 작성할 때면 그 매개변수들에 어떤 제약이 있을지 생각해야 한다. 이를 위한 원칙 2가지를 살펴보자. 📙 1. 원칙 1 : 오류는 가능한 한 빨리 (발생한 곳에서) 잡아야 한다. 오류를 발생한 즉시 잡지 못하면 해당 오류를 감지하기 어려워지고, 감지하더라도 오류의 발생 지점을 찾기 어려워진다. 매개변수 검사를 제대로 하지 못하면 아래와 같은 문제가 발생할 수 있다. 메서드가 수행되는 중간에 모호한 예외를 던지며 실패할 수 있다. 메서드가 잘 수행되지만 잘못된 결과를 반환할 수 있다. 메서드는 문제없이 수행됐지만, 어떤 객체를 이상한 상태로 만들어놓아서 미래의 알 수 없는 시점에 이 메서드와는 관련 없는 오류를 만들 수 있다. 이러한 문제를 예방하고자 public과 protected 메서드..

    스트림 병렬화는 주의해서 적용하라 - [7장. 람다와 스트림(아이템48)]

    📙 1. 자바의 동시성 프로그래밍 자바는 동시성 프로그래밍 측면에서 항상 앞서갔다. 처음 릴리스된 1996년 스레드, 동기화, wait/notify 지원 자바 5 동시성 컬렉션인 java.util.concurrent 라이브러리와 실행자(Executor) 프레임워크 지원 자바 7 고성능 병렬 분해(parallel decom-position) 프레임워크인 포크-조인(fork-join) 패키지 추가 자바 8 parallel 메서드만 한 번 호출하면 파이프라인을 병렬 실행할 수 있는 스트림 지원 이처럼 자바로 동시성 프로그램을 작성하기가 점점 쉬워지고 있다. 하지만, 동시성 프로그래밍을 할 때는 안전성(safety)과 응답 가능(liveness) 상태를 유지하기 위해 애써야 한다. 병렬 스트림 파이프라인 프로그..

    반환 타입으로는 스트림보다 컬렉션이 낫다 - [7장. 람다와 스트림(아이템47)]

    📙 1. 원소 시퀀스 반환 타입 비교 일련의 원소(원소 시퀀스)를 반환하는 메서드는 수없이 많다. 이런 메서드의 반환 타입으로 Collection, Set, List와 같은 인터페이스, Iterable, 배열, 스트림이 존재한다. 이 중 가장 적합한 타입은 컬렉션 인터페이스다. 만약, API를 스트림만 반환하도록 짜놓으면 반환된 스트림을 for-each로 반복하길 원하는 사용자는 당연히 불만을 토로할 것이다. 스트림을 반복하기 위해서는 아래와 같은 우회 방법을 선택해야 한다. for (ProcessHandle ph : (Iterable) ProcessHandle.allProcesses()::iterator) { ... } 작동은 하지만 실전에 쓰기에는 너무 난잡하고 직관성이 떨어진다. 그래서 아래와 같이..

    스트림에서는 부작용 없는 함수를 사용하라 - [7장. 람다와 스트림(아이템46)]

    📙 1. 스트림의 핵심 스트림은 그저 또 하나의 API가 아닌, 함수형 프로그래밍에 기초한 패러다임이다. 스트림 패러다임의 핵심은 계산을 일련의 변환(transformation)으로 재구성하는 부분이다. 이때 각 변환 단계는 가능한 한 이전 단계의 결과를 받아 처리하는 순수 함수여야 한다. 순수 함수란 오직 입력만이 결과에 영향을 주는 함수다. 다른 가변 상태를 참조하지 않고, 함수 스스로도 다른 상태를 변경하지 않아야 한다. 이를 위해서는 (중간 단계든 종단 단계든) 스트림 연산에 건네는 함수 객체는 모든 부작용(side effect)이 없어야 한다. 그렇다면 만약 부작용(side effect)이 발생하면 어떻게 될까? 아래와 같은 문제점이 발생하게 된다. 가독성 Stream을 사용한 순간 데이터의 변..

    스트림은 주의해서 사용하라 - [7장. 람다와 스트림(아이템45)]

    📙 1. 스트림의 특징 다량의 데이터 처리 작업(순차적이든 병렬적이든)을 돕고자 자바 8에 스트림 API가 추가되었다. 스트림의 특징은 아래와 같다. 스트림 안의 데이터 원소들은 객체 참조나 기본 타입 값(int, long, double)이다. 스트림 파이프라인은 소스 스트림에서 시작해 종단 연산(terminal operation)으로 끝나며, 그 사이에 하나 이상의 중간 연산(intermediate operation)이 있을 수 있다. 각 중간 연산은 스트림을 어떠한 방식으로 변환할 수 있다. 예를 들어, 각 원소에 함수를 적용하거나 특정 조건을 만족 못하는 원소를 걸러낼 수 있다. 스트림 파이프라인은 지연 평가(lazy evaluation)된다. 평가는 종단 연산이 호출될 때 이뤄지며, 종단 연산에 ..

    표준 함수형 인터페이스를 사용하라 - [7장. 람다와 스트림(아이템44)]

    📙 1. 함수형 인터페이스 자바가 람다를 지원하면서 상위 클래스의 기본 메서드를 재정의해 원하는 동작을 구현하는 템플릿 메서드 패턴의 매력이 크게 줄었다. 이를 대체하는 방법으로 함수 객체를 받는 정적 팩터리나 생성자를 제공하는 방법이 있다. 즉, 함수 객체를 매개변수로 받는 생성자와 메서드를 더 많이 사용하는 것이다. LinkedHashMap의 removeEldestEntry를 살펴보자. removeEldestEntry를 다음과 같이 재정의하면, 맵에 원소가 100개가 될 때마다 가장 오래된 원소를 하나씩 제거한다. // 기존 public class LinkedHashMap extends HashMap implements Map { ... protected boolean removeEldestEntry..

    람다보다는 메서드 참조를 사용하라 - [7장. 람다와 스트림(아이템43)]

    람다가 익명 클래스보다 나은 점 중에서 가장 큰 특징은 간결함이다. 그런데, 자바에는 함수 객체를 심지어 람다보다도 더 간결하게 만드는 방법이 있는데, 그것이 바로 메서드 참조(method reference)다. 이번 글에서는 람다와 메서드 참조를 비교해 보고 언제 어떤 것을 쓰면 좋은지 알아보도록 하자. 📙 1. 람다와 메서드 참조 public static void main(String[] args) { Map map = new HashMap(); int myKey = 1; int myValue = 3; map.merge(myKey, myValue, (count, incr) -> count + incr); System.out.println(map.get(myKey)); // 3 myValue = 5; ..