सीधे HashMap (शाब्दिक तरीके से) को कैसे प्रारंभ करें?


1090

क्या जावा हाशप को इस तरह से शुरू करने का कोई तरीका है ?:

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

सही सिंटैक्स क्या होगा? मुझे इस संबंध में कुछ भी नहीं मिला है। क्या यह संभव है? मैं एक नक्शे में कुछ "अंतिम / स्थिर" मान रखने के लिए सबसे छोटा / सबसे तेज़ तरीका खोज रहा हूं जो कभी नहीं बदलता है और मानचित्र बनाते समय अग्रिम में जाना जाता है।



निकटता से संबंधित: stackoverflow.com/questions/507602/… (दोनों प्रश्न स्थैतिक, अंतिम मूल्यों के साथ एक निरंतर मानचित्र को शुरू करने के बारे में हैं।)
जोनिक



यदि आप apache.commons.collections का उपयोग करते हैं, तो आप commons.apache.org/proper/commons-collections/javadocs/…
ax का

जवाबों:


1341

सभी संस्करण

मामले में आपको केवल एक प्रविष्टि की आवश्यकता होती है: वहाँ है Collections.singletonMap("key", "value")

जावा संस्करण 9 या उच्चतर के लिए:

हां, अब यह संभव है। जावा 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")
);

उदाहरण के ऊपर testऔर दोनों test2समान होंगे, बस मानचित्र को व्यक्त करने के विभिन्न तरीकों के साथ। Map.ofविधि, नक्शे में दस तत्वों पर निर्भर के लिए परिभाषित करते हुए किया गया है Map.ofEntriesविधि ऐसी कोई सीमा नहीं होगा।

ध्यान दें कि इस मामले में परिणामी नक्शा एक अपरिवर्तनीय मानचित्र होगा। यदि आप चाहते हैं कि मानचित्र आपस में जुड़ा हो, तो आप इसे फिर से कॉपी कर सकते हैं, उदाहरण के लिएmutableMap = new HashMap<>(Map.of("a", "b"));

( JEP 269 और जावदोक भी देखें )

जावा संस्करण 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;
}

3
यदि आप किसी फ़ंक्शन में तत्वों को आरंभ करना चाहते हैं तो यह काम नहीं करेगा ...
माइकल

9
@ मिचेल: हाँ, यदि आप एक फ़ंक्शन का उपयोग करना चाहते हैं, तो आप एक फ़ंक्शन का उपयोग नहीं कर सकते। लेकिन आप क्यों करना चाहते हैं?
yankee

6
और उन मामलों के लिए जब आपको एक प्रविष्टि के साथ एक मानचित्र की आवश्यकता होती है Collections.singletonMap():)
skwisgaar

3
अब जब स्थिर जावा 9 जारी कर दिया गया है, तो मुझे जवादोक के लिए यह लिंक पसंद है । और +1 क्योंकि एक कम निर्भरता!
फ्रैंकलिन यू

3
जावा 9 कहां entryप्रलेखित है?
nobar

1029

ये एक तरीका है।

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

हालांकि, आपको सावधान रहना चाहिए और यह सुनिश्चित करना चाहिए कि आप उपरोक्त कोड को समझते हैं (यह एक नया वर्ग बनाता है जो हैशपॉप से ​​विरासत में मिला है)। इसलिए, आपको यहां और अधिक पढ़ना चाहिए: http://www.c2.com/cgi/wiki?DoubleBraceInitialization , या बस अमरूद का उपयोग करें:

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

72
यह काम करता है लेकिन यह बदसूरत है और इसके अदृश्य दुष्प्रभाव हैं जो उपयोगकर्ता को इसे करने से पहले समझना चाहिए - उदाहरण के लिए, मौके पर एक संपूर्ण अनाम वर्ग उत्पन्न करना।
जिपर

96
हां, इस तरह मैंने सावधान रहने के बारे में लिखा और विवरण के लिए एक लिंक दिया।
gregory561

6
बढ़िया लिंक। GreencoddsTenthRuleOfProgramming के उस लिंक में संदर्भ पढ़ने लायक है।
माइकललोक

19
क्या आप "ImmutableMap.builder.put (" k1 "," v1 ") के रूप में जोड़ सकते हैं। डाल (" k2 "," v2 ")। निर्माण ()" के रूप में "की" अधिकतम "5 जोड़े तक सीमित है?
कोमराधोमोर


341

यदि आप तृतीय पक्ष की अनुमति देते हैं, तो आप शाब्दिक जैसे संक्षिप्तता प्राप्त करने के लिए अमरूद के इम्यूटेबल मैप का उपयोग कर सकते हैं :

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



26
इसके अलावा, अमरुद में इम्यूटेबल मैप.बिल्डर.पुट ("k1", "v1") है। पुट ("k2", "v2")। build ();
Xetius

16
ImmutableMap, HashMap के समान नहीं है, क्योंकि यह अशक्त मूल्यों पर विफल होगा, जबकि मानचित्र HashMap नहीं होगा।
ग्यूथेन

2
बस दूसरों की मदद करने के लिए जो इस मुद्दे का सामना कर सकते हैं। आपको इसे टाइप करने के लिए बिल्डर को मैप करना होगा <string> String>, इस तरह: Map <String, String> test = ImmutableMap। <String, String> builder ()। Put ("k1", "v1")। put ("k2", "v2")। build ();
थिआगो

यह बहुत बढ़िया है जेन्स!
गौरव

105

ऐसा करने का कोई सीधा तरीका नहीं है - जावा में कोई मैप शाब्दिक नहीं है (फिर भी - मुझे लगता है कि वे जावा 8 के लिए प्रस्तावित थे)।

कुछ लोग इसे पसंद करते हैं:

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

यह हैशपैम का एक अनाम उपवर्ग बनाता है, जिसका उदाहरण इनिशियलाइज़र इन मूल्यों को रखता है। (वैसे, एक मानचित्र में दो बार समान मूल्य नहीं हो सकता है, आपका दूसरा पुट पहले वाले को अधिलेखित कर देगा। मैं अगले उदाहरणों के लिए विभिन्न मूल्यों का उपयोग करूंगा।)

सामान्य तरीका यह होगा (स्थानीय चर के लिए):

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फाइनल कर सकते हैं ... इसे आज़माएँ और यहाँ रिपोर्ट करें।)


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

सरल और सटीक। मुझे लगता है कि एक विस्तारित टिप्पणी अनुभाग के साथ यह सबसे अच्छा जवाब होगा।
ओलाला

15
स्मृति निहितार्थ हैं, हालांकि ध्यान दिया जाना चाहिए। blog.jooq.org/2014/12/08/…
Amalgovinus

1
@ अम्मलगोविस मूल रूप से, एक नया उपवर्ग बनाकर, आप HashMapइस वर्ग में से प्रकार तर्क को हार्ड-कोडिंग कर रहे हैं । यह केवल तभी काम कर सकता है जब आप वास्तव में उन्हें प्रदान करें। (एक नए (खाली) हैशपॉप के साथ, प्रकार के तर्क प्रासंगिक नहीं हैं।)
पाओलो एर्बमैन

1
मुझे इसकी स्वच्छता पसंद है, लेकिन यह अनावश्यक अनाम वर्ग बनाता है और यहाँ वर्णित समस्याएं हैं: c2.com/cgi/wiki?DoubleBraceInitialization
udachny

1
@hello_its_me: क्योंकि इसका जैसा ही stackoverflow.com/a/6802512/1386911 उत्तर है, बस स्वरूपण अलग है। और इस मामले में इस विस्तारित स्वरूपण का पठनीयता के लिए कॉम्पैक्ट प्रारूप के शीर्ष पर कोई अतिरिक्त मूल्य नहीं है।
डैनियल हारी

44

एक विकल्प, सादा जावा 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");

मैंने
आपसे

1
Apache Utils के साथ एक अन्य समाधान जिसका उल्लेख कभी नहीं किया गया है, लेकिन जावा संस्करण से पहले का उपयोग करके पठनीय है: MapUtils.putAll (नया HashMap <स्ट्रिंग, स्ट्रिंग> (), नई वस्तु [] {"मेरी कुंजी", "मेरा मूल्य, ...
रोलिंटोकोर

3

tl; डॉ

Map.of…जावा 9 और बाद के तरीकों का उपयोग करें ।

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

Map.of

जावा 9 ने Map.ofस्थिर तरीकों की एक श्रृंखला को जोड़ा जो आप चाहते हैं: शाब्दिक सिंटैक्स का उपयोग करके एक अपरिवर्तनीय को त्वरित करेंMap

नक्शा (प्रविष्टियों का एक संग्रह) अपरिवर्तनीय है, इसलिए आप इंस्टेंटिंग के बाद प्रविष्टियों को जोड़ या हटा नहीं सकते हैं। इसके अलावा, प्रत्येक प्रविष्टि की कुंजी और मूल्य अपरिवर्तनीय है, इसे बदला नहीं जा सकता है। अन्य नियमों के लिए Javadoc देखें , जैसे कोई NULLs अनुमति नहीं, कोई डुप्लिकेट कुंजियाँ अनुमत नहीं हैं, और मैपिंग का पुनरावृत्ति क्रम मनमाना है।

आइए इन तरीकों को देखें, दिन-प्रति-सप्ताह के नक्शे के लिए कुछ नमूना डेटा का उपयोग करके उस व्यक्ति से जो हमें उम्मीद है कि उस दिन काम करेगा।

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

सप्ताहांतकर्त्ता.तोड़ (): {SUNDAY = व्यक्ति {नाम = 'बॉब'}, SATURDAY = व्यक्ति {नाम = 'ऐलिस'}}

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

सप्ताह के दिन काम करने वाला। , मोनडे = व्यक्ति {नाम = 'ऐलिस'}}

Map.copyOf

जावा 10 ने विधि जोड़ी Map.copyOf। एक मौजूदा मानचित्र पास करें, उस मानचित्र की एक अपरिवर्तनीय प्रतिलिपि वापस प्राप्त करें।

टिप्पणियाँ

सूचना है कि नक्शे के इटरेटर आदेश उत्पादन के माध्यम से Map.ofकर रहे हैं नहीं की गारंटी। प्रविष्टियों में एक मनमाना क्रम है। देखे गए आदेश के आधार पर कोड न लिखें, क्योंकि प्रलेखन चेतावनी देता है कि आदेश परिवर्तन के अधीन है।

ध्यान दें कि इन सभी Map.of…तरीकों एक वापसी Mapकी एक अनिर्दिष्ट वर्ग । अंतर्निहित ठोस वर्ग जावा के एक संस्करण से दूसरे में भी भिन्न हो सकता है। यह गुमनामी जावा को विभिन्न कार्यान्वयनों में से चुनने में सक्षम बनाती है, जो भी आपके विशेष डेटा के अनुकूल है। उदाहरण के लिए, यदि आपकी चाबियाँ किसी एनम से आती हैं, तो जावा EnumMapकवर के नीचे उपयोग कर सकता है ।


1

आप संभवतः अपना खुद का बना सकते हैं Map.of(जो केवल जावा 9 और उच्चतर में उपलब्ध है) विधि 2 आसान तरीकों से आसानी से

इसे मापदंडों की एक निर्धारित मात्रा के साथ बनाएं

उदाहरण

public <K,V> Map<K,V> mapOf(K k1, V v1, K k2, V v2 /* perhaps more parameters */) {
    return new HashMap<K, V>() {{
      put(k1, v1);
      put(k2,  v2);
      // etc...
    }};
}

एक सूची का उपयोग करके इसे बनाएं

मापदंडों के एक निश्चित सेट के लिए बहुत सारे तरीके बनाने के बजाय, आप इसे एक सूची का उपयोग करके भी बना सकते हैं।

उदाहरण

public <K, V> Map<K, V> mapOf(List<K> keys, List<V> values) {
   if(keys.size() != values.size()) {
        throw new IndexOutOfBoundsException("amount of keys and values is not equal");
    }

    return new HashMap<K, V>() {{
        IntStream.range(0, keys.size()).forEach(index -> put(keys.get(index), values.get(index)));
    }};
}

नोट यह सब कुछ के लिए उपयोग करने के लिए अनुशंसित नहीं है क्योंकि यह हर बार जब आप इसे उपयोग करते हैं तो एक अनाम वर्ग बनाता है।


1

जाव A

सादे जावा 8 में आपको Streams/Collectorsनौकरी करने के लिए उपयोग करने की संभावना है ।

Map<String, String> myMap = Stream.of(
         new SimpleEntry<>("key1", "value1"),
         new SimpleEntry<>("key2", "value2"),
         new SimpleEntry<>("key3", "value3"))
        .collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));

इससे बेनामी वर्ग नहीं बनाने का फायदा है।

ध्यान दें कि आयात कर रहे हैं:

import static java.util.stream.Collectors.toMap;
import java.util.AbstractMap.SimpleEntry;

बेशक, जैसा कि अन्य उत्तरों में उल्लेख किया गया है, जावा 9 में आपके पास समान करने के सरल तरीके हैं।


0

दुर्भाग्य से, यदि प्रकार की कुंजियाँ और मान समान नहीं हैं, तो वैरिएग का उपयोग करना बहुत उचित नहीं है क्योंकि आपको Object...पूरी तरह से सुरक्षा का उपयोग करना और खोना होगा। यदि आप हमेशा एक उदाहरण के लिए बनाना चाहते हैं Map<String, String>, toMap(String... args)हालांकि यह संभव है, लेकिन बहुत सुंदर नहीं होगा क्योंकि यह कुंजी और मूल्यों को मिलाना आसान होगा, और विषम संख्या में तर्क अमान्य होंगे।

आप HashMap की एक उप-श्रेणी बना सकते हैं जिसमें एक श्रृंखला योग्य विधि होती है जैसे

public class ChainableMap<K, V> extends HashMap<K, V> {
  public ChainableMap<K, V> set(K k, V v) {
    put(k, v);
    return this;
  }
}

और इसका उपयोग करें new ChainableMap<String, Object>().set("a", 1).set("b", "foo")

आम बिल्डर पैटर्न का उपयोग करने के लिए एक और तरीका है:

public class MapBuilder<K, V> {
  private Map<K, V> mMap = new HashMap<>();

  public MapBuilder<K, V> put(K k, V v) {
    mMap.put(k, v);
    return this;
  }

  public Map<K, V> build() {
    return mMap;
  }
}

और इसका उपयोग करें new MapBuilder<String, Object>().put("a", 1).put("b", "foo").build();

हालाँकि, मैंने अभी जो समाधान इस्तेमाल किया है, वह वैरग और Pairवर्ग का उपयोग करता है :

public class Maps {
  public static <K, V> Map<K, V> of(Pair<K, V>... pairs) {
    Map<K, V> = new HashMap<>();

    for (Pair<K, V> pair : pairs) {
      map.put(pair.first, pair.second);
    }

    return map;
  }
}

Map<String, Object> map = Maps.of(Pair.create("a", 1), Pair.create("b", "foo");

के शब्दाडंबर Pair.create()मुझे परेशान एक सा है, लेकिन यह काम करता है काफी ठीक। यदि आपको स्थिर आयात से ऐतराज नहीं है, तो आप निश्चित रूप से एक सहायक बना सकते हैं:

public <K, V> Pair<K, V> p(K k, V v) {
  return Pair.create(k, v);
}

Map<String, Object> map = Maps.of(p("a", 1), p("b", "foo");

(इसके बजाय Pairएक का उपयोग करने की कल्पना कर सकते हैं Map.Entry, लेकिन चूंकि यह एक इंटरफ़ेस है, इसके लिए एक कार्यान्वयन वर्ग और / या सहायक कारखाने विधि की आवश्यकता है। यह अपरिवर्तनीय भी नहीं है, और इसमें अन्य तर्क शामिल हैं जो इस कार्य के लिए उपयोगी नहीं हैं।)


0

आप जावा 8 में धाराओं का उपयोग कर सकते हैं (यह सेट का निर्गमन है):

@Test
public void whenInitializeUnmodifiableSetWithDoubleBrace_containsElements() {
    Set<String> countries = Stream.of("India", "USSR", "USA")
      .collect(collectingAndThen(toSet(), Collections::unmodifiableSet));

    assertTrue(countries.contains("India"));
}

Ref: https://www.baeldung.com/java-double-brace-initialization


0

यदि आपको केवल एक कुंजी-मूल्य जोड़ी रखने की आवश्यकता है, तो आप Collections.singletonMap (कुंजी, मान) का उपयोग कर सकते हैं;


1
स्वरूपण कोड पोस्ट को अधिक पठनीय बनाता है
रेनैटो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.