[JAVA] Map

Coastby·2022년 10월 6일
0

LIKELION Back-End School

목록 보기
33/61
post-custom-banner

HashMap

HashMap은 키(key)와 값(value)을 묶어서 하나의 데이터(entry)로 저장한다. 그리고 해싱(hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는데 있어서 뛰어난 성능을 보인다.

HashMap은 키와 값을 각각 Object 타입으로 저장한다. 어떤 형태로 저장하기 때문에 어떠한 객체도 저장할 수 있지만 키는 주로 String을 대문자 또는 소문자로 통일해서 사용하곤 한다.

  • 키 (key) : 컬렉션 내의 키 (key) 중에서 유일해야 한다.
  • 값 (value) : 키와 달리 데이터의 중복을 허용한다.

키는 저장된 값을 찾는데 사용되는 것이기 때문에 컬렉션 내에서 유일 (unique)해야 한다.

  • Object get(Object key) : 지정된 키의 값(value)을 반환한다. 못 찾으면 Null 반환.
  • Object replace (Object key, Object value) : 지정된 값을 지정된 객체 (value)로 대체
    • 사실 같은 키로 put을 하면 그 value는 덮어쓰기된다. 즉, 전의 value는 사라진다. 왜냐하면 HashMap에서 key는 하나만 있을 수 있기 때문이다.
  • Set keySet() : HashMap에 저장된 모든 키가 저장된 Set을 반환한다.

해싱

해싱이란 해시 함수 (hash function)을 이용해서 데이터를 해시 테이블에 저장하고 검색하는 기법을 말한다. 해시함수는 데이터가 저장되어 있는 곳을 알려주기 때문에 다량의 데이터 중에서도 원하는 데이터를 빠르게 찾을 수 있다.

해싱에서 사용하는 자료구조는 배열과 링크드 리스트의 조합으로 되어 있다.
저장할 데이터의 키를 해시함수에 넣으면 배열의 한 요소를 얻게 되고, 다시 그 곳에 연결되어 있는 링크드 리스트에 저장하게 된다.

배열은 크키가 커져도 원하는 요소가 몇 번째에 있는 지만 알면 빠르게 원하는 값을 찾을 수 있다. 그러나 링크드 리스트는 검색에 불리한 자료구조이기 때문에 링크드 리스트의 크기가 커질수록 검색속도가 떨어지게 된다.
하나의 링크드 리스트에 최소한의 데이터만 저장되려면, 저장될 데이터의 크기를 고려해서 HashMap의 크기를 적절하게 지정해주어야 하고, 해시함수가 서로 다른 키에 대해서 해시코드의 반환을 최소화해야 빠른 검색시간을 얻을 수 있다.

실제로는 HashMap과 같이 해싱을 구현한 컬렉션 클래스에서는 Object 클래스에 정의된 hashCode()를 해시함수로 사용한다. Object 클래스에 정의된 hashCode()는 객체의 주소를 이용하는 알고리즘으로 해시코드를 만들어 내기 때문에 모든 객체에 대해 hashCode()를 호출한 결과가 서로 유일한 훌륭한 방법이다.

○ 실습 예제

1. 학생들 이름 (key)과 github 주소 (value) 넣고 검색해보기

//HashMap 생성
HashMap<String, String> map = new HashMap<>();

//데이터 put
map.put("조예지", "https://github.com/coastby/java-project/tree/main/java-project/src");
map.put("권하준",	"https://github.com/dongyeon-0822/java-project-exercise");
map.put("조성윤",	"https://github.com/kang-subin/Java");
map.put("안예은",	"https://github.com/KoKwanwun/LikeLion.git");
map.put("남우빈",	"https://github.com/lcomment/Algorithm_Solution--Java/tree/main/LikeLion");
map.put("최경민",	"https://github.com/cmkxak/likelion-java-course");
map.put("안준휘",	"https://github.com/rnrudejr9/CodeLion-git-test");
map.put("하채민",	"https://github.com/Qkite/java-excercise-01/tree/main/src");
map.put("허도한",	"https://github.com/lucyoz/java-exercise");


System.out.println("맵의 게수는 "+ map.size() + "개 입니다.");	//맵의 개수는 9개입니다.
System.out.println(map.get("조예지"));						//https://github.com/coastby/java-project/tree/main/java-project/src

2. 특정 string에 있는 알파벳 개수 세기

String s에 있는 a~z까지 알파벳의 개수를 세는 알고리즘을 구현 해보세요.
대소문자는 구별하지 않습니다.

2-1) isAlphabet() 구현하기
String의 특정 문자가 알파벳이 맞으면 true, 아니면 false를 반환하는 함수

static boolean isAlphabet(char ch) {
	boolean result = false;
    //ch를 아스키로 바꾸지 않아도 바로 비교 가능
    if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
	    result = true;
    }
    return result;
}

2-2) Map<String, Integer> map = a~z까지 등록

//알파벳 키값 세팅
for (char c = 'A'; c <= 'Z'; c++) {
	alphabetMap.put(c, 0);
}

2-3) 하나씩 세어서 카운팅 & 출력

public static void main(String[] args) {
    String s1 = "aAAaab...bbcc//dd-efft-gg".toUpperCase();
    HashMap<Character, Integer> alphabetMap = new HashMap<>();

	//알파벳 키값 세팅
    for (char c = 'A'; c <= 'Z'; c++) {
    	alphabetMap.put(c, 0);
    }
    //하나씩 찾아서 카운팅
    for (int i = 0; i < s1.length(); i++) {
    	char ch = s1.charAt(i);
        if (isAlphabet(ch)) {
                alphabetMap.put(ch, alphabetMap.get(ch)+1);
        }
    }
    System.out.println(alphabetMap);

}
profile
훈이야 화이팅
post-custom-banner

0개의 댓글