วิธีที่ดีที่สุดในการสร้างแผนที่ว่างใน Java


117

ฉันต้องการสร้างแผนที่ว่างเปล่า

if (fileParameters == null)
    fileParameters = (HashMap<String, String>) Collections.EMPTY_MAP;

ปัญหาคือโค้ดด้านบนสร้างคำเตือนนี้: Type safety: Unchecked cast from Map to HashMap

วิธีที่ดีที่สุดในการสร้างแผนที่ว่างนี้คืออะไร?


ประเภทที่คุณประกาศสำหรับ fileParameters คืออะไร?
jjnguy

คุณอาจจะได้รับ ClassCastException ด้วย
Tom Hawtin - แท็กไลน์

1
fileParameters ควรเป็นแผนที่ไม่ใช่ HashMap
Steve Kuo

คำตอบ:


242

1)หากแผนที่ไม่เปลี่ยนรูป:

Collections.emptyMap()

// or, in some cases:
Collections.<String, String>emptyMap()

คุณจะต้องใช้อย่างหลังในบางครั้งเมื่อคอมไพเลอร์ไม่สามารถระบุได้โดยอัตโนมัติว่าต้องการแผนที่ประเภทใด (เรียกว่าการอนุมานประเภท ) ตัวอย่างเช่นพิจารณาวิธีการที่ประกาศเช่นนี้:

public void foobar(Map<String, String> map){ ... }

เมื่อส่งแผนที่ว่างไปยังแผนที่โดยตรงคุณจะต้องมีความชัดเจนเกี่ยวกับประเภท:

foobar(Collections.emptyMap());                 // doesn't compile
foobar(Collections.<String, String>emptyMap()); // works fine

2)หากคุณจำเป็นต้องสามารถแก้ไขแผนที่ได้ตัวอย่างเช่น:

new HashMap<String, String>()

(ตามที่tehblanx ชี้ให้เห็น )


ภาคผนวก : หากโครงการของคุณใช้Guavaคุณมีทางเลือกต่อไปนี้:

1)แผนที่ไม่เปลี่ยนรูป:

ImmutableMap.of()
// or:
ImmutableMap.<String, String>of()

จริงอยู่ที่นี่ไม่มีประโยชน์อะไรมากมายเมื่อเทียบกับ Collections.emptyMap()จริงอยู่ที่ไม่ได้รับประโยชน์ใหญ่ที่นี่เมื่อเทียบกับจาก Javadoc :

แผนที่นี้ทำงานและดำเนินการโดยเปรียบเทียบกับCollections.emptyMap()และเป็นที่นิยมมากที่สุดสำหรับความสอดคล้องและการบำรุงรักษาของโค้ดของคุณ

2)แผนที่ที่คุณสามารถแก้ไขได้:

Maps.newHashMap()
// or:
Maps.<String, String>newHashMap()

Mapsมีวิธีการโรงงานที่คล้ายกันสำหรับการสร้างอินสแตนซ์ของแผนที่ประเภทอื่น ๆ เช่นTreeMapหรือLinkedHashMapหรือ


อัปเดต (2018) : บนJava 9หรือใหม่กว่ารหัสที่สั้นที่สุดสำหรับการสร้างแผนที่ว่างที่ไม่เปลี่ยนรูปคือ:

Map.of()

... ใช้ใหม่วิธีการโรงงานความสะดวกสบายจากJEP 269 😎


ในกรณีส่วนใหญ่การอนุมานประเภทใช้ได้ผล (เช่น. map = Collections.emptyMap () ทำงาน)
Sébastien RoccaSerra

ใช่จริง ฉันแก้ไขคำตอบให้ครอบคลุมมากขึ้นเล็กน้อย
Jonik

16

ปัญหาคือแผนที่นี้สามารถใช้ได้กับวัตถุแผนที่เท่านั้นที่ไม่ใช่ HashMap
JorgeO

7
คุณควร (โดยทั่วไป) หลีกเลี่ยงการประกาศออบเจ็กต์เฉพาะประเภทและใช้อินเทอร์เฟซ (หรือพาเรนต์นามธรรม) แทน พยายามหลีกเลี่ยง "HashMap <String, String> foo;" และใช้ "Map <String, String> foo;" แทน
TofuBeer


10

หากคุณต้องการอินสแตนซ์ของ HashMap วิธีที่ดีที่สุดคือ:

fileParameters = new HashMap<String,String>();

เนื่องจากแผนที่เป็นอินเทอร์เฟซคุณจึงต้องเลือกคลาสที่สร้างอินสแตนซ์หากคุณต้องการสร้างอินสแตนซ์เปล่า HashMap ดูเหมือนจะดีพอ ๆ กับที่อื่น ๆ - ดังนั้นใช้แค่นั้น



2

เนื่องจากในหลาย ๆ กรณีแผนที่ว่างถูกใช้สำหรับการออกแบบที่ไม่ปลอดภัยคุณสามารถใช้nullToEmptyวิธียูทิลิตี้:

class MapUtils {

  static <K,V> Map<K,V> nullToEmpty(Map<K,V> map) {
    if (map != null) {
      return map;
    } else {
       return Collections.<K,V>emptyMap(); // or guava ImmutableMap.of()
    }
  }

}  

ในทำนองเดียวกันสำหรับชุด:

class SetUtils {

  static <T> Set<T> nullToEmpty(Set<T> set) {
    if (set != null) {
      return set;
    } else {
      return Collections.<T>emptySet();
    }
  }

}

และรายการ:

class ListUtils {

  static <T> List<T> nullToEmpty(List<T> list) {
    if (list != null) {
      return list;
    } else {
      return Collections.<T>emptyList();
    }
  }

}

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