IT이야기

정적 맵을 초기화하려면 어떻게 해야 하는가?

cyworld 2022. 5. 22. 11:26
반응형

정적 맵을 초기화하려면 어떻게 해야 하는가?

정전기 초기화를 어떻게 하시겠습니까?Map자바에서?

방법 1: 정적 이니셜라이저
방법 2: 인스턴스 이니셜라이저(익명 하위 클래스) 또는 다른 방법?

각각의 장단점은 무엇인가?

다음은 두 가지 방법을 보여 주는 예다.

import java.util.HashMap;
import java.util.Map;

public class Test {
    private static final Map<Integer, String> myMap = new HashMap<>();
    static {
        myMap.put(1, "one");
        myMap.put(2, "two");
    }

    private static final Map<Integer, String> myMap2 = new HashMap<>(){
        {
            put(1, "one");
            put(2, "two");
        }
    };
}

인스턴스 이니셜라이저는 이 경우 통사당일 뿐이지, 그렇지?나는 네가 왜 단지 초기화를 위해 익명 수업이 더 필요한지 모르겠다.그리고 만약 만들어지는 수업이 최종이라면 그것은 효과가 없을 것이다.

고정 이니셜라이저를 사용하여 불변의 지도를 만들 수도 있다.

public class Test {
    private static final Map<Integer, String> myMap;
    static {
        Map<Integer, String> aMap = ....;
        aMap.put(1, "one");
        aMap.put(2, "two");
        myMap = Collections.unmodifiableMap(aMap);
    }
}

나는 고정적이고 불변한 지도를 초기화하는 구아바 방식을 좋아한다.

static final Map<Integer, String> MY_MAP = ImmutableMap.of(
    1, "one",
    2, "two"
);

보시다시피 (의 편리한 공장 방식 때문에) 매우 간결하다.

지도에 5개 이상의 항목이 포함되도록 하려면 더 이상 사용할 수 없음ImmutableMap.of(). 대신 다음 라인을 따라 시도하십시오.

static final Map<Integer, String> MY_MAP = ImmutableMap.<Integer, String>builder()
    .put(1, "one")
    .put(2, "two")
    // ... 
    .put(15, "fifteen")
    .build();

Guava의 불변 수집 유틸리티의 이점에 대한 자세한 내용은 Guava 사용자 안내서에서 설명되는 불변 수집을 참조하십시오.

(의 일부) Guava는 Google Collections라고 불렸었다.Java 프로젝트에서 아직 이 라이브러리를 사용하지 않았다면, 시도해 볼 것을 강력히 추천한다!과바는 동료 SO 사용자들의 동의에 따라 빠르게 자바에게 가장 인기 있고 유용한 무료 제3자 리브 중 하나가 되었다.(만약 당신이 그것을 처음 접한다면, 그 링크 뒤에는 훌륭한 학습 자원이 있다.


업데이트(2015):자바 8에 대해서는, 글쎄, 나는 다른 어떤 것보다도 훨씬 깨끗하기 때문에 여전히 Guava 접근법을 사용할 것이다.Guava 종속성을 원하지 않는 경우, 이전 초기화 방법을 고려하십시오.2차원 배열과 스트림 API를 사용한 해킹은 내게 물어보면 꽤 추악하고, 키와 값이 같은 유형이 아닌 맵을 만들어야 한다면(예:Map<Integer, String>그 문제에서

일반적으로 구아바의 미래에 대해서는 자바 8에 관해서 루이 와세르만은 2014년에 이렇게 말했고, 2016년에는 구아바 21이 자바 8요구하고 적절하게 지원할 것이라고 발표하였다.


업데이트(2016):Tagir Valeev가 지적하는 와 같이, Java 9는 수집품에 대한 편의 공장 방법을 추가함으로써 순수 JDK만 사용하여 이 방법을 최종적으로 깨끗하게 만들 것이다.

static final Map<Integer, String> MY_MAP = Map.of(
    1, "one", 
    2, "two"
);

다음을 사용할 수 있다.

public class Test {
    private static final Map<Integer, String> MY_MAP = createMap();

    private static Map<Integer, String> createMap() {
        Map<Integer, String> result = new HashMap<>();
        result.put(1, "one");
        result.put(2, "two");
        return Collections.unmodifiableMap(result);
    }
}
  1. 그것은 내가 개인적으로 나쁜 스타일이라고 생각하는 익명의 수업을 피하고, 또한 피한다.
  2. 그것은 지도 제작을 더욱 분명하게 한다.
  3. 그것은 지도를 수정할 수 없게 만든다.
  4. MY_MAP가 상수이므로 상수처럼 이름을 붙일 것이다.

Java 5는 다음과 같은 보다 컴팩트한 구문을 제공한다.

static final Map<String , String> FLAVORS = new HashMap<String , String>() {{
    put("Up",    "Down");
    put("Charm", "Strange");
    put("Top",   "Bottom");
}};

두 번째 방법의 한 가지 장점은 로 포장할 수 있다는 것이다.Collections.unmodifiableMap()어떤 것도 나중에 컬렉션을 업데이트하지 않을 것을 보장하기 위해:

private static final Map<Integer, String> CONSTANT_MAP = 
    Collections.unmodifiableMap(new HashMap<Integer, String>() {{ 
        put(1, "one");
        put(2, "two");
    }});

 // later on...

 CONSTANT_MAP.put(3, "three"); // going to throw an exception!

Map.of자바 9+로

private static final Map<Integer, String> MY_MAP = Map.of(1, "one", 2, "two");

자세한 내용은 JEP 269를 참조하십시오.JDK 9는 2017년 9월에 일반에 출시되었다.

Java 8 단선 정적 맵 이니셜라이저:

private static final Map<String, String> EXTENSION_TO_MIMETYPE =
    Arrays.stream(new String[][] {
        { "txt", "text/plain" }, 
        { "html", "text/html" }, 
        { "js", "application/javascript" },
        { "css", "text/css" },
        { "xml", "application/xml" },
        { "png", "image/png" }, 
        { "gif", "image/gif" }, 
        { "jpg", "image/jpeg" },
        { "jpeg", "image/jpeg" }, 
        { "svg", "image/svg+xml" },
    }).collect(Collectors.toMap(kv -> kv[0], kv -> kv[1]));

편집: 초기화하려면Map<Integer, String>질문에서와 같이, 당신은 다음과 같은 것이 필요하다.

static final Map<Integer, String> MY_MAP = Arrays.stream(new Object[][]{
        {1, "one"},
        {2, "two"},
}).collect(Collectors.toMap(kv -> (Integer) kv[0], kv -> (String) kv[1]));

편집(2):을 사용하는 더 이 있다.new SimpleEntry<>(k, v)전화. 다음 대답을 확인하십시오. https://stackoverflow.com/a/37384773/3950982

자바 9

우리는 각 항목을 만들기 위해 전화를 사용할 수 있다.

import static java.util.Map.entry;
private static final Map<Integer,String> map = Map.ofEntries(
        entry(1, "one"),
        entry(2, "two"),
        entry(3, "three"),
        entry(4, "four"),
        entry(5, "five"),
        entry(6, "six"),
        entry(7, "seven"),
        entry(8, "eight"),
        entry(9, "nine"),
        entry(10, "ten"));

우리는 또한 사용할 수 있다.Map.of여기서 Tagir가 제안한 바와 같이, 그러나 우리는 10개 이상의 항목을 가지고 있을 수 없다.Map.of.

자바 8

우리는 지도 항목의 스트림을 만들 수 있다.우리는 이미 두 번의 구현을 가지고 있다.Entryjava.util.AbstractMapSimpleEntrySimpleImableEntry 입니다.이 예에서는 전자를 다음과 같이 사용할 수 있다.

import java.util.AbstractMap.*;
private static final Map<Integer, String> myMap = Stream.of(
            new SimpleEntry<>(1, "one"),
            new SimpleEntry<>(2, "two"),
            new SimpleEntry<>(3, "three"),
            new SimpleEntry<>(4, "four"),
            new SimpleEntry<>(5, "five"),
            new SimpleEntry<>(6, "six"),
            new SimpleEntry<>(7, "seven"),
            new SimpleEntry<>(8, "eight"),
            new SimpleEntry<>(9, "nine"),
            new SimpleEntry<>(10, "ten"))
            .collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue));
            

Eclipse Collections를 사용하면 다음과 같은 모든 기능이 작동한다.

import java.util.Map;

import org.eclipse.collections.api.map.ImmutableMap;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.impl.factory.Maps;

public class StaticMapsTest
{
    private static final Map<Integer, String> MAP =
        Maps.mutable.with(1, "one", 2, "two");

    private static final MutableMap<Integer, String> MUTABLE_MAP =
       Maps.mutable.with(1, "one", 2, "two");


    private static final MutableMap<Integer, String> UNMODIFIABLE_MAP =
        Maps.mutable.with(1, "one", 2, "two").asUnmodifiable();


    private static final MutableMap<Integer, String> SYNCHRONIZED_MAP =
        Maps.mutable.with(1, "one", 2, "two").asSynchronized();


    private static final ImmutableMap<Integer, String> IMMUTABLE_MAP =
        Maps.mutable.with(1, "one", 2, "two").toImmutable();


    private static final ImmutableMap<Integer, String> IMMUTABLE_MAP2 =
        Maps.immutable.with(1, "one", 2, "two");
}

Eclipse Collections를 사용하여 초기 지도를 정적으로 초기화할 수도 있다.

import org.eclipse.collections.api.map.primitive.ImmutableIntObjectMap;
import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
import org.eclipse.collections.impl.factory.primitive.IntObjectMaps;

public class StaticPrimitiveMapsTest
{
    private static final MutableIntObjectMap<String> MUTABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two");

    private static final MutableIntObjectMap<String> UNMODIFIABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .asUnmodifiable();

    private static final MutableIntObjectMap<String> SYNCHRONIZED_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .asSynchronized();

    private static final ImmutableIntObjectMap<String> IMMUTABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .toImmutable();

    private static final ImmutableIntObjectMap<String> IMMUTABLE_INT_OBJ_MAP2 =
            IntObjectMaps.immutable.<String>empty()
                    .newWithKeyValue(1, "one")
                    .newWithKeyValue(2, "two");
} 

참고: 나는 Eclipse Collections의 커밋자입니다.

이런 상황에서 나는 결코 익명의 하위 클래스를 만들지 않을 것이다.예를 들어 지도를 수정할 수 없도록 하려면 정적 이니셜라이저가 동일하게 잘 작동한다.

private static final Map<Integer, String> MY_MAP;
static
{
    Map<Integer, String>tempMap = new HashMap<Integer, String>();
    tempMap.put(1, "one");
    tempMap.put(2, "two");
    MY_MAP = Collections.unmodifiableMap(tempMap);
}

어쩌면 구글 컬렉션을 보는 것이 흥미로울지도 모른다. 예를 들어, 구글 컬렉션을 그들의 페이지에 있는 비디오와 같이 말이다.지도와 세트를 초기화할 수 있는 다양한 방법을 제공하고, 불변의 컬렉션을 제공한다.

업데이트: 이 라이브러리의 이름은 Guava 입니다.

나는 익명 수업을 좋아한다. 왜냐하면 그것은 그것을 다루는 것이 쉽기 때문이다.

public static final Map<?, ?> numbers = Collections.unmodifiableMap(new HashMap<Integer, String>() {
    {
        put(1, "some value");
                    //rest of code here
    }
});
public class Test {
    private static final Map<Integer, String> myMap;
    static {
        Map<Integer, String> aMap = ....;
        aMap.put(1, "one");
        aMap.put(2, "two");
        myMap = Collections.unmodifiableMap(aMap);
    }
}

만약 우리가 둘 이상의 상수를 선언한다면, 그 코드는 정적 블록으로 쓰여질 것이고, 그것은 미래에 유지되기 어렵다.그래서 익명 수업을 이용하는 것이 더 좋다.

public class Test {

    public static final Map numbers = Collections.unmodifiableMap(new HashMap(2, 1.0f){
        {
            put(1, "one");
            put(2, "two");
        }
    });
}

그리고 상수를 상수로 취급할 수 없는 다른 현명한 상수에 수정 불가능한 맵을 사용하는 것이 좋다.

정적 블록 스타일보다 "더블 브레이스 초기화" 스타일을 강력히 제안할 수 있다.

누군가는 익명수업, 오버헤드, 퍼포먼스 등을 좋아하지 않는다고 말할 수 있다.

그러나 내가 더 고려하는 것은 코드 가독성과 유지관리성이다.이런 관점에서, 나는 이중 버팀대가 정적 방법보다 더 나은 코드 스타일이라고 생각한다.

  1. 원소들은 내포되어 있고 인라인으로 되어 있다.
  2. 절차적인 것이 아니라 OO가 더 OO이다.
  3. 성능 영향은 매우 작으며 무시될 수 있다.
  4. 더 나은 IDE 개요 지원(다음에는 많은 익명 정적{} 블록)
  5. 당신은 그들의 관계를 가져오기 위해 몇 줄의 코멘트를 저장했다.
  6. 초기화되지 않은 개체의 요소 누출/인스턴스 리드 발생을 예외 및 바이트 코드 최적화 도구에서 방지하십시오.
  7. 정적 블록의 실행 순서에 대해 걱정하지 마십시오.

또한 익명 클래스의 GC를 알고 있으며, 다음을 사용하여 항상 일반 해시맵으로 변환할 수 있다.new HashMap(Map map).

다른 문제에 직면할 때까지 당신은 이것을 할 수 있다.그럴 경우 다른 코딩 스타일(예: 정적, 공장 클래스 없음)을 사용하여 코딩하십시오.

평소와 같이 Apache-commons에는 MapUtils.putAlls(Map, Object[]) 메서드 MapUtils.putAll:

예를 들어, 색상 맵을 작성하려면:

Map<String, String> colorMap = MapUtils.putAll(new HashMap<String, String>(), new String[][] {
     {"RED", "#FF0000"},
     {"GREEN", "#00FF00"},
     {"BLUE", "#0000FF"}
 });

여기 내가 제일 좋아하는 것이 있다.

  • 과바의 것을 쓰고 싶지 않다(또는 사용할 수 없다).ImmutableMap.of()
  • 아니면 돌연변이가 필요해Map
  • 아니면 10개 이상의 진입 제한이 필요하다.Map.of(): JDK9+
public static <A> Map<String, A> asMap(Object... keysAndValues) {
  return new LinkedHashMap<String, A>() {{
    for (int i = 0; i < keysAndValues.length - 1; i++) {
      put(keysAndValues[i].toString(), (A) keysAndValues[++i]);
    }
  }};
}

매우 콤팩트하며, 표류 값(즉, 값이 없는 최종 키)을 무시한다.

사용량:

Map<String, String> one = asMap("1stKey", "1stVal", "2ndKey", "2ndVal");
Map<String, Object> two = asMap("1stKey", Boolean.TRUE, "2ndKey", new Integer(2));

익명 클래스를 생성하지 않으려면 정적 이니셜라이저를 사용하는 것이 좋으므로 정적 이니셜라이저로 초기화하는 팁을 나열하십시오.나열된 모든 솔루션/팁은 유형 안전하다.

주: 질문은 지도를 수정할 수 없게 만드는 것에 대해 아무 말도 하지 않기 때문에, 나는 그것을 생략할 것이다. 그러나 그것은 쉽게 할 수 있다는 것을 알고 있다.Collections.unmodifiableMap(map).

퍼스트 팁

첫 번째 팁은 지도에 대한 로컬 참조를 할 수 있다는 것이며, 지도에 다음과 같은 짧은 이름을 입력하십시오.

private static final Map<Integer, String> myMap = new HashMap<>();
static {
    final Map<Integer, String> m = myMap; // Use short name!
    m.put(1, "one"); // Here referencing the local variable which is also faster!
    m.put(2, "two");
    m.put(3, "three");
}

두 번째 팁

두 번째 팁은 항목을 추가하기 위한 도우미 방법을 만들 수 있다는 것이다. 또한 다음 작업을 수행하려면 이 도우미 방법을 공개하십시오.

private static final Map<Integer, String> myMap2 = new HashMap<>();
static {
    p(1, "one"); // Calling the helper method.
    p(2, "two");
    p(3, "three");
}

private static void p(Integer k, String v) {
    myMap2.put(k, v);
}

여기의 도우미 방법은 요소만 추가할 수 있기 때문에 다시 사용할 수 없다.myMap2할 수 수 는 더 않을 다시 사용할 수 있도록 지도 자체를 도우미 방법의 파라미터로 만들 수 있지만, 그러면 초기화 코드는 더 짧아지지 않을 것이다.

세 번째 팁

세 번째 팁은 채우기 기능을 사용하여 재사용 가능한 빌더와 같은 도우미 클래스를 만들 수 있다는 것이다.이 수업은 형식적으로 안전한 10줄짜리 간단한 도우미 수업이다.

public class Test {
    private static final Map<Integer, String> myMap3 = new HashMap<>();
    static {
        new B<>(myMap3)   // Instantiating the helper class with our map
            .p(1, "one")
            .p(2, "two")
            .p(3, "three");
    }
}

class B<K, V> {
    private final Map<K, V> m;

    public B(Map<K, V> m) {
        this.m = m;
    }

    public B<K, V> p(K k, V v) {
        m.put(k, v);
        return this; // Return this for chaining
    }
}

만약 당신이 수정할 수 없는 지도를 원한다면, 마침내 Java 9는 멋진 공장 방법을 추가했다.ofMap 유사한 방법이 Set, List에도 추가된다.

Map<String, String> unmodifiableMap = Map.of("key1", "value1", "key2", "value2");

네가 만들고 있는 익명 수업은 잘 돼.그러나 당신은 이것이 내부 클래스라는 것을 알아야 하며, 따라서 그것은 주변 클래스 인스턴스에 대한 참조를 포함할 것이다.그래서 당신은 그것을 가지고 어떤 것을 할 수 없다는 것을 알게 될 것이다.아주 이상한 실수를 하게 될 거야.

그렇게 말하긴 했지만, 당신이 알고 있는 한 이 접근법은 괜찮다.나는 대부분의 시간을 모든 종류의 컬렉션을 간결하게 초기화하는 데 사용한다.

편집: 코멘트에서 이 클래스가 정적 클래스라는 점을 올바르게 지적했다.분명히 나는 이것을 충분히 자세히 읽지 않았다.하지만 내 의견은 여전히 익명의 내부 수업에도 적용된다.

비교적 안전한 컴파일 시간 유형 검사를 실행 시간으로 전환하십시오.

static final Map<String, Integer> map = MapUtils.unmodifiableMap(
    String.class, Integer.class,
    "cat",  4,
    "dog",  2,
    "frog", 17
);

이 구현은 다음과 같은 오류를 포착해야 한다.

import java.util.HashMap;

public abstract class MapUtils
{
    private MapUtils() { }

    public static <K, V> HashMap<K, V> unmodifiableMap(
            Class<? extends K> keyClazz,
            Class<? extends V> valClazz,
            Object...keyValues)
    {
        return Collections.<K, V>unmodifiableMap(makeMap(
            keyClazz,
            valClazz,
            keyValues));
    }

    public static <K, V> HashMap<K, V> makeMap(
            Class<? extends K> keyClazz,
            Class<? extends V> valClazz,
            Object...keyValues)
    {
        if (keyValues.length % 2 != 0)
        {
            throw new IllegalArgumentException(
                    "'keyValues' was formatted incorrectly!  "
                  + "(Expected an even length, but found '" + keyValues.length + "')");
        }

        HashMap<K, V> result = new HashMap<K, V>(keyValues.length / 2);

        for (int i = 0; i < keyValues.length;)
        {
            K key = cast(keyClazz, keyValues[i], i);
            ++i;
            V val = cast(valClazz, keyValues[i], i);
            ++i;
            result.put(key, val);
        }

        return result;
    }

    private static <T> T cast(Class<? extends T> clazz, Object object, int i)
    {
        try
        {
            return clazz.cast(object);
        }
        catch (ClassCastException e)
        {
            String objectName = (i % 2 == 0) ? "Key" : "Value";
            String format = "%s at index %d ('%s') wasn't assignable to type '%s'";
            throw new IllegalArgumentException(String.format(format, objectName, i, object.toString(), clazz.getSimpleName()), e);
        }
    }
}

Java 8에서는 다음과 같은 패턴을 사용하게 되었다.

private static final Map<String, Integer> MAP = Stream.of(
    new AbstractMap.SimpleImmutableEntry<>("key1", 1),
    new AbstractMap.SimpleImmutableEntry<>("key2", 2)
).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

가장 간결하고 약간 우회적인 것은 아니지만.

  • 하지 않다java.util
  • 키와 가치를 위해 다양한 유형을 쉽게 수용할 수 있는 유형도 다양하다.

지도에 값을 하나만 추가하면 되는 경우 Collections.singletonMap:

Map<K, V> map = Collections.singletonMap(key, value)

선인장 이용 및 이용 가능:

private static final Map<String, String> MAP = new StickyMap<>(
  new MapEntry<>("name", "Jeffrey"),
  new MapEntry<>("age", "35")
);

당신의 두 번째 접근법(Double Brace 초기화)은 반(反)패턴으로 생각되므로, 나는 첫 번째 접근법을 택하겠다.

정적 맵을 초기화하는 또 다른 쉬운 방법은 다음과 같은 유틸리티 기능을 사용하는 것이다.

public static <K, V> Map<K, V> mapOf(Object... keyValues) {
    Map<K, V> map = new HashMap<>(keyValues.length / 2);

    for (int index = 0; index < keyValues.length / 2; index++) {
        map.put((K)keyValues[index * 2], (V)keyValues[index * 2 + 1]);
    }

    return map;
}

Map<Integer, String> map1 = mapOf(1, "value1", 2, "value2");
Map<String, String> map2 = mapOf("key1", "value1", "key2", "value2");

참고: 입력Java 9Map.of를 사용할 수 있다.

나는 정적 이니셜라이저 구문을 좋아하지 않으며 익명의 하위 클래스에 대해 확신할 수 없다.일반적으로, 나는 정적 이니셜라이저를 사용하는 것에 대한 모든 반대와 사전 답변에서 언급된 익명의 하위 클래스를 사용하는 것에 대한 모든 반대 의견에 동의한다.반면에 - 이 게시물들에 제시된 프로들은 나에게 충분하지 않다.정적 초기화 방법 사용:

public class MyClass {
    private static final Map<Integer, String> myMap = prepareMap();

    private static Map<Integer, String> prepareMap() {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "one");
        hashMap.put(2, "two");

        return hashMap;
    }
}

내가 사용하는 접근방식이 어떤 답변에도 게시되지 않았으므로(그리고 좋아하게 되었다) 여기에 다음과 같은 내용이 있다.

나는 정적 이니셜라이저를 사용하는 것을 좋아하지 않으며, 익명 수업은 각 인스턴스마다 새로운 클래스를 만드는 것이기 때문에 나는 익명 클래스를 좋아하지 않는다.

대신 다음과 같은 초기화를 선호한다.

map(
    entry("keyA", "val1"),
    entry("keyB", "val2"),
    entry("keyC", "val3")
);

유감스럽게도 이러한 방법은 표준 자바 라이브러리의 일부가 아니므로, 다음과 같은 방법을 정의하는 유틸리티 라이브러리를 작성(또는 사용)해야 할 것이다.

 public static <K,V> Map<K,V> map(Map.Entry<K, ? extends V>... entries)
 public static <K,V> Map.Entry<K,V> entry(K key, V val)

('static 가져오기'를 사용하여 메서드의 이름 앞에 붙일 필요가 없음)

다른 컬렉션(list, set, sortedSet, sortedMap 등)에 대해 유사한 정적 방법을 제공하는 것이 유용하다는 것을 알았다.

그것은 json 객체 초기화만큼 좋지는 않지만, 가독성에 관한 한, 그런 방향으로의 한 걸음이다.

Java는 지도 리터럴을 지원하지 않기 때문에 지도 인스턴스는 항상 명시적으로 인스턴스화하고 채워야 한다.

다행히 자바에서는 공장법을 이용하여 지도 리터럴의 행태를 대략적으로 추정할 수 있다.

예를 들면 다음과 같다.

public class LiteralMapFactory {

    // Creates a map from a list of entries
    @SafeVarargs
    public static <K, V> Map<K, V> mapOf(Map.Entry<K, V>... entries) {
        LinkedHashMap<K, V> map = new LinkedHashMap<>();
        for (Map.Entry<K, V> entry : entries) {
            map.put(entry.getKey(), entry.getValue());
        }
        return map;
    }
    // Creates a map entry
    public static <K, V> Map.Entry<K, V> entry(K key, V value) {
        return new AbstractMap.SimpleEntry<>(key, value);
    }

    public static void main(String[] args) {
        System.out.println(mapOf(entry("a", 1), entry("b", 2), entry("c", 3)));
    }
}

출력:

{a=1, b=2, c=3}

한 번에 한 요소씩 지도를 만들고 채우는 것보다 훨씬 편리하다.

JEP 269는 Collections API를 위한 몇 가지 편리한 공장 방법을 제공한다.이 공장 방식은 현재 자바 버전인 8에 있는 것이 아니라 자바 9 릴리즈를 위해 계획되어 있다.

을 위해Map두 가지 공장 방법이 있다.of그리고ofEntries. 사용of, 교대로 키/값 쌍을 전달할 수 있다.예를 들어, 다음을 생성하기 위해Map맘에 들다{age: 27, major: cs}:

Map<String, Object> info = Map.of("age", 27, "major", "cs");

『10』의 『10』에.of10개의 키/값 쌍이 포함된 지도를 만들 수 있다.이러한 제한이나 키/값을 교체하는 것이 마음에 들지 않는 경우ofEntries:

Map<String, Object> info = Map.ofEntries(
                Map.entry("age", 27),
                Map.entry("major", "cs")
);

둘 다of그리고ofEntries불변의 것을 되돌려 줄 것이다.Map그래서 당신은 공사 후에 그들의 요소들을 바꿀 수 없다.JDK 9 Early Access를 사용하여 이러한 기능을 사용해 보십시오.

음... 나는 에넘스를 좋아해;)

enum MyEnum {
    ONE   (1, "one"),
    TWO   (2, "two"),
    THREE (3, "three");

    int value;
    String name;

    MyEnum(int value, String name) {
        this.value = value;
        this.name = name;
    }

    static final Map<Integer, String> MAP = Stream.of( values() )
            .collect( Collectors.toMap( e -> e.value, e -> e.name ) );
}

나는 답을 읽었고 나만의 지도 제작자를 쓰기로 결심했다.자유롭게 복사 붙여넣고 즐기세요.

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * A tool for easy creation of a map. Code example:<br/>
 * {@code MapBuilder.of("name", "Forrest").and("surname", "Gump").build()}
 * @param <K> key type (inferred by constructor)
 * @param <V> value type (inferred by constructor)
 * @author Vlasec (for http://stackoverflow.com/a/30345279/1977151)
 */
public class MapBuilder <K, V> {
    private Map<K, V> map = new HashMap<>();

    /** Constructor that also enters the first entry. */
    private MapBuilder(K key, V value) {
        and(key, value);
    }

    /** Factory method that creates the builder and enters the first entry. */
    public static <A, B> MapBuilder<A, B> mapOf(A key, B value) {
        return new MapBuilder<>(key, value);
    }

    /** Puts the key-value pair to the map and returns itself for method chaining */
    public MapBuilder<K, V> and(K key, V value) {
        map.put(key, value);
        return this;
    }

    /**
     * If no reference to builder is kept and both the key and value types are immutable,
     * the resulting map is immutable.
     * @return contents of MapBuilder as an unmodifiable map.
     */
    public Map<K, V> build() {
        return Collections.unmodifiableMap(map);
    }
}

편집: 최근에 공용 정적 방법을 계속 찾음of꽤 자주 그리고 나는 약간 그것을 좋아한다.나는 그것을 코드에 추가해서 시공자를 비공개로 해서 정적인 공장 방식 패턴으로 전환했다.

편집2: 최근에는 더 이상 정적 방법이라는 것을 좋아하지 않는다.of정적 가져오기를 사용할 때는 상당히 안 좋아 보이기 때문이다.로 이름을 바꾸었다.mapOf대신에, 정적 수입에 더 적합하게 만든다.

참조URL: https://stackoverflow.com/questions/507602/how-can-i-initialise-a-static-map

반응형