티스토리 뷰

Backend/Java8

#23 Optional 응용 method

RadderNepa 2022. 10. 12. 00:23

● 도입

- Optional을 응용할 수 있는 method에 대해 알아보자

public void ifPresent(Consumer<? super T> action)
public <U> Optional<U> map(Function<? super T, ? extends U> mapper)
public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)

ifPresent
- Optional 안에 값이 있을 때 parameter로 들어온 Consumer를 실행(Optional이 null이 아니라면 action을 실행)
- Optional이 비어있으면 아무일도 일어나지 않는다.
* 이전 글에서 배웠던 isPresent와 헷갈리지 말자

map
- Stream의 map과 유사하다.
- Optional 안에 값이 있을 때 mapper로 들어온 Function을 실행한다.
- Optional이 비어있으면 아무일도 일어나지 않는다.
- [Function<? super T, ? extends U>의 return type(? extends U)]에 따라 Optional 안에 들어있는 값의 type도 바뀐다.
* [<U> Optional<U> map(Function<? super T, ? extends U>]을 보면 Optional 안에 들어있는 값의 type이 Function의
return type과 동일하다는 것을 알 수 있다.

flatMap
– mapper의 return 값이 또 다른 Optional이라면 한 단계의 Optional이 되도록 납작하게 해준다.
(mapper를 적용했을 때 Optional 안에 또 하나의 Optional이 있는 형태라면 이것을 한 단계의 Optional이 되게 해준다.)

 

 

● 실습

package com.fastcampus.functionalprogramming.chapter7.model;

import java.util.List;

public class User {
	private int id;
	private String name;
	private String emailAddress;
	private boolean isVerified;
	private List<Integer> friendUserIds;
	
	public int getId() {
		return id;
	}
	
	public User setId(int id) {
		this.id = id;
		return this;
	}
	
	public String getName() {
		return name;
	}
	
	public User setName(String name) {
		this.name = name;
		return this;
	}
	
	public String getEmailAddress() {
		return emailAddress;
	}
	
	public User setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
		return this;
	}
	
	public boolean isVerified() {
		return isVerified;
	}
	
	public User setVerified(boolean isVerified) {
		this.isVerified = isVerified;
		return this;
	}
	
	public List<Integer> getFriendUserIds() {
		return friendUserIds;
	}
	
	public User setFriendUserIds(List<Integer> friendUserIds) {
		this.friendUserIds = friendUserIds;
		return this;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", " + (name != null ? "name=" + name + ", " : "")
				+ (emailAddress != null ? "emailAddress=" + emailAddress + ", " : "") + "isVerified=" + isVerified
				+ ", " + (friendUserIds != null ? "friendUserIds=" + friendUserIds : "") + "]";
	}
}

1. ifPresent

package com.fastcampus.functionalprogramming.chapter7;

import java.util.Optional;

import com.fastcampus.functionalprogramming.chapter7.model.User;

public class Chapter7Section2 {
	public static void main(String[] args) {
		// 1. ifPresent
		// maybeUser안에 User가 있을 수도 있고 없을 수도 있다.
		Optional<User> maybeUser1 = Optional.ofNullable(maybeGetUser(true));
		maybeUser1.ifPresent(user -> System.out.println("maybeUser1 : " + user));
		
		// maybeUser2가 null이기에 ifPresent 안의 내용은 실행되지 않는다.
		Optional<User> maybeUser2 = Optional.ofNullable(maybeGetUser(false));
		maybeUser2.ifPresent(user -> System.out.println("maybeUser2 : " + user));
	}
	
	// 오브젝트를 return(할 수도 OR 아닐 수도) 있는 메소드
	public static User maybeGetUser(boolean returnUser) {
		if (returnUser) {
			return new User()
					  .setId(1001)
					  .setName("Alice")
					  .setEmailAddress("alice@fastcampus.co.kr")
					  .setVerified(false);
		}
		return null;
	}
}

maybeUser2가 비어 있기에 "maybeUser2.ifPresent(user -> System.out.println("maybeUser2 : " + user))"는 실행되지 않았다.

 

2. map

package com.fastcampus.functionalprogramming.chapter7;

import java.util.Optional;

import com.fastcampus.functionalprogramming.chapter7.model.User;

public class Chapter7Section2 {
	public static void main(String[] args) {
		// 2. map
		Optional<Integer> maybeId1 = Optional.ofNullable(maybeGetUser(true))
		.map(user -> user.getId());
		maybeId1.ifPresent(id -> System.out.println("maybeId1 : " + id));
		System.out.println(maybeId1);
		
		// maybeId2가 null이기에 map 안의 내용은 실행되지 않는다.
		Optional<Integer> maybeId2 = Optional.ofNullable(maybeGetUser(false))
		.map(user -> user.getId());
		maybeId2.ifPresent(id -> System.out.println("maybeId2 : " + id));
		System.out.println(maybeId2);
	}
	
	// 오브젝트를 return(할 수도 OR 아닐 수도) 있는 메소드
	public static User maybeGetUser(boolean returnUser) {
		if (returnUser) {
			return new User()
					  .setId(1001)
					  .setName("Alice")
					  .setEmailAddress("alice@fastcampus.co.kr")
					  .setVerified(false);
		}
		return null;
	}
}

maybeId2가 비어 있기에 "maybeId2.ifPresent(id -> System.out.println("maybeId2 : " + id)"는 실행되지 않았다.

 

2-1. Optional의 map 또한 Stream의 map과 마찬가지로 여러 method들을 연속해서 사용할 수 있다.

package com.fastcampus.functionalprogramming.chapter7;

import java.util.Optional;

import com.fastcampus.functionalprogramming.chapter7.model.User;

public class Chapter7Section2 {
	public static void main(String[] args) {
		// 2-1
		// Optional의 map 또한 Stream의 map과 마찬가지로 여러 method들을 연속해서 사용할 수 있다.
		String username = Optional.ofNullable(maybeGetUser(true))
		.map(User::getName)
		.map(name -> "The name is " + name)
		.orElse("The name is empty");
		System.out.println(username);
		
		// username2가 null이기에 map 안의 내용은 실행되지 않는다.
		String username2 = Optional.ofNullable(maybeGetUser(false))
				.map(User::getName)
				.map(name -> "The name is " + name)
				.orElse("The name is empty");	// username2는 비어있는 Optional이기에 orElse의 default 값이 출력된다.
		System.out.println(username2);
	}
	
	// 오브젝트를 return(할 수도 OR 아닐 수도) 있는 메소드
	public static User maybeGetUser(boolean returnUser) {
		if (returnUser) {
			return new User()
					  .setId(1001)
					  .setName("Alice")
					  .setEmailAddress("alice@fastcampus.co.kr")
					  .setVerified(false);
		}
		return null;
	}
}

 

3. flatMap

- User class의 내용을 조금 변경했다.

[변경전]
public String getEmailAddress() {
	return emailAddress;
}

[변경후]
// emailAddress가 있을 수도 있고 없을 수도 있기 때문에 return type을 Optional<String>로 변경
public Optional<String> getEmailAddress() {
    // emailAddress가 null이라면 빈 Optional을 return
    // emailAddress가 null이 아니라면 해당 값(emailAddress)이 들어있는 Optional을 return
    return Optional.ofNullable(emailAddress);
}
package com.fastcampus.functionalprogramming.chapter7;

import java.util.Optional;

import com.fastcampus.functionalprogramming.chapter7.model.User;

public class Chapter7Section2 {
	public static void main(String[] args) {
		// 3. flatMap
		// Optional 안에 또 하나의 Optional이 있는 형태
		Optional<Optional<String>> maybeEmail = Optional.ofNullable(maybeGetUser(true)).map(User::getEmailAddress);
		System.out.println(maybeEmail);
		
		// 내가 원하는 형태는 Optional<Optional<String>>이 아니라 Optional<String>
		// 이럴때 flatMap을 사용한다.
		Optional<String> maybeEmai2 = Optional.ofNullable(maybeGetUser(true)).flatMap(User::getEmailAddress);
		maybeEmai2.ifPresent(email -> System.out.println("maybeEmai2 : " + email));
		System.out.println(maybeEmai2);
		
		Optional<String> maybeEmai3 = Optional.ofNullable(maybeGetUser(false)).flatMap(User::getEmailAddress);
		maybeEmai3.ifPresent(email -> System.out.println("maybeEmai3 : " + email));
		System.out.println(maybeEmai3);
	}
	
	// 오브젝트를 return(할 수도 OR 아닐 수도) 있는 메소드
	public static User maybeGetUser(boolean returnUser) {
		if (returnUser) {
			return new User()
					  .setId(1001)
					  .setName("Alice")
					  .setEmailAddress("alice@fastcampus.co.kr")
					  .setVerified(false);
		}
		return null;
	}
}

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함