Map vs class 클래스를 사용해야 하는 이유

Jan 09, 2024
Map vs class 클래스를 사용해야 하는 이유
 
자바에서 객체를 생성해 데이터를 저장할 때 Map 을 사용할 수도 있고, class를 사용할 수도 있다.
이번 블로그에서는 객체를 생성해 저장할때 차이를 비교해본다. 객체에 이름과 나이를 저장 후 나이에서 하나씩 빼는 코드를 만들어보았다.
 

1. Map 사용

 
public class StreamEx01 { public static void main(String[] args) { Map<String, Object> data1 = new HashMap<>(); data1.put("name", "홍길동"); data1.put("age", 20); Map<String, Object> data2 = new HashMap<>(); data2.put("name", "장보고"); data2.put("age", 15); Map<String, Object> data3 = new HashMap<>(); data3.put("name", "이순신"); data3.put("age", 30); List<Map<String, Object>> arr = Arrays.asList(data1, data2, data3); List<Map<String, Object>> newArr = arr.stream().map(d -> { int newAge = (Integer) d.get("age") - 1; d.put("age", newAge); return d; }).toList(); newArr.stream().forEach(System.out::println); } }
 
 
Map<String, Object> data1 = new HashMap<>(); data1.put("name", "홍길동"); data1.put("age", 20);
맵은 키-값 의 구조를 가지고 있다. name 이라는 키에 맞는 값을 넣을 수 있다.
키 값은 보통 String 변수로 설정하고, 입력 값은 정할 수 없기 때문에 추상화된 Object 변수 를 사용한다.
 
List<Map<String, Object>> arr = Arrays.asList(data1, data2, data3);
 
List 를 사용할 때 변수가 2개이기 때문에 <<>> 이중 괄호로 값을 입력한다.
 
List<Map<String, Object>> newArr = arr.stream().map(d -> { int newAge = (Integer) d.get("age") - 1; // 다운캐스팅 d.put("age", newAge); return d; }).toList();
 
map() 을 사용해 데이터들의 값을 변환한다. Map 에서 출력값은 Object 타입이기 때문에 값을 대입하려면 다운캐스팅을 반드시 해야 한다.
 
 

2. class 사용

class User { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public User(String name, int age) { this.name = name; this.age = age; } public void changeAge() { this.age = this.age - 1; } } public class StreamEx02 { public static void main(String[] args) { // 객체 3명 만들기 User u1 = new User("홍길동", 20); User u2 = new User("장보고", 15); User u3 = new User("이순신", 30); List<User> list = Arrays.asList(u1, u2, u3); List<User> newAge = list.stream().map(u -> { u.changeAge(); return u; }).toList(); newAge.stream().forEach(u -> System.out.println(u.getAge())); } }
 
이번에는 클래스를 통해 객체를 생성해 데이터를 저장했다.
 
class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; }
 
User 클래스를 만들어 변수 설정을 하고 생성자를 만 들어 초기화를 했다.
 
 
public void changeAge() { this.age = this.age - 1; }
 
클래스에서는 메서드를 만들어 호출하는 방식으로 사용할 수 있다. changeAge 메서드를 만들고, 이 메서드가 호출될 때마다 나이가 1씩 차감되는 방식이다.
 
List<User> newAge = list.stream().map(u -> { u.changeAge(); return u; }).toList();
 
Map 에서는 다운캐스팅을 해서 int 값으로 저장했지만, class 는 메서드를 호출하기만 하면 된다.
 
notion image
 

3. class 를 사용해야 하는 이유

 
컴파일 에러 확인 불가
Map 은 Object 형을 변수로 갖기 때문에 잘못된 값을 입력받아도 확인할 수 없다. 예를 들어 String 값을 저장해야 하지만 int 로 저장해도 확인할 수 없다.
 
가독성이 떨어짐
Map을 사용하는 구조는 가독성이 떨어진다. 만약 Map<String, Object>를 본다면, 우리가 받는 Key 값은 무엇이고, Value 값은 무엇이며 어떠한 타입인지를 파악하기가 쉽지않다. Map으로 작성된 코드를 이해하기 위해서는 불필요한 코드 리딩 시간이 필요하고 생산성이 떨어지게 된다.
 
다운캐스팅을 해야됨
Map은 자료형이 Object 기 때문에 해당 데이터를 사용하려면 다운캐스팅이 불가피하다.
 
데이터의 불변성을 확보할 수 없음
Map<String, Object> data1 = new HashMap<>(); data1.put("name", "홍길동"); Map<String, Object> data2 = new HashMap<>(); data1.put("name", "장보고");
 
Map 은 오타의 가능성이 있고, 데이터를 잘못 입력하면 데이터값이 변경될 수 있다.
Share article

{CODE-RYU};