item 55 JungHyunLyoo - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์—†๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์ทจํ•  ์ˆ˜ ์žˆ๋Š” ์„ ํƒ์ง€

java 8 ์ด์ „

  1. throw Exception
  2. null ๋ฐ˜ํ™˜

์˜ˆ์™ธ๋Š” ์ง„์งœ ์˜ˆ์™ธ์ ์ธ ์ƒํ™ฉ์—์„œ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฉฐ(item 69) ์˜ˆ์™ธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์Šคํƒ ์ถ”์  ์ „์ฒด๋ฅผ

์บก์ฒ˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„์šฉโ†‘

null์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ถ€๋‹ดโ†‘

java 8 ์ดํ›„

  1. Optional ๋ฐ˜ํ™˜
String str = "hello";

Optional<String> o = Optional.ofNullable(str); // str์ด null์ด๋ฉด ๋นˆ Optional ๊ฐ์ฒด ๋ฐ˜ํ™˜

Optional๋Š” null์ด ์•„๋‹Œ Tํƒ€์ž… ์ฐธ์กฐ๋ฅผ ํ•˜๋‚˜ ๋‹ด๊ฑฐ๋‚˜, ํ˜น์€ ์•„๋ฌด๊ฒƒ๋„ ๋‹ด์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

Optional์€ ์›์†Œ๋ฅผ ์ตœ๋Œ€ 1๊ฐœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” '๋ถˆ๋ณ€' ์ปฌ๋ ‰์…˜์ด๋‹ค.

Optional์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋ณ€ํ™˜ ์˜ˆ

item30์— ์•„๋ž˜์˜ ์ฝ”๋“œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

public static <E extends Comparable<E>> E max(Collection<E> c) {

    if (c.isEmpty())
        throw new IllegalArgumentException("๋นˆ ์ปฌ๋ ‰์…˜");

    E result = null;

    for (E e : c)
        if (result == null || e.compareTo(result) > 0)
            result = Objects.requireNonNull(e);

    return result;

}

Optional์„ ์ด์šฉํ•˜์—ฌ ์ด๋ ‡๊ฒŒ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {

    if (c.isEmpty())
        return Optional.empty();//์ ์ ˆํ•œ ์ •์ • ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ

    E result = null;

    for (E e : c)
        if (result == null || e.compareTo(result) > 0)
            result = Objects.requireNonNull(e);

    return Optional.of(result);//์ ์ ˆํ•œ ์ •์ • ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ

}

์œ„ ์ฝ”๋“œ๋ฅผ ์ŠคํŠธ๋ฆผ์„ ์ด์šฉํ•ด ๋” ์งง๊ฒŒ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ŠคํŠธ๋ฆผ์˜ ์ข…๋‹จ ์—ฐ์‚ฐ ์ค‘ ์ƒ๋‹น์ˆ˜๊ฐ€ ์˜ต์…”๋„์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ!

public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
    return c.stream().max(Comparator.naturalOrder());
}

null๊ณผ throw Exception ๋Œ€์‹  Optional์„ ์„ ํƒํ•˜๋Š” ๊ธฐ์ค€?

Optional์€ ๋ฐ˜ํ™˜๊ฐ’์ด ์—†์„ ์ˆ˜๋„ ์žˆ์Œ์„ API ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ช…ํ™•ํžˆ ์•Œ๋ ค์ค€๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ๋ฐ˜ํ™˜๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ๋ฅผ ํ•„์ˆ˜๋กœ ๋Œ€๋น„ํ•ด์•ผ ํ•  ๋•Œ Optional์„ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„ ๊ฒƒ์ด๋‹ค.

์•„๋ž˜๋Š” Optional์„ ๋ฐ˜ํ™˜๋ฐ›์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ทจํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์‹œ์ด๋‹ค.

  1. ๊ธฐ๋ณธ๊ฐ’ ์ •ํ•˜๊ธฐ
String str = max(words).orElse("no words");
  1. ์˜ˆ์™ธ ๋˜์ง€๊ธฐ
Toy myToy = max(toys).orElseThrow(SimpleException::new); 
//์˜ˆ์™ธ ํŒฉํ„ฐ๋ฆฌ ์ „๋‹ฌ. ์‹ค์ œ๋กœ ์˜ˆ์™ธ๊ฐ€ ์ผ์–ด๋‚˜์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ ์ƒ์„ฑ ๋น„์šฉ์€ ๋“ค์ง€ ์•Š์Œ
  1. ๊ฐ’์ด ์ฑ„์›Œ์ ธ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ธฐ
Element lastNobleGas = max(Elements.NOBLE_GASES).get();

๊ทธ๋Ÿฐ๋ฐ ๋•Œ๋•Œ๋กœ ๊ธฐ๋ณธ๊ฐ’์„ ์ •ํ•ด๋‘๋Š” ๋น„์šฉ์ด ๋ถ€๋‹ด๋  ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

๊ทธ๋Ÿด ๋• Supplier๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” orElseGet์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ ๋น„์šฉ์„ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ๊ธฐ๋ณธ๊ฐ’์ด ์ฒ˜์Œ ํ•„์š”ํ•  ๋•Œ, Supplier๋ฅผ ์‚ฌ์šฉํ•ด ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ.

Supplier๋Š” Optional์ด null์ผ ๋•Œ๋งŒ ์‹คํ–‰๋œ๋‹ค!

Optional.orElse vs Optional.orElseGet

Optional.orElse

private static String wontRunThis() { 
    System.out.println("Won't run this"); 
    return "foo"; 
} 
public void optional1() { 
    String o = Optional.of("Hello World!").orElse(wontRunThis()); 
    System.out.println("Result : " + o); 
}

result

Won't run this 
Result : Hello World!

Optional.orElseGet

private static String wontRunThis() { 
    System.out.println("Won't run this"); 
    return "foo"; 
} 
public void optional2() { 
    String o = Optional.of("Hello World!").orElseGet(() -> wontRunThis()); 
    System.out.println("Result : " + o); 
}

result

Result : Hello World!

์ถœ์ฒ˜ https://itstory.tk/entry/Java-8-OptionalorElse-vs-OptionalorElseGet [๋•'s IT Story]

Optional์„ ๋ฐ›์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํƒ€ ๋ฉ”์„œ๋“œ

์•ž์„œ์˜ ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒฝ์šฐ, filter, map, flatMap, ifPresent ๋“ฑ์˜ ๊ณ ๊ธ‰ ๋ฉ”์„œ๋“œ๋“ค๋กœ

์ ์ ˆํ•œ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ isPresent๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์›ฌ๋งŒํ•˜๋ฉด ์ด ๋ฉ”์„œ๋“œ๋“ค ๋ง๊ณ  ์ƒ๋‹จ์˜ ๋‚˜์—ด๋œ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•˜์ž.

๊ทธ๊ฒƒ์ด ๋” ์งง๊ณ  ๋ช…ํ™•ํ•˜๊ณ  ์šฉ๋ฒ•์— ๋งž๋Š” ์ฝ”๋“œ์ด๋‹ค. ์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” isPresent๊ฐ€ ์‚ฌ์šฉ๋œ ์˜ˆ์‹œ์ด๋‹ค.

Optional<ProcessHandle> parentProcess = ph.parent();
System.out.println(
    "๋ถ€๋ชจ PID: " + (parentProcess.isPresent() ?
    String.valueOf(parentProcess.get().pid()) : "N/A")
);

์ด ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹ค๋“ฌ์„ ์ˆ˜ ์žˆ๋‹ค.

System.out.println("๋ถ€๋ชจ PID: " +
    ph.parent().map(h -> String.valueOf(h.pid())).orElse("N/A"));

์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” java 8์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ๋„ ๋งŽ๋‹ค.

streamOfOptionals.filter(Optional::isPresent).map(Optional::get)

java 9์—์„œ๋Š” Optional์— stream() ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

streamOfOptionals.flatMap(Optional::stream)

wrapper class๋ฅผ ์œ„ํ•œ Optional

๋ฐ•์‹ฑ๋œ ๊ธฐ๋ณธ ํƒ€์ž…์„ ๋‹ด๋Š” ์˜ต์…”๋„์€ ๊ธฐ๋ณธ ํƒ€์ž… ์ž์ฒด๋ณด๋‹ค ๋ฌด๊ฒ๋‹ค. ๋‘ ๊ฒน์ด๋‚˜ ๊ฐ์‹ธ๊ธฐ ๋•Œ๋ฌธ.

๊ทธ๋ž˜์„œ ์ž๋ฐ” API ์„ค๊ณ„์ž๋Š” int, long, double ์ „์šฉ Optional class๋“ค์„ ์ค€๋น„ํ•ด๋†จ๋‹ค.

  • OptionalInt
  • OptionalLong
  • OptionalDouble

์ด ํด๋ž˜์Šค๋“ค๋„ Optional๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฑฐ์˜ ๋‹ค ์ œ๊ณตํ•œ๋‹ค.

๋‹จ '๋œ ์ค‘์š”ํ•œ ๊ธฐ๋ณธ ํƒ€์ž…'์šฉ์ธ Boolean, Byte, Character, Short, Float์€ ์˜ˆ์™ธ๋ผ๊ณ  ํ•œ๋‹ค.

Optional์„ Map์˜ value๋กœ ์‚ฌ์šฉํ•˜์ง€ ๋ง์ž

์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด, Map ์•ˆ์— ํ‚ค๊ฐ€ ์—†๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐฉ๋ฒ•์ด ๋‘๊ฐ€์ง€๊ฐ€ ๋œ๋‹ค.

  1. key ์ž์ฒด๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
  2. value๊ฐ€ ๋นˆ Optional์ธ ๊ฒฝ์šฐ

์“ธ๋ฐ์—†์ด ๋ณต์žก์„ฑ๋งŒ ๋†’์—ฌ์„œ ํ˜ผ๋ž€๊ณผ ์˜ค๋ฅ˜ ๊ฐ€๋Šฅ์„ฑ์„ ํ‚ค์šธ ๋ฟ์ด๋‹ค.

Optional์„ ์ปฌ๋ ‰์…˜์˜ key, value๋‚˜ ๋ฐฐ์—ด์˜ ์›์†Œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ ์ ˆํ•œ ์ƒํ™ฉ์€ ๊ฑฐ์˜ ์—†๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ