ProgramingTip

정적지도를 초기화해야합니까?

bestdevel 2020. 9. 27. 13:19
반응형

정적지도를 초기화해야합니까?


MapJava 에서 정적 어떻게 초기화하십니까?

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

각각의 장단점은 무엇입니까?

다음은 두 가지 방법을 예입니다.

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

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

    private static final Map<Integer, String> myMap2 = new HashMap<Integer, String>(){
        {
            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);
    }
}

나는 정적 인 불변의 맵을 초기화 하는 Guava 방식을 좋아합니다 .

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

보시다시피 매우 간결합니다 (의 편리한 공장 방법 때문에 ).ImmutableMap

지도에 5 개 이상의 항목이 더 이상 사용할 수 없습니다 ImmutableMap.of(). 대신 다음 줄을 따라 시도하십시오 .ImmutableMap.builder()

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

Guava 사용 설명서에 설명변경 불가능한 수집 항목을 참조하십시오 .

(의 일부) Guava는 Google 컬렉션 이라고 불렀습니다 . 아직 Java 프로젝트 에서이 라이브러리를 사용하고 있지면 보는 것이 좋습니다 ! Guava는 동료 SO 사용자가 동의하는 대로 Java 용으로 가장 인기있는 유용한 기능 라이브러리 하나가 . (당신이 사용하는 익숙하지 않다면, 그 링크 훌륭한 학습 자원이 있습니다.)


업데이트 (2015) : Java 8의 경우 다른 것보다 훨씬 깨끗하기 때문에 여전히 Guava 접근 방식을 사용합니다. 구아바을 원하지 않는 종속성 경우 또는 일반 오래된 초기화를 메서드 고려하십시오 . 2 차원 배열 및 스트림 API를 사용 하여 해킹 은 저에게 물어 보면 매우 추하고 키와이 동일한 유형이 아닌 맵을 매개 변수 할 경우 (질문에서와 같이) 추악 해 처리 Map<Integer, String>합니다.

자바 팔에 일반적으로 구아바의 미래에 소개는, 루이 Wasserman 은이 말했다 2014 년 다시하고 [ 현재 발표 된 구아바 (21)가 발표 한 구아바 (8)가 필요합니다 .


Update (2016) :로 Tagir Valeev 보낸 지적 , 자바 (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<Integer, String>();
        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!

다음은 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]));

Edit (2) : new SimpleEntry<>(k, v)호출 스트림을 사용하는 i_am_zero의 더 나은 혼합 유형 지원 버전이 있습니다. 그 대답을 확인하십시오 : https://stackoverflow.com/a/37384773/3950982


자바 9에서

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

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


자바 9

우리는 다음 Map.ofEntries과 같이 사용할 수 있습니다 .

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의 답변에서 제안한대로 사용할 수도 있습니다 .Map.of

Java 8 (Neat 솔루션)

맵 항목 스트림을 만들 수 있습니다. 는 이미 두 우리 가지 구현이 Entryjava.util.AbstractMap있는 있습니다 SimpleEntrySimpleImmutableEntry을 . 이 예에서는 전자를 다음과 같이 사용할 수 있습니다.

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));

함께 이클립스 컬렉션 , 다음의 모든 작동합니다 :

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 컬렉션을 사용하여 기본 맵을 정적으로 초기화 할 수도 있습니다.

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 컬렉션의 커미터입니다.


이 상황에서는 익명의 하위 클래스를 만들지 언어로 작성합니다. 예를 들어 생성 된 맵을 수 완성해서 생성 한 정적 이니셜 라이가 똑같이 잘 작동합니다.

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);
}

페이지에있는 동영상과 같은 Google 컬렉션 을 확인하는 것이 흥미로울 수 있습니다 . 맵과 세트를 초기화하는 다양한 방법을 제공하고 변경이 불가능한 컬렉션도 제공합니다.

업데이트 :이 라이브러리의 이름은 이제 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");
        }
    });
}

그리고 상수로 unmodifiableMap을 사용하는 것이 좋습니다. 구분 상수로 취급 할 수 없습니다.


정적 블록 스타일보다 "이중 중괄호 초기화"스타일을 강력하게 제안 할 수 있습니다.

누군가는 익명의 클래스, 오버 헤드, 성능 등을 좋아하지 않는다고 말할 수 있습니다.

그러나 내가 더 고려하는 것은 코드 가독성과 유지 보수성입니다. 이 관점에서 이중 중괄호는 정적 메서드보다 더 나은 코드 스타일입니다.

  1. 요소는 중첩되고 인라인됩니다.
  2. 절차가 아닌 OO에 가깝습니다.
  3. 성능에 효율적으로 사용할 수 있습니다.
  4. 더 나은 IDE 개요 지원 (많은 익명 정적 {} 블록이 아님)

  5. 관계를 맺기 위해 몇 줄의 주석을 저장했습니다.
  6. 예외 및 바이트 코드 최적화 프로그램에서 초기화되지 않은 개체의 가능한 요소 / 인스턴스 리드를 방지합니다.
  7. 정적 블록의 실행 순서에 대해 걱정할 필요가 없습니다.

또한 익명 클래스의 GC를 알고 있으면 .NET을 사용하여 항상 일반 HashMap으로 변환 할 수 있습니다 new HashMap(Map map).

다른 문제에 직면 할 때까지 할 수 있습니다. 그렇게한다면 완전한 다른 코딩 스타일 (예 : 정적, 팩토리 클래스 없음)을 많이 사용합니다.


apache-commons에는 메소드와 같이 메소드 MapUtils.putAll (Map, Object [])이 있습니다 .

예를 들어, 색상 맵을 만들려면 :

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

Guava의 사용을 사용할 경우 사용 가능한 ImmutableMap.of()변경 항목이 필요한 경우 다음을 가장 좋아합니다 Map.

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));

Java 9 ofMap인터페이스에 멋진 팩토리 메소드 추가했습니다 . 설정, 목록에도 추가 방법이 추가됩니다.

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


익명 클래스 생성을 피하기 위해 정적 이니셜 라이저를 사용하는 것을 선호하는 것이 더 이상 목적이없는 정적 이니셜 라이저로 초기화하는 팁을하겠습니다. 모든 솔루션 / 팁은 형식이 안전합니다.

참고 : 이 질문은지도를 만들 수 있지만 아무 말도하지 않습니다 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);
}

여기서 도우미 메서드는 .NET Framework 요소를 추가 할 수 있기 때문에 추가 할 수 없습니다 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
    }
}

생성중인 익명 클래스가 잘 작동합니다. 다음은 내부 클래스 내부 클래스 인스턴스에 대한 참조를 포함합니다. 따라서 XStream사용하여 특정 작업을 수행 할 수 있습니다. 매우 이상한 오류가 발생합니다.

당신이 알고있는 한이 있어은 괜찮습니다. 나는 간결한 방식으로 모든 종류의 컬렉션을 초기화하기 위해 대부분의 시간을 사용합니다.

편집 : 정적 정적 클래스라는 주석에서 지적했습니다. 나는 분명히 충분히 자세히 읽었습니다. 그러나 내 의견 여전히 익명의 내부 클래스에 적용됩니다.


간결하고 실용적인 것을 보여줍니다. 타임 유형 검사를 실행으로 전환 할 수 있습니다.

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
  • 유형이 안전하고 키와 값에 대해 다양한 유형을 쉽게 수용 할 수 있습니다.

은 사용할 수 당신 있습니다 에서 Cactoos :StickyMapMapEntry

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

나는 정적 이니셜 라이저 구문을 좋아하지 않고 익명의 서브 클래스에 확신이 없습니다. 일반적으로 정적 정적 이니셜 라이저를 사용하는 모든 단점과 이전 사용에서 한 익명 하위 클래스를 사용하는 모든 단점에 동의합니다. 반면에 충분에 제시된 전문가는 저에게 충분하지 않습니다. 정적 초기화 방법을 사용하는 것을 선호합니다.

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")
);

안타깝게도 메소드는 표준 Java 라이브러리의 일부가 아니 메소드 다음 메소드를 정의하는 유틸리티 라이브러리를 작성 (또는 사용)해야합니다.

 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)

( '정적 가져 오기'를 사용하면 메소드 이름을 접두사로 필요가 없습니다)

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

json 초기화 초기화만큼 좋지는 않지만 가독성에 관한 한 그 방향으로 나아가는 단계입니다.


Java는 맵 리터럴을 지원하지 않기 때문에 맵 인스턴스는 항상 명시 적으로 인스턴스화되고 있어야합니다.

여러 가지 팩토리 메소드를 사용하여 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}

한 번에 한 요소 씩 맵을 만들고 채우는 것보다 훨씬 편리합니다.


맵에 하나의 값만 추가해야하는 경우 Collections.singletonMap 을 사용할 수 있습니다 .

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

두 번째 접근 방식 (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");

참고 : Map.ofJava 9 를 사용할 수 있습니다 .


JEP 269 는 Collections API에 대한 몇 가지 편리한 팩토리 메소드를 제공합니다. 이 팩토리 메소드는 현재 Java 버전 (8)이 있습니다 Java 9 릴리스에 계획되어 있습니다.

를 들어이 Map두 공장 방법은 다음과 것 ofofEntries. 를 사용하면 of교대로 키 / 값 쌍을 사용할 수 있습니다. 예를 들어, 다음 Map과 같이 만들려면 {age: 27, major: cs}다음을 수행하십시오.

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

현재에는 10 개의 오버로드 된 버전이 of있으므로 10 개의 키 / 값 쌍을 포함하는지도를 만들 수 있습니다. 이 제한 또는 대체 키 / 값이 마음에 들지에서 사용할 수 있습니다 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꽤 자주 찾고 조금 좋아합니다. 코드에 추가하고 생성 해 비공개로 설정하여 정적 팩토리 메서드 패턴으로 전환했습니다.

EDIT2 : 최근에는 of정적 가져 오기를 오기를 사용할 때 상당히 나빠 보이기 때문에 정적 메소드를 더 좋아하지 않습니다 . mapOf대신 이름을 변경하여 정적 가져 오기에 더 적합합니다.

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

반응형