HashMap
에 값을 추가하고 싶습니다. 같은 클래스. 두 가지 해결책이 있습니다.
-
static
로 모든 값 추가 - 첫 번째 메서드가 호출되면 값을 추가
솔루션 # 1 :
private static Map<Character, String> codes = new HashMap<>(); static { codes.put("A", ".-"); codes.put("B", "-..."); codes.put("C", "-.-."); codes.put("D", "-.."); codes.put("E", "."); codes.put("F", "..-."); // ... }
솔루션 # 2 :
boolean methodIsCalled = false; public static char decode(String s) { if(!methodIsCalled) { addValues(); methodIsCalled = true; } // ... } private static void addValues() { codes.put("A", ".-"); codes.put("B", "-..."); codes.put("C", "-.-."); codes.put("D", "-.."); codes.put("E", "."); codes.put("F", "..-."); // ... }
어떤 것이 가장 효율적입니까? 가장 좋은 방법은 무엇입니까?
댓글
- 애초에 HashMap에 삽입하는 이유는 무엇입니까? 26 개 문자열 배열이 아닌 이유는 무엇입니까?
- 26 개 문자열 배열이이 문제를 어떻게 해결합니까? 특히 매핑은 어떻게하나요? A-> 0, B-> 0, …, 염두에두고있는 암시 적 변환이 있습니까?
- @Ali 최종 배열은 불변성과 초기화를 처리합니다. A- > 0, B- > 1은 필요한 다른 라이브러리, 추가 정적 블록 또는 건축업자. ' 명확하고 합리적입니다.
- @MichaelT 사용자가 모스 부호에 대한 매핑, 문자열 배열을 원할 경우이 특정 예의 경우 26 사이즈는 괜찮지 만 일반적인 해결책은 아닙니다. 내 대답은이 특정 솔루션이 아닌 일반적인 솔루션에 대한 것이 었습니다. 많은 경우 도메인이 너무 커서 정수에 대한 직접 매핑을 사용할 수없고 해시 맵을 사용해야합니다.
- @MichaelT btw, 배열은 크기 만 변경할 수 있지만 변경할 수 있습니다. 그 요소 중 하나. a [0] = " new val ".
답변
해시 맵이 정적이고 한 번만 초기화되고 클래스의 모든 인스턴스에서 공유되므로 솔루션 1이 문제가 될 수 있습니다. 이것이 의도 한 동작입니까, 아니면 각 인스턴스에 자체 맵이 있기를 원합니까? 하나의 맵만있는 경우 정적 맵을 사용하는 대신 생성자에 세트를 전달하는 것이 좋습니다. 예를 들면 다음과 같습니다.
public class Data { private final Map<Character, String> codes; public Data(Map<Character, String> codes) { this.codes = codes} }
솔루션 2는 필요할 때마다 세트의 지연 초기화 오버 헤드를 제거하고 프로그램 논리에 추악한 검사 methodIsCalled
를 추가합니다. 생성자에서지도를 초기화하는 것이 더 나은 옵션이라고 생각합니다.
public class Data { private final Map<Character, String> codes; public Data() { this.codes = new HashMap<>(); codes.put("A", ".-"); codes.put("B", "-..."); codes.put("C", "-.-."); codes.put("D", "-.."); codes.put("E", "."); codes.put("F", "..-."); } }
답변해야 할 또 다른 질문은 나중에이 해시 맵의 값을 변경하는 경우입니다. 또는 아닙니다. 변경하지 않으면 변경 불가능한 hashMaps를 찾는 것이 좋습니다. 한 가지 옵션은 Collections.unmodifiableMap (map)을 사용하는 것입니다.
또한 Google Guava 라이브러리를 사용하여지도를 초기화 할 수 있습니다. 한 줄로 변경 불가능한지도 얻기 :
ImmutableMap.<Character, String>builder() .put("A", ".-") .put("B", "-...") .put("C", "-.-.") .put("D", "-..") .put("E", ".") .put("F", "..-.") .build();
답변
어떤 것도 이길 수 없습니다. 메모리 소비가 최적화 된 Guava의 ImmutableMap이 있지만 다음은 한 쌍의 순수한 솔루션입니다.
/* Name of the class has to be "Main" only if the class is public. */ class Ideone { private static final Map<Character, String> codes1; static { Map<Character, String> temp= new HashMap<Character, String>(); temp.put("A", ".-"); temp.put("B", "-..."); temp.put("C", "-.-."); temp.put("D", "-.."); temp.put("E", "."); temp.put("F", "..-."); // ... codes1 = Collections.unmodifiableMap(temp); } private static final Map<Character, String> codes2 = Collections.unmodifiableMap(new HashMap<Character, String>() { { put("A", ".-"); put("B", "-..."); put("C", "-.-."); put("D", "-.."); put("E", "."); put("F", "..-."); // ... } }); }
Answer
지연 초기화를 고집하지 않으면 (그리고 26 개 항목으로 구성된 작고 성장하지 않는 맵의 경우) 가독성을 위해 최적화하지 않는 이유는 무엇입니까? 나는 항상
private static Map<Character, String> codes = newMap( "A", ".-", "B", "-...", "C", "-.-.", ... );
(적절하게 정의 된 도우미 함수 newMap
포함)와 같은 것을 사용합니다.
코멘트
- 매개 변수 팩으로 newMap을 작성할 수도 있습니까?
- @ VF1 varargs를 사용하여 일반 함수로 정의하면 가능합니다. .
답변
이 경우 질문은 효율적인 방법이 아니라 언제 수행합니까? 실제로지도를 초기화하고 준비해야합니다.
정적 초기화의 경우-클래스가로드 될 때까지
“거대한”설정이 필요한 경우 지연로드 방식이 필요할 수 있습니다. “매핑하고 종종 이러한 값이 값 비싼 소스 (예 : 네트워크를 통해)에서 나온다고 말하면 외부 플래그가 필요하지 않을 수도 있습니다.
Collection.isEmpty ()는 이미 초기화되었는지 여부를 알려줍니다. 여부 (물론 초기화 할 값이 하나 이상 있어야 함)