JiwonDev

#12. Optional API (Null๊ฐ’ ์ฒ˜๋ฆฌ)

by JiwonDev

์ž๋ฐ”๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์— ํ™•์ธ๊ฐ€๋Šฅํ•œ null safe ์—ฐ์‚ฐ์„ ๋”ฐ๋กœ ์ œ๊ณตํ•ด์ฃผ์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ๊ธฐ์กด์—๋Š” ์กฐ๊ฑด๋ฌธ์œผ๋กœ ํ™•์ธํ•˜๊ฑฐ๋‚˜ ์˜ˆ์™ธ๋ฅผ ๋˜์ ธ ์ฑ…์ž„์„ ์ฝ”๋“œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋„˜๊ธฐ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ์—ˆ๋‹ค.

* ์ฐธ๊ณ ๋กœ Optional์€ Stream ์ „์šฉ ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹ˆ๋‹ค. Optional.Stream() ํ†ตํ•ด ์ŠคํŠธ๋ฆผ์„ ์ƒ์„ฑํ•˜์—ฌ(Java9๋ถ€ํ„ฐ ์ถ”๊ฐ€๋จ) ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

# NPE (NullPointerException)

์œ„์—๋„ ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ, ์˜๋„ํ–ˆ๋˜ ์˜๋„ํ•˜์ง€์•Š์•˜๋˜ ๊ฐ์ฒด์— ๊ฐ’์„ ํ• ๋‹นํ•ด์ฃผ์ง€์•Š์•„ null์ด ๋“ค์–ด๊ฐ€์„œ ์ƒ๊ธฐ๋Š” NPE ๋ฌธ์ œ๋Š” ํ”ํžˆ ์ผ์–ด๋‚˜๋Š” ์˜ˆ์™ธ์ด๋ฉด์„œ ๊น”๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐํ•˜๊ธฐ๋Š” ์–ด๋ ค์šด ์ฃผ์ œ์˜€๋‹ค. (* ์ด๋ฅผ ์กฐ๊ธˆ์ด๋‚˜๋งˆ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  2020๋…„ Java14๋ถ€ํ„ฐ๋Š” instanceof ํ‚ค์›Œ๋“œ์™€ NPE์— ๋Œ€ํ•œ ์˜ค๋ฅ˜๋ฅผ ๋” ์ž์„ธํ•˜๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.)

// ํ•ธ๋“œํฐ ์ œ์กฐ์‚ฌ์˜ ์ด๋ฆ„์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
public String getPhoneManufacturerName(Person person) {
    // `person` ์ด null ์ด๋ฉด?
    // ์•„๋‹ˆ๋ฉด `getPhone()` ๋ฉ”์„œ๋“œ์˜ ๊ฒฐ๊ณผ๊ฐ€ null ์ด๋ฉด?
    return person.getPhone().getManufacturer().getName();
}

// ๋งŒ์•ฝ.. ๋‚ด๊ฐ€ ๋งŒ๋“  ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ฒ˜๋Ÿผ ํ˜ธ์ถœํ•˜๋Š” ์ž…์žฅ์ด๋ผ๋ฉด?
String manufacturerName = getPhoneManufacturerName(person);

// manufacturer ๊ฐ€ null ์„ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ NPE๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
String lowerCaseName = manufacturerName.toLowerCase();

# NPE๋ฅผ ์˜ˆ๋ฐฉํ•˜๋Š” ๊ณ ์ „์ ์ธ ๋ฐฉ๋ฒ•

Java8 ์ด์ „์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ NPE๋ฅผ ์˜ˆ๋ฐฉํ–ˆ์—ˆ๋‹ค.

// ์ง•๊ทธ๋Ÿฌ์šด ์˜ˆ์™ธ์ฒ˜๋ฆฌ ์ฝ”๋“œ
public String getPhoneManufacturerName(Person person) {
	if (person != null) {
	    Phone phone = person.getPhone();
        if (phone != null) {
        	Manufacturer manufacturer = phone.getManufacturer();
	        if (manufacturer != null) {
	            return manufacturer.getName();
	        }
	    }
	}
	return "Samsung";
}

 

๊ทธ๋Ÿฌ๋ฉด์„œ ๊ฐœ๋ฐœ์ž๋“ค์ด ์•„์ด๋””์–ด๋ฅผ ๋‚ธ ๊ฒƒ์ด, ๋„ ๊ฐ์ฒด ํŒจํ„ด(Null Object Pattern)์ด ์—ˆ๋‹ค. ์ด ํŒจํ„ด์˜ ํ•ต์‹ฌ์€ null ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ์ด๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋Š” null ๋‹ด๋‹น ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.

/* ๋„ ๊ฐ์ฒด(Null Object) ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋กœ ๊ตฌํ˜„. */
class NullMessenger implements Messenger {
	@Override
	public void send(String msg) {
        // ๊ทธ๋ƒฅ ๋นˆ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์•„๋ฌด ๋™์ž‘๋„ ํ•˜์ง€ ์•Š๋Š”๋‹ค.
	}
}


/* null ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ํด๋ž˜์Šค๋“ค. */
interface Messenger {
	void send(String msg);
}

class Kakao implements Messenger {
	@Override
	public void send(String msg) {...} 
}

class Line implements Messenger {
	@Override
	public void send(String msg) {...}
}
class MessengerFactory {
    public static Messenger getMessenger(String name) {
        if ( ... ){
            return ... // ํŠน์ • ์กฐ๊ฑด์— ๋งž๋Š” Messenger ๊ตฌํ˜„์ฒด ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. 
        }
        // ๊ฒฐ๊ณผ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ `null`์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ  `NullMessenger`๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
        return new NullMessenger();
    }
}

// ์‹ค์ œ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ
Messenger messenger = MessengerFactory.getMessenger("KakaoTalk");
messenger.send("Hello");

์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์„œ NPE ์—๋Ÿฌ๋Š” ํ”ผํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๊ฐ€ ํ•ด๋‹น ๊ฐ์ฒด์˜ 'Null ์ „์šฉ ํด๋ž˜์Šค'๋ฅผ ์•Œ๊ณ  ์žˆ์–ด์•ผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ๋‹ค. ๋งŒ์•ฝ ์ธํ„ฐํŽ˜์ด์Šค์— ๋‚ด์šฉ์ด ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜ ์ •ํ™•ํ•œ ํด๋ž˜์Šค ๊ตฌํ˜„์„ ์ž˜ ๋ชจ๋ฅธ๋‹ค๋ฉด ๊ธฐ์กด์˜ if(..null) ์ค‘๋ณต์ฒ˜๋ฆฌ๋ณด๋‹ค ํ›จ์”ฌ ๋” ๋ณต์žกํ•œ ๊ฒ€์‚ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.


 

# Optional Class์˜ ๋“ฑ์žฅ

์ด๋Ÿฌํ•œ ๋ฌธ์ œ์ ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ์œ„ํ•ด Java8 ๋ถ€ํ„ฐ ๊ณต์‹์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” Null ์ „์šฉ ๊ฐ์ฒด๊ฐ€ Optional Class์ด๋‹ค. ์œ„์—์„œ ๋งํ•œ null-object pattern์„ ์ž๋ฐ”์—์„œ ๊ณต์‹์ ์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ณ  ํ‘œ์ค€ํ™” ํ•œ ๊ฒƒ์ด๋‹ค.

๋‹ค๋ฅธ ํ•ด๊ฒฐ์ฑ…์€ ์—†์—ˆ๋‚˜์š”?

๋”๋ณด๊ธฐ

Java1.7์— null-safe ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์—ฐ์‚ฐ์„ ๋„์ž…ํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ์—ˆ๋‹ค. ( Project Coin ) ํ•˜์ง€๋งŒ ์ƒˆ๋กœ์šด ์•ˆ์ „์žฅ์น˜๋ฅผ ์ ์šฉํ•˜๋Š” ์ด์ ๋ณด๋‹ค ๋„์ž…ํ–ˆ์„ ๋•Œ JVM์ด๋‚˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•จ์— ์žˆ์–ด ์ถ”๊ฐ€ํ•ด์•ผํ•˜๋Š” ๋น„์šฉ์ด๋‚˜ ํ•ด๊ฒฐํ•ด์•ผํ•  ๋ฌธ์ œ์ ๋“ค์ด ์žˆ์—ˆ๊ธฐ์— ๊ฒฐ๊ณผ์ ์œผ๋กœ ์Šน์ธ ๋˜์ง€๋Š” ์•Š์•˜๋‹ค.

// Java7์˜ Project Coin - ์—˜๋น„์Šค ์—ฐ์‚ฐ์ž๊ฐ€ ์ ์šฉ๋˜์—ˆ๋‹ค๋ฉด ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์•˜์„๊นŒ?
public String getPhoneManufacturerName(Person person) {
    // ์ฒด์ด๋‹ ์ค‘์—์„œ null์ด ์žˆ๋‹ค๋ฉด, "Samsung"์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    return person?.getPhone()?.getManufacturer()?.getName() : "Samsung";
}

# Optional ์ƒ์„ฑ

์ œ๋„ˆ๋ฆญ ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•˜๊ณ , ์ „์šฉ Static Factory Method๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

Optional<Person> person; // Person ํƒ€์ž…์˜ `Optional` ๋ณ€์ˆ˜
Optional<Phone> phone; // phone ํƒ€์ž…์˜ `Optional` ๋ณ€์ˆ˜

// ์‚ฌ์šฉ์˜ˆ์‹œ
phone1 = Optional.empty();
phone2 = Optional.ofNullable(phone);

# Optional.empty()

๋น„์–ด์žˆ๋Š” Optional ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์‹ฑ๊ธ€ํ„ด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.

// ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜
// `Optional` ํด๋ž˜์Šค์˜ ์ •์  ๋ฉค๋ฒ„๋กœ ์„ ์–ธ๋˜์–ด ์‹ฑ๊ธ€ํ†ค์„ ๊ตฌํ˜„ํ•จ.
private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

// ์˜ˆ์ œ
Optional<String> emptyOpt = Optional.empty();

# Optional.of ( T value )

๊ฐ’์ด null ์ด๋ผ๋ฉด NPE ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค. ๋งŒ์•ฝ ํ•ด๋‹น ๊ฐ์ฒด์— ๊ฐ’์ด ๋ฐ˜๋“œ์‹œ ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

// ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜
public static <T> Optional<T> of(T value);
// ์˜ˆ์ œ
Optional<String> opt = Optional.of("result");

# Optional.ofNullable( T value )

๊ฐ’์ด null์ผ ์ˆ˜๋„ ์žˆ๋Š” T ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋งŒ์•ฝ ๊ฐ’์ด null์ด๋ผ๋ฉด ๋น„์–ด์žˆ๋Š” Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

// ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜
public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

// ์˜ˆ์ œ
Optional<String> opt = Optional.ofNullable(null);

# Optional ์ค‘๊ฐ„ ์—ฐ์‚ฐ

# Filter

// ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜
public Optional<T> filter(Predicate<? super T> predicate);

// ๊ฐ’์ด ๋น„์–ด์žˆ๋‹ค๋ฉด(null์ด๋ผ๋ฉด) NPE ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.
Optional.of("True").filter((val) -> "True".eqauls(val)).orElse("NO DATA"); // "True"
Optional.of("False").filter((val) -> "True".eqauls(val)).orElse("NO DATA"); // "NO DATA"

// ์กฐ๊ฑด์— ๋งž๋Š” Optional(=person) ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š”๋‹ค. ๋น„์–ด์žˆ๋‹ค๋ฉด empty Optional์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
Optional.ofNullable(person).filter(p -> p.getName().equals("Kimtaeng"));

 


# map

mapper ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ ๊ฐ’์„ ์ˆ˜์ •ํ•œ๋‹ค.

// ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜
public<U> Optional<U> map(Function<? super T, ? extends U> mapper);
// ์˜ˆ์ œ
Integer test = Optional.of("1").map(Integer::valueOf).orElseThrow(NoSuchElementException::new); // string to integer

// Optional ๊ฐ์ฒด(=person)๊ฐ€ ๊ฐ’์ด ์žˆ๋‹ค๋ฉด map์„ ์‹คํ–‰ํ•˜๊ณ , ๋น„์–ด์žˆ๋‹ค๋ฉด ์•„๋ฌด๋Ÿฐ ์—ฐ์‚ฐ์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค.
Optional.ofNullable(person).map(p -> p.getName());

 


# flatMap

์ค‘์ฒฉ๋œ Optional ๊ตฌ์กฐ๋ฅผ ํ•œ ๋‹จ๊ณ„ ์—†์• ๊ณ  ๋‹จ์ผ ์š”์†Œ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค. ์ดํ•ด๊ฐ€ ๋˜์ง€์•Š๋Š”๋‹ค๋ฉด ์ด ๋งํฌ๋ฅผ ์ฐธ์กฐํ•˜์ž.

// ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper);

// ์˜ˆ์ œ
String result = Optional.of("result")
        .flatMap((val) -> Optional.of("good"))
        .get();
System.out.println(result); // print 'good'
class Person {
	private Optional<Phone> phone;
	// getter, setter ์ƒ๋žต
}

/* person ๊ฐ์ฒด๋ฅผ ์ฃผ๋ฉด ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๊ณ ์žˆ๋Š” phone์„ ๋ฐ˜ํ™˜ํ•จ.*/

// ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ. Optional ์œผ๋กœ Optional<phone>๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋‹ค.
public Optional<Phone> testMap(Person person) {
	// Optional<Optional<Phone>> ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ ์˜ค๋ฅ˜ ๋ฐœ์ƒ
	return Optional.ofNullable(person)
	    .map(Person::getPhone);
}

// ์ž‘๋™ํ•˜๋Š” ์ฝ”๋“œ. flatMap์„ ์ด์šฉํ•˜์—ฌ Optional<> ์ค‘์ฒฉ์„ ํ•œ ๋‹จ๊ณ„ ์ œ๊ฑฐํ•ด์ค€๋‹ค.
// Optional<Optional<phone>>์„ Optional<Phone>์œผ๋กœ ์ ‘๊ทผํ•œ๋‹ค. Stream flatmap๊ณผ ๋™์ž‘๋ฐฉ์‹์ด ์œ ์‚ฌํ•˜๋‹ค.
public Optional<Phone> testFlatMap(Person person) {
    return Optional.ofNullable(person)
        .flatMap(Person::getPhone);
}

 


# or (null ๋Œ€์ฒด๊ฐ’ ์ง€์ •)

๊ฐ’์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ Optional ๊ฐ์ฒด๋ฅผ, ์—†๋Š” ๊ฒฝ์šฐ ๋น„์–ด์žˆ๋Š” Optional์ด ์•„๋‹ˆ๋ผ or(~)์— ๋“ฑ๋กํ•œ Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Optional.ofNullable("Hi")
    .filter(value -> value.length() > 3) // `filter` ์กฐ๊ฑด์— ๊ฑธ๋Ÿฌ์ง. ๋นˆ Optional ๋ฐ˜ํ™˜
    .or(() -> Optional.of("Hello")) // ๊ฐ’์ด ์—†์œผ๋ฏ€๋กœ ๋Œ€์ฒด Optional[Hello] ๋ฐ˜ํ™˜

# Stream์œผ๋กœ ๋ณ€ํ™˜

์ค‘๊ฐ„์— ๋น„์–ด์žˆ๋Š” Optional ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฒฝ์šฐ, Stream.empty()๊ฐ€ ๋ฐ˜ํ™˜๋˜๋ฉฐ ํ•จ์ˆ˜ ์ฒด์ด๋‹์ด ๋” ์ด์ƒ ์ง„ํ–‰๋˜์ง€ ์•Š๋Š”์ ์„ ์œ ์˜ํ•˜์ž. ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์ด ๋ฉˆ์ถ˜๋‹ค.

public void testOptionalWithStream() {
    // ์ฐธ๊ณ ๋กœ List.of๋Š” ์ž๋ฐ” 9์—์„œ ์ถ”๊ฐ€๋œ ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ. ํŠœํ”Œ์„ ๋งŒ๋“ ๋‹ค.
    // Unmodifiable list(์ˆ˜์ • ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ฆฌ์ŠคํŠธ)๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ฃผ์˜
    List.of(4, 3, 2, 5)
        .stream() // stream์œผ๋กœ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.
        .map(value -> value > 2 ? Optional.of(value) : Optional.empty())
        .flatMap(Optional::stream)
        .forEach(System.out::println);
}

๋ฌผ๋ก  ๋žŒ๋‹ค์‹๊ณผ ๋ฉ”์„œ๋“œ ๋ ˆํผ๋Ÿฐ์Šค๋Š” ์„ ํƒ์‚ฌํ•ญ์ด๋‹ค. ๊ผญ ํ•„์š”ํ•˜๋‹ค๋ฉด ์ต๋ช…ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด๋„ ์ƒ๊ด€์—†๋‹ค. 

// ์œ„์™€ ์™„์ „ํžˆ ๊ฐ™์€ ์ฝ”๋“œ์ด๋‹ค. ์ดํ•ด๋ฅผ ๋•๊ธฐ์œ„ํ•ด ์ค‘๊ฐ„์ค‘๊ฐ„ println์„ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.
public void testOptionalWithStream() {
    List.of(4, 3, 2, 5)
        .stream()
        .map(value -> {
            return value > 2 ? Optional.of(value) : Optional.empty();
        })
        .peek(v -> {
            // ๋„˜์–ด์˜ค๋Š” ๊ฐ’์„ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•จ
            System.out.println("peek: " + v);
        })
        .flatMap(new Function<Optional<? extends Object>, Stream<?>>() {
            @Override
            public Stream<?> apply(Optional<?> o) {
                System.out.println("flatMap: " + o);
                return o.stream();
            }
        })
        .forEach(v -> {
            System.out.println("forEach: " + v);
        });
}

 


 

# Optional ๊ฐ’ ๊บผ๋‚ด์˜ค๊ธฐ (์ข…๋‹จ ์ฒ˜๋ฆฌ)

 

'๐ŸŒฑBackend > Java' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

#14. JSP์™€ ์›น ํ”„๋กœ๊ทธ๋ž˜๋ฐ  (0) 2021.07.16
#13 JSP (Java Server Pages)  (0) 2021.07.14
#11 Stream API  (0) 2021.07.12
#10 Modern Java (Java8~)  (0) 2021.07.12
#8 Java - 3 (์“ฐ๋ ˆ๋“œ, IO, ๋„คํŠธ์›Œํฌ)  (0) 2021.07.09

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ