문제
해결 방안 고민
// 중고 노트북 구매 - 바탕화면 정리 안 되어 있음
/*
* 조건
* 1. 확장자별로 정리해서 몇 개씩 있는지 알려주기
* 2. 보기 편안하게 확장자들을 사전 순으로 정렬해주기
*/
/*
* 8을 입력한다. -> br.readLine();
* 입력한 숫자대로 문자열을 입력한다 => sbrus.txt (이름.확장자)
* Map을 활용하여 파일이름과 확장자 명을 저장
* 확장자명만 모은 array 생성 후 정렬
* TreeMap을 활용하여 map 정렬
* -- 출력 형태 --
* icpc 2
* spc 2
* txt 3
* world 1
*/
Java
복사
•
확장자명만 고려하면 되기 때문에 “.”을 기준으로 확장자명을 구분하기로 했다.
•
입출력 데이터 형식을 봤을 때 HashMap을 활용하면 괜찮겠다고 생각했다.
•
확장자명만 따로 분리하여 배열을 만들고 정렬된 Map의 key와 동일하면 해당 key와 value를 조건에 맞게 반복 출력하는 방식으로 진행하면 된다.
해결 방법
•
굳이 배열을 만들 필요 없이 TreeMap을 활용하여 map을 정렬한 다음 출력하면 되는 문제였다.
•
“.”을 기준으로 나눌 때 반드시 (”\\.”)으로 작성해야 한다.
코드
•
1번째 코드
◦
배열을 생성해서 진행하는 바람에 시간이 더 소요되었다.
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
// 파일 정리 - 실버 3
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
HashMap<String, Integer> map = new HashMap<>();
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
String[] arr = br.readLine().split("\\.");
map.put(arr[1], map.getOrDefault(arr[1], 0) + 1);
}
// map = icpc, spc, txt, world
int size = map.size();
int idx = 0;
String[] name = new String[size];
// key 얻는 방법
for (String key : map.keySet()) {
name[idx++] = key;
}
// 정렬
Arrays.sort(name);
Map<String, Integer> sortedMap = new TreeMap<>(map);
// key / value 동시에 얻기 (entrySet())
idx = 0;
for (Entry<String, Integer> nameMap : sortedMap.entrySet()) {
if (Objects.equals(nameMap.getKey(), name[idx])) {
bw.write(name[idx] + " " + nameMap.getValue());
bw.newLine();
}
idx++;
}
bw.flush();
bw.close();
br.close();
}
}
Java
복사
•
2번째 코드
◦
1번째 코드보다 시간이 더 적게 소요되었다.
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
// 파일 정리 - 실버 3
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
HashMap<String, Integer> map = new HashMap<>();
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
String[] arr = br.readLine().split("\\.");
map.put(arr[1], map.getOrDefault(arr[1], 0) + 1);
}
// Map 정렬
Map<String, Integer> sortedMap = new TreeMap<>(map);
for (Entry<String, Integer> nameMap : sortedMap.entrySet()) {
bw.write(nameMap.getKey() + " " + nameMap.getValue());
bw.newLine();
}
bw.flush();
bw.close();
br.close();
}
}
Java
복사
결과
•
1번째 코드 - 972ms
•
2번째 코드 - 792ms
Map에 대한 정리
•
HashMap에서 Key값 뽑아내기
◦
entrySet()은 key와 value 값을, keySet()은 key값만 가져올 수 있다.
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapSample {
public static void main(String[] args) {
Map<String, Integer> hashMap = new HashMap<String, Integer>();
hashMap.put("Key1", 1);
hashMap.put("Key2", 2);
hashMap.put("Key3", 3);
hashMap.put("Key4", 4);
hashMap.put("Key5", 5);
// Iterator 사용 1 - keySet()
Iterator<String> keys = hashMap.keySet().iterator();
while (keys.hasNext()){
String key = keys.next();
System.out.println("KEY : " + key); // Key2 , Key1, Key4, Key3, Key5
}
// Iterator 사용 2 - keySet()
Set set = hashMap.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
String key = (String) iterator.next();
System.out.println("KEY : " + key); // Key2 , Key1, Key5, Key4, Key3
}
// Iterator 사용 3 - entrySet() : key / value
Set set2 = hashMap.entrySet();
Iterator iterator2 = set2.iterator();
while (iterator2.hasNext()){
Entry<String, Integer> entry = (Entry)iterator2.next();
String key = (String) entry.getKey();
int value = (Integer) entry.getValue();
System.out.println("hashMap Key : " + key);
System.out.println("hashMap Value : " + value);
}
// 방법 2 - entrySet() : key / value => 둘 다 뽑아내려면 Entry를 활용한다
for (Entry<String, Integer> elem : hashMap.entrySet()){
System.out.println("키 : " + elem.getKey() + "값 : " + elem.getValue());
}
// 방법 3 - keySet() : key
for (String key : hashMap.keySet()){
System.out.println("키 : " + key);
}
}
}
Java
복사
•
HashMap 키(Key)정렬 방법
순서를 보장하지 않는 HashMap
HashMap은 어떠한 경우에도 키 또는 값을 기준으로 정렬되지 않는다. HashMap은 키의 해시 값을 기반으로 요소를 정렬하기 때문이다.
Map<String, Integer> map = new HashMap<>();
map.put("John", 34);
map.put("Jane", 26);
map.put("Tom", 27);
map.put("Bill", 29);
System.out.println(map);
== 실행 결과 ==
{Tom=27, John=34, Bill=29, Jane=26}
Java
복사
TreeMap을 사용하여 정렬
TreeMap은 SortedMap 인터페이스를 상속받는 클래스이다.
•
문자열 사전 순으로 키 정렬
◦
TreeMap에 Comparator를 생략하면 기본 Comparator가 동작한다. Comparator에서 문자열을 비교하는 경우 compareTo() 메서드가 실행된다. 이 메서드는 문자열을 사전 순으로 비교하고 오름차순으로 정렬한다.
List<String> li = new ArrayList<String>(
Arrays.asList("John", "Jane", "Tom", "Bill")
);
Map<String, Integer> map = new HashMap<>();
map.put("John", 34);
map.put("Jane", 26);
map.put("Tom", 27);
map.put("Bill", 29);
Map<String, Integer> sortedMap = new TreeMap<>(map);
System.out.println(sortedMap);
== 결과 ==
{Bill=29, Jane=26, John=34, Tom=27}
Java
복사
•
개발자 정의
◦
개발자가 TreeMap에 new Comparator<T>()를 전달하여 정렬 로직을 직접 구현할 수 있다.
Map<String, Integer> map = new HashMap<>();
map.put("John", 34);
map.put("Jane", 26);
map.put("Tom", 27);
map.put("Bill", 29);
Map<String, Integer> sortedMap = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int lengthDifference = o1.length() - o2.length();
if (lengthDifference != 0) return lengthDifference;
return o1.compareTo(o2);
}
});
sortedMap.putAll(map);
System.out.println(sortedMap);
== 결과 ==
{Tom=27, Bill=29, Jane=26, John=34}
Java
복사
TreeMap 클래스에 Comparator을 사용하여 compare() 메서드를 재정의(Override)한다. 재정의된 compare() 메서드는 문자열의 길이를 비교하고 문자열의 길이가 동일하면 사전 순으로 비교한다. 정렬 로직을 정의했으면 putAll() 메서드를 사용하여 map의 모든 요소를 sortedMap에 삽입한다. 삽입된 map 요소는 개발자가 재정의한 compare() 메서드를 통해 정렬된다.
LinkedHashMap을 사용하여 정렬
LinkedHashMap은 삽입 순서를 유지하는 클래스이다. LinkedHashMap 클래스는 이중 연결 리스트 방식으로 데이터를 관리하므로 요소를 접근하는데 유용하게 사용할 수 있다.
•
문자열 사전 순으로 키 정렬
◦
Map.Entry 클래스에는 comparingByKey() 메서드가 존재한다. 이 메서드는 키를 비교하기 위해 사용되는 메서드이다. 키의 타입을 String으로 정의하였기 때문에 키를 사전 순으로 정렬한다.
Map<String, Integer> map = new HashMap<>();
map.put("John", 34);
map.put("Jane", 26);
map.put("Tom", 27);
map.put("Bill", 29);
Map<String, Integer> sortedMap = map.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> { throw new AssertionError(); },
LinkedHashMap::new
));
System.out.println(sortedMap);
== 결과 ==
{Bill=29, Jane=26, John=34, Tom=27}
Java
복사