เพิ่มหลายรายการใน HashMap พร้อมกันในหนึ่งคำสั่ง


138

ฉันต้องการเริ่มต้น HashMap คงที่และต้องการทำในคำสั่งบรรทัดเดียว หลีกเลี่ยง sth เช่นนี้

  hashMap.put("One", new Integer(1)); // adding value into HashMap
  hashMap.put("Two", new Integer(2));      
  hashMap.put("Three", new Integer(3));

คล้ายกับในวัตถุประสงค์ C:

[NSDictionary dictionaryWithObjectsAndKeys:
@"w",[NSNumber numberWithInt:1],
@"K",[NSNumber numberWithInt:2],
@"e",[NSNumber numberWithInt:4],
@"z",[NSNumber numberWithInt:5],
@"l",[NSNumber numberWithInt:6],
nil] 

ฉันไม่พบตัวอย่างใด ๆ ที่แสดงวิธีการทำเช่นนี้เมื่อดูจำนวนมาก

คำตอบ:


259

คุณสามารถทำได้:

Map<String, Integer> hashMap = new HashMap<String, Integer>()
{{
     put("One", 1);
     put("Two", 2);
     put("Three", 3);
}};

11
@ user387184 ใช่พวกเขาเรียกมันว่า "double brace initializer" ดูหัวข้อนี้: stackoverflow.com/questions/924285/…
Thai.Fouad

2
ฉันเพิ่งใส่มันในรหัสของฉันและฉันได้รับคำเตือน / ข้อความนี้ในบรรทัด: "คลาสที่ทำให้เป็นอนุกรมไม่ได้ประกาศฟิลด์ serialVersionUID สุดท้ายที่เป็นแบบสแตติก" ฉันจะเพิกเฉยได้หรือไม่ สิ่งนี้หมายความว่า? ขอบคุณ
user387184

31
คุณไม่ควรใช้วิธีนี้ มันจะสร้างระดับใหม่สำหรับทุกครั้งที่คุณใช้มันซึ่งมีมากประสิทธิภาพเลวร้ายยิ่งกว่าเพียงสมถะสร้างแผนที่ ดูstackoverflow.com/questions/924285/…
Timo Türschmann

7
เหตุผลที่ฉันลงคะแนนนี้เพราะไม่ได้อธิบายว่านี่เป็นการสร้างคลาสใหม่ทุกครั้งที่คุณใช้ ฉันคิดว่าผู้คนควรตระหนักถึงข้อเสียของการทำเช่นนี้
idungotnosn

6
@ TimoTürschmannดูเหมือนว่าถ้าฉันต้องการการเริ่มต้นแผนที่แบบคงที่เช่นนี้มันจะคงที่และกำจัดทุกครั้งที่คุณใช้การลงโทษประสิทธิภาพ - คุณต้องได้รับโทษครั้งเดียว ฉันไม่เห็นเวลาอื่นที่ต้องการให้การเริ่มต้นประเภทนี้โดยไม่มีตัวแปรเป็นแบบคงที่ (เช่นทุกคนจะใช้สิ่งนี้ในการวนซ้ำหรือไม่) ฉันอาจจะผิด แต่โปรแกรมเมอร์ก็สร้างสรรค์
Chris Cirefice

65

คุณสามารถใช้ ImmutableMap ของ Google Guava ใช้งานได้ตราบใดที่คุณไม่สนใจที่จะแก้ไขแผนที่ในภายหลัง (คุณไม่สามารถเรียก .put () บนแผนที่หลังจากสร้างมันขึ้นมาโดยใช้วิธีนี้):

import com.google.common.collect.ImmutableMap;

// For up to five entries, use .of()
Map<String, Integer> littleMap = ImmutableMap.of(
    "One", Integer.valueOf(1),
    "Two", Integer.valueOf(2),
    "Three", Integer.valueOf(3)
);

// For more than five entries, use .builder()
Map<String, Integer> bigMap = ImmutableMap.<String, Integer>builder()
    .put("One", Integer.valueOf(1))
    .put("Two", Integer.valueOf(2))
    .put("Three", Integer.valueOf(3))
    .put("Four", Integer.valueOf(4))
    .put("Five", Integer.valueOf(5))
    .put("Six", Integer.valueOf(6))
    .build();

ดูเพิ่มเติมที่: http://docs.guava-luments.googlecode.com/git/javadoc/com/google/common/collect/ImmutableMap.html

คำถามที่เกี่ยวข้องบ้าง: ImmutableMap.of () วิธีแก้ปัญหาสำหรับ HashMap ในแผนที่?


ฝรั่งมีขนาดใหญ่ฉันจะไม่ใช้มันกับแอพ Android ของฉันเว้นแต่จะจำเป็นจริงๆ
ericn

4
ระวังที่ImmutableMapไม่ยอมรับnullคีย์หรือค่า
Vadzim

@ericn ProGuardให้คุณยกเว้นส่วนใด ๆ ของห้องสมุดที่คุณไม่ได้ใช้
dimo414

55

ตั้งแต่ Java 9 เป็นไปได้ที่จะใช้Map.of(...)เช่น:

Map<String, Integer> immutableMap = Map.of("One", 1, 
                                           "Two", 2, 
                                           "Three", 3);

แผนที่นี้ไม่เปลี่ยนรูป หากคุณต้องการให้แผนที่ไม่แน่นอนคุณต้องเพิ่ม:

Map<String, Integer> hashMap = new HashMap<>(immutableMap);

หากคุณไม่สามารถใช้ Java 9 ได้คุณกำลังติดกับวิธีเขียนตัวช่วยที่คล้ายกันด้วยตนเองหรือใช้ไลบรารีบุคคลที่สาม (เช่นGuava ) เพื่อเพิ่มฟังก์ชันการทำงานนั้นให้คุณ


หลังจากเพิ่ม 10 รายการมันจะพ่นข้อผิดพลาดแปลก "ไม่สามารถแก้ไขวิธีการ" ข้อผิดพลาดนี้มีวิธีนี้หรือไม่?
vikramvi

2
@vikramvi ใช่ถ้าคุณดูเอกสาร Map.ofจะทำได้มากถึง 10 รายการเพราะค่อนข้างลำบาก
jolivier

8

Java ไม่มีตัวอักษรแผนที่ดังนั้นจึงไม่มีวิธีที่ดีที่จะทำสิ่งที่คุณขอ

หากคุณต้องการไวยากรณ์ประเภทนี้ให้พิจารณา Groovy บางตัวซึ่งใช้งานร่วมกับ Java ได้และให้คุณทำสิ่งต่อไปนี้

def map = [name:"Gromit", likes:"cheese", id:1234]

8

แผนที่มีวิธีการเพิ่มจากโรงงานใน Java 9 สำหรับรายการสูงสุด 10 รายการแผนที่มีตัวสร้างมากเกินไปที่ใช้คู่คีย์และค่า ตัวอย่างเช่นเราสามารถสร้างแผนที่ของเมืองต่าง ๆ และประชากรของพวกเขา (อ้างอิงจาก google ในเดือนตุลาคม 2559) ดังนี้:

Map<String, Integer> cities = Map.of("Brussels", 1_139000, "Cardiff", 341_000);

กรณี var-args สำหรับ Map นั้นยากขึ้นเล็กน้อยคุณต้องมีทั้งคีย์และค่า แต่ใน Java วิธีการไม่สามารถมีพารามิเตอร์ var-args สองตัว ดังนั้นกรณีทั่วไปได้รับการจัดการโดยใช้วิธีการ var-args ของMap.Entry<K, V>วัตถุและเพิ่มentry()วิธีการคงที่ที่สร้างพวกเขา ตัวอย่างเช่น:

Map<String, Integer> cities = Map.ofEntries(
    entry("Brussels", 1139000), 
    entry("Cardiff", 341000)
);

วิธีการรวบรวมโรงงานใน Java 9


ยอดเยี่ยมถ้าคุณสามารถใช้ Java 9+ ด้วยวิธีการจากโรงงานเหล่านี้ส่งคืนแผนที่ที่ไม่เปลี่ยนรูป
Sourabh

6

นี่คือคลาสที่เรียบง่ายที่จะบรรลุสิ่งที่คุณต้องการ

import java.util.HashMap;

public class QuickHash extends HashMap<String,String> {
    public QuickHash(String...KeyValuePairs) {
        super(KeyValuePairs.length/2);
        for(int i=0;i<KeyValuePairs.length;i+=2)
            put(KeyValuePairs[i], KeyValuePairs[i+1]);
    }
}

และจากนั้นจะใช้มัน

Map<String, String> Foo=QuickHash(
    "a", "1",
    "b", "2"
);

อัตราผลตอบแทนนี้ {a:1, b:2}


4
    boolean x;
    for (x = false, 
        map.put("One", new Integer(1)), 
        map.put("Two", new Integer(2)),      
        map.put("Three", new Integer(3)); x;);

ละเว้นการประกาศของx(ซึ่งเป็นสิ่งจำเป็นเพื่อหลีกเลี่ยงการวินิจฉัย "คำสั่งที่ไม่สามารถเข้าถึงได้") โดยทางเทคนิคแล้วมันเป็นเพียงคำสั่งเดียว


14
นี่เป็นแฮ็คที่น่าขยะแขยง
คาห์บันได

1
@MicahStairs - แต่มันเป็นเพียงคำสั่งเดียว
Hot Licks

2
จริง แต่นี่คือรหัสที่ฉันไม่เคยหวังว่าจะสะดุดในการผลิต
คาห์บันได

@ MicahStairs - ฉันเห็นแล้วแย่ลง
เลียร้อน

1
ฉันได้ค้นหาสิ่งนี้วันนี้รหัสนี้ทำงานอย่างไร ฉันได้เพิ่มลงในรหัสสำหรับการทดสอบ แต่ฉันไม่สามารถหาวิธีการทำงานภายใน ... :)
GOXR3PLUS

1

คุณสามารถเพิ่มฟังก์ชั่นยูทิลิตี้นี้ให้กับคลาสยูทิลิตี้:

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

    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 = YourClass.mapOf(1, "value1", 2, "value2");
Map<String, String> map2 = YourClass.mapOf("key1", "value1", "key2", "value2");

หมายเหตุ: ใน Java 9คุณสามารถใช้Map.of


-1

วิธีการอื่นอาจจะเขียนฟังก์ชั่นพิเศษเพื่อดึงค่าองค์ประกอบทั้งหมดจากหนึ่งสตริงโดยการแสดงออกปกติ:

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Example {
    public static void main (String[] args){
        HashMap<String,Integer> hashMapStringInteger = createHashMapStringIntegerInOneStat("'one' => '1', 'two' => '2' , 'three'=>'3'  ");

        System.out.println(hashMapStringInteger); // {one=1, two=2, three=3}
    }

    private static HashMap<String, Integer> createHashMapStringIntegerInOneStat(String str) {
        HashMap<String, Integer> returnVar = new HashMap<String, Integer>();

        String currentStr = str;
        Pattern pattern1 = Pattern.compile("^\\s*'([^']*)'\\s*=\\s*>\\s*'([^']*)'\\s*,?\\s*(.*)$");

        // Parse all elements in the given string.
        boolean thereIsMore = true;
        while (thereIsMore){
            Matcher matcher = pattern1.matcher(currentStr);
            if (matcher.find()) {
                returnVar.put(matcher.group(1),Integer.valueOf(matcher.group(2)));
                currentStr = matcher.group(3);
            }
            else{
                thereIsMore = false;
            }
        }

        // Validate that all elements in the given string were parsed properly
        if (currentStr.length() > 0){
            System.out.println("WARNING: Problematic string format. given String: " + str);
        }

        return returnVar;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.