[Java] Map 연습문제 2

1. 파티원 구하기

  1. n명의 게임 캐릭터 정보가 주어진다.
  2. 내 캐릭터와 같은 서버의 힐러 직업을 가진 유저를 출력한다.
  3. 2번에서 가장 높은 레벨을 출력한다. (유저가 10만, 100만일 경우를 가정)
public static void main(String[] args) {

  Map<String, String> myCharacter = new LinkedHashMap<>();
  myCharacter.put("서버", "B");
  myCharacter.put("닉네임", "마롭");
  myCharacter.put("직업", "마법사");
  myCharacter.put("레벨", "38");

  Map<String, String> character1 = new LinkedHashMap<>();
  character1.put("서버", "A");
  character1.put("닉네임", "사자고양이");
  character1.put("직업", "전사");
  character1.put("레벨", "11");
  characters.add(character1);

  Map<String, String> character2 = new LinkedHashMap<>();
  character2.put("서버", "B");
  character2.put("닉네임", "하구루");
  character2.put("직업", "마법사");
  character2.put("레벨", "46");
  characters.add(character2);

  Map<String, String> character3 = new LinkedHashMap<>();
  character3.put("서버", "B");
  character3.put("닉네임", "바다");
  character3.put("직업", "힐러");
  character3.put("레벨", "23");
  characters.add(character3);

  Map<String, String> character4 = new LinkedHashMap<>();
  character4.put("서버", "A");
  character4.put("닉네임", "초보");
  character4.put("직업", "힐러");
  character4.put("레벨", "4");
  characters.add(character4);

  Map<String, String> character5 = new LinkedHashMap<>();
  character5.put("서버", "B");
  character5.put("닉네임", "토르");
  character5.put("직업", "힐러");
  character5.put("레벨", "84");
  characters.add(character5);
}

2. 풀이

  1. 반복문을 위해 유저 정보 List에 저장 (Map이 아닌 List에 저장하는 이유는 아래에서 설명)
  2. 서버, 직업을 비교
  3. 내 캐릭터와 같은 서버에 있는 힐러 직업 출력
  4. 출력된 유저 중 가장 높은 레벨의 유저 출력

같은 서버의 힐러 유저

List<Map<String, String>> characters = new ArrayList<>(); // 출력: {서버=a, 닉네임=b, 직업=c...}
Iterator<Map<String, String>> iter = characters.iterator();
  while (iter.hasNext()) {
    Map<String, String> character = iter.next(); // 다시 저장하는 이유: next()로 다시 호출하는 경우를 방지
    if (character.get("서버").equals(myCharacter("서버")) && character.get("직업").equals("힐러")) {
      System.out.println(character);
    }
  }

/* 출력
{서버=B, 닉네임=바다, 직업=힐러, 레벨=23}
{서버=B, 닉네임=토르, 직업=힐러, 레벨=84}
*/

3번까지의 코드다.

가독성을 높이기 위해서는 character.get("서버"), character.get("직업")을 String에 다시 저장하면 된다.

가장 높은 레벨 출력

풀이 1

Map<String, String> maxLevelCharacter = null; // while문 안에 넣을 경우 계속 초기화되어 max를 구할 수 없음

Iterator<Map<String, String>> iter = characters.iterator();
while (iter.hasNext()) {
  Map<String, String> character = iter.next();
  if (character.get("직업").equals("힐러") && character.get("서버").equals(myCharacter.get("서버"))) {
    System.out.println(character);
    maxLevelCharacter = character; // 비교를 위해 character값을 저장
    if (maxLevelCharacter.get("레벨").compareTo(character.get("레벨")) < 0) { // A.compareTo(B) A가 B보다 클 경우 1, 작을 경우 -1, 같을 경우 0
      maxLevelCharacter = character; // A가 B보다 작을 때 B를 max에 넣는다.
    }
  }
}
System.out.println(maxLevelCharacter);

풀이 2

Map<String, String> maxLevelCharacter = null;
int maxLevel = 0; // 값이 초기화 되지 않도록 while문 밖에 저장

Iterator<Map<String, String>> iter = characters.iterator();
while (iter.hasNext()) {
  Map<String, String> character = iter.next();
  if (character.get("직업").equals("힐러") && character.get("서버").equals(myCharacter.get("서버"))) {
    System.out.println(character);
    int level = Integer.parseInt(character.get("레벨")); // 레벨 타입을 String -> int로 변환
    if (maxLevel < level) {
      maxLevelCharacter = character;
    }
  }
}
System.out.println(maxLevelCharacter);

3. Map? List? 어떨 때 사용할까?

이는 무엇을 중심으로 반복할 것인가에 따라 달라진다.

  • 단순히 순서대로 전체를 반복해야 할 때는 List
  • 닉네임, id 등 특정 key로 빠르게 찾고 싶을 때는 Map

4. 풀며 궁금하거나 느꼈던 점들

maxLevelCharacter = null로 구현체없이 생성?

HashMap, LinkedHashMapnull을 허용한다.

그럼 maxLevelCharacter는 어떤 구현체일까?

maxLevelCharacter은 null값을 넣어 선언만 되었을뿐, 아직 어떤 구현체로도 생성되지 않았다.

만약 그냥 값을 넣고 출력하면 어떻게 될까?

예시

위에서 보듯 NullPointerException 문구를 마주하게 된다.

Map으로 반복문 돌릴 때 중요한 포인트

이번 문제를 풀며, Map 인터페이스를 사용함에 있어서 가장 중요한 포인트는 <k-v> 구조를 정확히 이해하고 값을 꺼낼 줄 알아야 한다는 것이었다.

여기에 더하자면 Map이 효율적일지 List가 효율적인지 판단할 수 있는 눈이 아닐까?

추후 DB를 효율적으로 관리하기 위해서도 분명 필요한 부분이라고 생각한다.

Categories:

Updated:

Leave a comment