การเพิ่มคีย์หรือค่า null ให้กับ HashMap ใน Java คืออะไร?


91

HashMap อนุญาตให้ใช้คีย์ null หนึ่งคีย์และค่า null จำนวนเท่าใดก็ได้ การใช้งานคืออะไร?


11
"บางทีปัญหาไม่ใช่ว่าไม่มีอะไรรบกวนเรา แต่เรากำลังรบกวนมัน"
bmargulies

3
ใน Guava คอลเลคชันของ Google หลายคลาสไม่อนุญาตให้มีค่าว่างและเหตุผลเบื้องหลังก็คือ 95% ของกรณีไม่จำเป็นต้องมีค่าว่างและสามารถแสดงถึงข้อบกพร่องซึ่งอาจหาได้ยาก
stivlo

สิ่งที่แปลกคือConcurrentHashMapไม่รองรับคีย์ว่างในขณะที่HashMapทำ
codepleb

2
HashMap เท่านั้นที่อนุญาตให้ null :)
subhashis

คำตอบ:


126

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

Map<A, B> foo;
A search;
B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);

HashMapจัดการคีย์ null เป็นพิเศษ (เนื่องจากไม่สามารถเรียก.hashCode()ใช้วัตถุว่างได้) แต่ค่า null ไม่ได้มีอะไรพิเศษมันถูกเก็บไว้ในแผนที่เหมือนอย่างอื่น


4
ดังนั้นถ้า .hashCode () เป็นไปไม่ได้บน null ใครเป็นคนตัดสินใจว่าจะป้อนคีย์ null ในการขนส่ง?
Pacerier

26
@Pacerier มีวิธีพิเศษในHashMap( putForNullKey) ที่จัดการกับมัน เก็บไว้ในตาราง 0
Michael Mrozek

1
@MichaelMrozek บรรทัดสุดท้ายของคุณB val = foo.containsKey(search) ? foo.get(search) : foo.get(null);ฉันคิดว่าเราสามารถเรียกเมธอดในคีย์การค้นหาซึ่งจะได้ผลลัพธ์เหมือนกัน B val = foo.get(search);คุณช่วยแก้ไขฉันได้ไหมถ้าฉันทำอะไรผิดพลาด
dheerajraaj

6
@ dheeraj92 รหัสของคุณจะตั้งค่าvalเป็นnullถ้าไม่มีคีย์ ของฉันตั้งค่าเป็นnullแผนที่ใดก็ได้ในแผนที่ นั่นคือประเด็นฉันเก็บค่าเริ่มต้นที่ไม่ใช่ค่าว่างไว้ที่nullคีย์ในแผนที่และใช้หากไม่มีคีย์จริง
Michael Mrozek

28

ตัวอย่างหนึ่งสำหรับการสร้างแบบจำลองต้นไม้ หากคุณใช้ HashMap เพื่อแสดงโครงสร้างแบบทรีโดยที่คีย์คือพาเรนต์และค่าคือรายชื่อเด็กค่าของnullคีย์จะเป็นโหนดรูท


6

ตัวอย่างหนึ่งของการใช้งานสำหรับnull ค่าคือเมื่อใช้HashMapเป็นแคชสำหรับผลการดำเนินงานที่มีราคาแพง (เช่นการเรียกร้องให้บริการเว็บภายนอก) nullซึ่งอาจจะกลับมา

การใส่nullค่าในแผนที่จะช่วยให้คุณสามารถแยกความแตกต่างระหว่างกรณีที่การดำเนินการไม่ได้ถูกดำเนินการสำหรับคีย์ที่กำหนด ( cache.containsKey(someKey)ส่งคืนfalse) และตำแหน่งที่ดำเนินการแล้ว แต่ส่งคืนnullค่า ( cache.containsKey(someKey)ส่งคืนtrue, cache.get(someKey)ส่งคืนnull)

หากไม่มีnullค่าคุณจะต้องใส่ค่าพิเศษบางอย่างในแคชเพื่อระบุการnullตอบสนองหรือไม่ก็แคชการตอบสนองนั้นเลยและดำเนินการทุกครั้ง


3

คำตอบจนถึงตอนนี้จะพิจารณาเพียงคุณค่าของการมีnullกุญแจเท่านั้น แต่คำถามก็ถามถึงany number of null valuesเช่นกัน

ประโยชน์ของการจัดเก็บค่าnullกับคีย์ใน HashMap นั้นเหมือนกับในฐานข้อมูล ฯลฯ - คุณสามารถบันทึกความแตกต่างระหว่างการมีค่าที่ว่างเปล่า (เช่นสตริง "") และไม่มีค่าเลย (null) .


2

ต่อไปนี้เป็นตัวอย่างกรณีที่มีการกำหนดnullไว้เพียงอย่างเดียวของฉันซึ่งกุญแจจะมีประโยชน์:

public class Timer {
    private static final Logger LOG = Logger.getLogger(Timer.class);
    private static final Map<String, Long> START_TIMES = new HashMap<String, Long>();

    public static synchronized void start() {
        long now = System.currentTimeMillis();
        if (START_TIMES.containsKey(null)) {
            LOG.warn("Anonymous timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(null).longValue()) +"ms"); 
        }
        START_TIMES.put(null, now);
    }

    public static synchronized long stop() {
        if (! START_TIMES.containsKey(null)) {
            return 0;
        }

        return printTimer("Anonymous", START_TIMES.remove(null), System.currentTimeMillis());
    }

    public static synchronized void start(String name) {
        long now = System.currentTimeMillis();
        if (START_TIMES.containsKey(name)) {
            LOG.warn(name + " timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(name).longValue()) +"ms"); 
        }
        START_TIMES.put(name, now);
    }

    public static synchronized long stop(String name) {
        if (! START_TIMES.containsKey(name)) {
            return 0;
        }

        return printTimer(name, START_TIMES.remove(name), System.currentTimeMillis());
    }

    private static long printTimer(String name, long start, long end) {
        LOG.info(name + " timer ran for " + (end - start) + "ms");
        return end - start;
    }
}

หากคุณกำลังพยายามหยุดตัวจับเวลาที่ไม่มีอยู่หรือตัวจับเวลาที่หยุดไปแล้วนั่นน่าจะเป็นข้อผิดพลาดไม่ใช่ละเว้น
คดีของ Fund Monica

@QPaysTaxes - ขึ้นอยู่กับเจตนาของคุณ หากคุณต้องการยูทิลิตี้น้ำหนักเบาที่สามารถใช้งานได้ง่ายโดยทั่วไปคุณไม่ต้องการthrow Exceptionอยู่ใกล้ ๆ นอกจากนี้การพยายามหยุดตัวจับเวลาที่ไม่มีอยู่จริงหรือหยุดไปแล้วเป็นสิ่งที่ผู้โทรสามารถกู้คืนได้โดยทั่วไป
aroth

1

อีกตัวอย่างหนึ่ง: ฉันใช้เพื่อจัดกลุ่มข้อมูลตามวันที่ แต่บางข้อมูลไม่มีวันที่ ฉันสามารถจัดกลุ่มโดยใช้ส่วนหัว "NoDate"


0

คีย์ว่างยังมีประโยชน์เมื่อแผนที่เก็บข้อมูลสำหรับการเลือก UI โดยที่คีย์แผนที่แสดงถึงฟิลด์บีน

ตัวอย่างเช่นค่าช่องว่างที่เกี่ยวข้องจะแสดงเป็น "(โปรดเลือก)" ในการเลือก UI

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