[java] 문자 그대로 HashMap을 직접 초기화하는 방법은 무엇입니까?

다음과 같이 Java HashMap을 초기화하는 방법이 있습니까? :

Map<String,String> test =
    new HashMap<String, String>{"test":"test","test":"test"};

올바른 구문은 무엇입니까? 나는 이것에 관해 아무것도 찾지 못했다. 이것이 가능한가? 지도를 만들 때 절대 변경되지 않고 미리 알려진 일부 “최종 / 정적”값을지도에 넣는 가장 짧고 빠른 방법을 찾고 있습니다.



답변

모든 버전

단 하나의 항목 만 필요한 경우 :이 있습니다 Collections.singletonMap("key", "value").

Java 버전 9 이상의 경우 :

예, 지금 가능합니다. Java 9에는 맵 작성을 단순화하는 몇 가지 팩토리 메소드가 추가되었습니다.

// this works for up to 10 elements:
Map<String, String> test1 = Map.of(
    "a", "b",
    "c", "d"
);

// this works for any number of elements:
import static java.util.Map.entry;
Map<String, String> test2 = Map.ofEntries(
    entry("a", "b"),
    entry("c", "d")
);

모두 위의 예에서 testtest2단지지도를 표현하는 다른 방법으로, 동일합니다. Map.of그동안 방법은, 맵 10 개 요소까지에 대해 정의 된 Map.ofEntries방법은 그런 제한이 없습니다.

이 경우 결과 맵은 변경 불가능한 맵이됩니다. 지도를 변경할 수있게하려면 다시 복사 할 수 있습니다 (예 :mutableMap = new HashMap<>(Map.of("a", "b"));

( JEP 269Javadoc 참조 )

Java 버전 8까지 :

아니요, 모든 요소를 ​​수동으로 추가해야합니다. 익명 서브 클래스에서 이니셜 라이저를 사용하여 구문을 약간 더 짧게 만들 수 있습니다.

Map<String, String> myMap = new HashMap<String, String>() {{
        put("a", "b");
        put("c", "d");
    }};

그러나 익명 서브 클래스는 경우에 따라 원치 않는 동작을 일으킬 수 있습니다. 예를 들면 다음과 같습니다.

  • 메모리 소비, 디스크 공간 소비 및 시작 시간을 증가시키는 추가 클래스를 생성합니다.
  • 정적이 아닌 메소드의 경우 : 작성 메소드가 호출 된 오브젝트에 대한 참조를 보유합니다. 즉, 작성된 맵 오브젝트가 여전히 참조되는 동안 외부 클래스의 오브젝트를 가비지 콜렉션 할 수 없으므로 추가 메모리가 차단됩니다.

초기화에 함수를 사용하면 초기화 프로그램에서 맵을 생성 할 수 있지만 불쾌한 부작용을 피할 수 있습니다.

Map<String, String> myMap = createMap();

private static Map<String, String> createMap() {
    Map<String,String> myMap = new HashMap<String,String>();
    myMap.put("a", "b");
    myMap.put("c", "d");
    return myMap;
}


답변

이것은 한 가지 방법입니다.

HashMap<String, String> h = new HashMap<String, String>() {{
    put("a","b");
}};

그러나주의해서 위의 코드를 이해해야합니다 (HashMap에서 상속되는 새 클래스를 만듭니다). 따라서 http://www.c2.com/cgi/wiki?DoubleBraceInitialization
에서 자세한 내용을 읽
거나 Guava를 사용 하십시오 .

Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);


답변

타사 라이브러리를 허용하면 GuavaImmutableMap 을 사용 하여 리터럴과 같은 간결성을 얻을 수 있습니다 .

Map<String, String> test = ImmutableMap.of("k1", "v1", "k2", "v2");

이것은 최대 5 개의 키 / 값 쌍 에서 작동합니다. 그렇지 않으면 빌더를 사용할 수 있습니다 .

Map<String, String> test = ImmutableMap.<String, String>builder()
    .put("k1", "v1")
    .put("k2", "v2")
    ...
    .build();


답변

이를 수행하는 직접적인 방법은 없습니다-Java에는 맵 리터럴이 없습니다 (아직 Java 8에 대해 제안 된 것 같습니다).

어떤 사람들은 이것을 좋아합니다 :

Map<String,String> test = new HashMap<String, String>(){{
       put("test","test"); put("test","test");}};

그러면 인스턴스 이니셜 라이저가 이러한 값을 넣는 HashMap의 익명 서브 클래스가 작성됩니다. (그런 식으로, 맵은 동일한 값의 두 배를 포함 할 수 없으며, 두 번째 풋은 첫 번째 값을 덮어 씁니다. 다음 예제에서는 다른 값을 사용합니다.)

일반적인 방법은 다음과 같습니다 (로컬 변수의 경우).

Map<String,String> test = new HashMap<String, String>();
test.put("test","test");
test.put("test1","test2");

귀하의 경우 test맵 인스턴스 변수는, 생성자 또는 인스턴스 초기화에서 초기화를 넣어 :

Map<String,String> test = new HashMap<String, String>();
{
    test.put("test","test");
    test.put("test1","test2");
}

귀하의 경우 test지도가 클래스 변수가 정적 초기화에서 초기화를 넣어 :

static Map<String,String> test = new HashMap<String, String>();
static {
    test.put("test","test");
    test.put("test1","test2");
}

지도를 변경하지 않으려면 초기화 후로지도를 래핑해야합니다 Collections.unmodifiableMap(...). 정적 초기화 프로그램 에서도이 작업을 수행 할 수 있습니다.

static Map<String,String> test;
{
    Map<String,String> temp = new HashMap<String, String>();
    temp.put("test","test");
    temp.put("test1","test2");
    test = Collections.unmodifiableMap(temp);
}

(지금 당신이 test최종 결승을 할 수 있는지 잘 모르겠습니다 … 시험 해보고 여기에 신고하십시오.)


답변

Map<String,String> test = new HashMap<String, String>()
{
    {
        put(key1, value1);
        put(key2, value2);
    }
};


답변

대안은 일반 Java 7 클래스 및 varargs를 사용하는 것 HashMapBuilder입니다.이 메소드를 사용하여 클래스 를 작성하십시오 .

public static HashMap<String, String> build(String... data){
    HashMap<String, String> result = new HashMap<String, String>();

    if(data.length % 2 != 0)
        throw new IllegalArgumentException("Odd number of arguments");

    String key = null;
    Integer step = -1;

    for(String value : data){
        step++;
        switch(step % 2){
        case 0:
            if(value == null)
                throw new IllegalArgumentException("Null key value");
            key = value;
            continue;
        case 1:
            result.put(key, value);
            break;
        }
    }

    return result;
}

다음과 같은 방법을 사용하십시오.

HashMap<String,String> data = HashMapBuilder.build("key1","value1","key2","value2");


답변

tl; dr

Map.of…Java 9 이상에서 메소드를 사용하십시오 .

Map< String , String > animalSounds =
    Map.of(
        "dog"  , "bark" ,   // key , value
        "cat"  , "meow" ,   // key , value
        "bird" , "chirp"    // key , value
    )
;

Map.of

Java 9는 Map.of원하는 것을 수행하기 위해 일련의 정적 메소드를 추가했습니다 . 리터럴 구문을 사용하여 불변 Map을 인스턴스화하십시오 .

맵 (항목 모음)은 변경할 수 없으므로 인스턴스화 후 항목을 추가하거나 제거 할 수 없습니다. 또한 각 항목의 키와 값은 변경할 수 없으며 변경할 수 없습니다. NULL이 허용되지 않거나 중복 키가 허용되지 않으며 맵핑의 반복 순서는 임의적 인 다른 규칙에 대해서는 Javadoc참조하십시오 .

우리가 요일에 근무할 것으로 예상되는 사람에게 요일 맵에 대한 일부 샘플 데이터를 사용하여 이러한 방법을 살펴 보겠습니다.

Person alice = new Person( "Alice" );
Person bob = new Person( "Bob" );
Person carol = new Person( "Carol" );

Map.of()

Map.of빈을 만듭니다 Map. 수정할 수 없으므로 항목을 추가 할 수 없습니다. 다음은 항목이없는 빈지도의 예입니다.

Map < DayOfWeek, Person > dailyWorkerEmpty = Map.of();

dailyWorkerEmpty.toString () : {}

Map.of( … )

Map.of( k , v , k , v , …)1 ~ 10 개의 키-값 쌍을 취하는 몇 가지 방법이 있습니다. 다음은 두 항목의 예입니다.

Map < DayOfWeek, Person > weekendWorker =
        Map.of(
            DayOfWeek.SATURDAY , alice ,     // key , value
            DayOfWeek.SUNDAY , bob           // key , value
        )
;

weekendWorker.toString () : {SUNDAY = 사람 {name = ‘Bob’}, SATURDAY = 사람 {name = ‘Alice’}}

Map.ofEntries( … )

Map.ofEntries( Map.Entry , … )Map.Entry인터페이스를 구현하는 많은 수의 객체를 가져옵니다 . 자바는 그 인터페이스, 하나 개의 가변, 다른 불변을 구현하는 두 개의 클래스를 번들 : AbstractMap.SimpleEntry, AbstractMap.SimpleImmutableEntry. 그러나 구체적인 클래스를 지정할 필요는 없습니다. Map.entry( k , v )메소드 를 호출 하고 키와 값을 전달하면 Map.Entry인터페이스를 구현하는 클래스의 객체를 다시 얻을 수 있습니다.

Map < DayOfWeek, Person > weekdayWorker = Map.ofEntries(
        Map.entry( DayOfWeek.MONDAY , alice ) ,            // Call to `Map.entry` method returns an object implementing `Map.Entry`. 
        Map.entry( DayOfWeek.TUESDAY , bob ) ,
        Map.entry( DayOfWeek.WEDNESDAY , bob ) ,
        Map.entry( DayOfWeek.THURSDAY , carol ) ,
        Map.entry( DayOfWeek.FRIDAY , carol )
);

weekdayWorker.toString () : {WEDNESDAY = 사람 {name = ‘Bob’}, 화요일 = 사람 {name = ‘Bob’}, THURSDAY = 사람 {name = ‘Carol’}, FRIDAY = 사람 {name = ‘Carol’} , MONDAY = 사람 {name = ‘Alice’}}

Map.copyOf

자바 10은 그 방법을 추가했다 Map.copyOf. 기존지도를 전달하고 해당지도의 불변 사본을 다시 가져옵니다.

노트

공지 사항지도의 반복자 순서가 생산 것을 통해이 Map.of되어 있지 보장. 항목은 임의의 순서로되어 있습니다. 설명서는 주문이 변경 될 수 있음을 경고하므로 표시된 순서에 따라 코드를 작성하지 마십시오.

이 모든 것을 참고 Map.of…방법이를 반환 Map으로 지정되지 않은 클래스 . 기본 콘크리트 클래스는 Java 버전마다 다를 수 있습니다. 이 익명 성을 통해 Java는 특정 데이터에 가장 적합한 것이 무엇이든 다양한 구현 중에서 선택할 수 있습니다. 예를 들어, 키가 enum 에서 온 경우 Java EnumMap는 표지 아래를 사용할 수 있습니다 .